mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
1. implement instanceof, in, delete operator
2. VariableDeclaratorNode does not affect execute result 3. optimize Object get, set in interpreter Signed-off-by: seonghyun kim <sh8281.kim@samsung.com>
This commit is contained in:
parent
b2ea88b251
commit
11e625f373
26 changed files with 386 additions and 114 deletions
|
|
@ -47,6 +47,8 @@ class Node;
|
|||
F(BinaryLeftShift, 1, 2) \
|
||||
F(BinarySignedRightShift, 1, 2) \
|
||||
F(BinaryUnsignedRightShift, 1, 2) \
|
||||
F(BinaryInOperation, 1, 2) \
|
||||
F(BinaryInstanceOfOperation, 1, 2) \
|
||||
F(CreateObject, 1, 0) \
|
||||
F(CreateArray, 1, 0) \
|
||||
F(GetObject, 1, 2) \
|
||||
|
|
@ -63,6 +65,7 @@ class Node;
|
|||
F(UnaryNot, 1, 1) \
|
||||
F(UnaryBitwiseNot, 1, 1) \
|
||||
F(UnaryTypeof, 1, 1) \
|
||||
F(UnaryDelete, 1, 1) \
|
||||
F(Jump, 0, 0) \
|
||||
F(JumpComplexCase, 0, 0) \
|
||||
F(JumpIfTrue, 0, 0) \
|
||||
|
|
@ -79,6 +82,7 @@ class Node;
|
|||
F(LoadRegexp, 1, 0) \
|
||||
F(CallNativeFunction, 0, 0) \
|
||||
F(CallEvalFunction, 0, 0) \
|
||||
F(ResetExecuteResult, 0, 0) \
|
||||
F(End, 0, 0)
|
||||
|
||||
enum Opcode {
|
||||
|
|
@ -526,6 +530,8 @@ DEFINE_BINARY_OPERATION(BitwiseXor, "bitwise Xor");
|
|||
DEFINE_BINARY_OPERATION(LeftShift, "left shift");
|
||||
DEFINE_BINARY_OPERATION(SignedRightShift, "signed right shift");
|
||||
DEFINE_BINARY_OPERATION(UnsignedRightShift, "unsigned right shift");
|
||||
DEFINE_BINARY_OPERATION(InOperation, "in operation");
|
||||
DEFINE_BINARY_OPERATION(InstanceOfOperation, "instance of");
|
||||
|
||||
|
||||
class CreateObject : public ByteCode {
|
||||
|
|
@ -606,7 +612,21 @@ public:
|
|||
};
|
||||
|
||||
|
||||
typedef Vector<std::pair<ObjectStructure*, size_t>, gc_malloc_ignore_off_page_allocator<std::pair<ObjectStructure*, size_t>>> ObjectStructureChain;
|
||||
struct ObjectStructureChainItem : public gc {
|
||||
ObjectStructure* m_objectStructure;
|
||||
size_t m_version;
|
||||
bool operator==(const ObjectStructureChainItem& item) const
|
||||
{
|
||||
return m_objectStructure == item.m_objectStructure && m_version == item.m_version;
|
||||
}
|
||||
|
||||
bool operator!=(const ObjectStructureChainItem& item) const
|
||||
{
|
||||
return !operator==(item);
|
||||
}
|
||||
};
|
||||
|
||||
typedef Vector<ObjectStructureChainItem, gc_malloc_ignore_off_page_allocator<ObjectStructureChainItem>> ObjectStructureChain;
|
||||
|
||||
struct GetObjectInlineCacheData {
|
||||
GetObjectInlineCacheData()
|
||||
|
|
@ -875,6 +895,28 @@ public:
|
|||
#endif
|
||||
};
|
||||
|
||||
class UnaryDelete : public ByteCode {
|
||||
public:
|
||||
UnaryDelete(const ByteCodeLOC& loc, const size_t& registerIndex0, const size_t& registerIndex1, AtomicString name)
|
||||
: ByteCode(Opcode::UnaryDeleteOpcode, loc)
|
||||
, m_registerIndex0(registerIndex0)
|
||||
, m_registerIndex1(registerIndex1)
|
||||
, m_id(name)
|
||||
{
|
||||
}
|
||||
|
||||
size_t m_registerIndex0;
|
||||
size_t m_registerIndex1;
|
||||
AtomicString m_id;
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void dump()
|
||||
{
|
||||
printf("unary delete r%d r%d %s", (int)m_registerIndex0, (int)m_registerIndex1, m_id.string()->toUTF8StringData().data());
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class Jump : public ByteCode {
|
||||
public:
|
||||
Jump(const ByteCodeLOC& loc, size_t pos = SIZE_MAX)
|
||||
|
|
@ -1236,6 +1278,21 @@ public:
|
|||
NativeFunctionPointer m_fn;
|
||||
};
|
||||
|
||||
class ResetExecuteResult : public ByteCode {
|
||||
public:
|
||||
ResetExecuteResult(const ByteCodeLOC& loc)
|
||||
: ByteCode(Opcode::ResetExecuteResultOpcode, loc)
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
virtual void dump()
|
||||
{
|
||||
printf("reset execute result");
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
class End : public ByteCode {
|
||||
public:
|
||||
End(const ByteCodeLOC& loc)
|
||||
|
|
|
|||
|
|
@ -782,7 +782,10 @@ void ByteCodeInterpreter::interpret(ExecutionState& state, CodeBlock* codeBlock,
|
|||
Object* obj = data->m_object;
|
||||
for (size_t i = 0; i < data->m_hiddenClassChain.size(); i++) {
|
||||
auto hc = data->m_hiddenClassChain[i];
|
||||
if (hc.first != obj->structure() && hc.second == obj->structure()->version()) {
|
||||
ObjectStructureChainItem testItem;
|
||||
testItem.m_objectStructure = obj->structure();
|
||||
testItem.m_version = obj->structure()->version();
|
||||
if (hc != testItem) {
|
||||
shouldUpdateEnumerateObjectData = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -823,6 +826,34 @@ void ByteCodeInterpreter::interpret(ExecutionState& state, CodeBlock* codeBlock,
|
|||
NEXT_INSTRUCTION();
|
||||
}
|
||||
|
||||
UnaryDeleteOpcodeLbl : {
|
||||
UnaryDelete* code = (UnaryDelete*)currentCode;
|
||||
if (code->m_id.string()->length()) {
|
||||
registerFile[code->m_registerIndex0] = Value(env->deleteBinding(state, code->m_id));
|
||||
} else {
|
||||
const Value& o = registerFile[code->m_registerIndex0];
|
||||
const Value& p = registerFile[code->m_registerIndex1];
|
||||
registerFile[code->m_registerIndex0] = Value(o.toObject(state)->deleteOwnProperty(state, ObjectPropertyName(state, p)));
|
||||
}
|
||||
ADD_PROGRAM_COUNTER(UnaryDelete);
|
||||
NEXT_INSTRUCTION();
|
||||
}
|
||||
|
||||
BinaryInOperationOpcodeLbl : {
|
||||
BinaryInOperation* code = (BinaryInOperation*)currentCode;
|
||||
auto result = registerFile[code->m_srcIndex1].toObject(state)->get(state, ObjectPropertyName(state, registerFile[code->m_srcIndex0]));
|
||||
registerFile[code->m_srcIndex0] = Value(result.hasValue());
|
||||
ADD_PROGRAM_COUNTER(BinaryInOperation);
|
||||
NEXT_INSTRUCTION();
|
||||
}
|
||||
|
||||
BinaryInstanceOfOperationOpcodeLbl : {
|
||||
BinaryInstanceOfOperation* code = (BinaryInstanceOfOperation*)currentCode;
|
||||
registerFile[code->m_srcIndex0] = instanceOfOperation(state, registerFile[code->m_srcIndex0], registerFile[code->m_srcIndex1]);
|
||||
ADD_PROGRAM_COUNTER(BinaryInstanceOfOperation);
|
||||
NEXT_INSTRUCTION();
|
||||
}
|
||||
|
||||
LoadByGlobalNameOpcodeLbl : {
|
||||
LoadByGlobalName* code = (LoadByGlobalName*)currentCode;
|
||||
GlobalObject* g = state.context()->globalObject();
|
||||
|
|
@ -856,6 +887,12 @@ void ByteCodeInterpreter::interpret(ExecutionState& state, CodeBlock* codeBlock,
|
|||
NEXT_INSTRUCTION();
|
||||
}
|
||||
|
||||
ResetExecuteResultOpcodeLbl : {
|
||||
registerFile[0] = Value();
|
||||
ADD_PROGRAM_COUNTER(ResetExecuteResult);
|
||||
NEXT_INSTRUCTION();
|
||||
}
|
||||
|
||||
} catch (const Value& v) {
|
||||
if (state.context()->m_sandBoxStack.size()) {
|
||||
SandBox* sb = state.context()->m_sandBoxStack.back();
|
||||
|
|
@ -1035,6 +1072,31 @@ Value ByteCodeInterpreter::newOperation(ExecutionState& state, const Value& call
|
|||
return receiver;
|
||||
}
|
||||
|
||||
Value ByteCodeInterpreter::instanceOfOperation(ExecutionState& state, const Value& left, const Value& right)
|
||||
{
|
||||
if (!right.isFunction()) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_InstanceOf_NotFunction);
|
||||
}
|
||||
if (left.isObject()) {
|
||||
FunctionObject* C = right.asFunction();
|
||||
// while (C->isBoundFunc())
|
||||
// C = C->codeBlock()->peekCode<CallBoundFunction>(0)->m_boundTargetFunction;
|
||||
Value P = C->getFunctionPrototype(state);
|
||||
Value O = left.asObject()->getPrototype(state);
|
||||
if (P.isObject()) {
|
||||
while (!O.isUndefinedOrNull()) {
|
||||
if (P == O) {
|
||||
return Value(true);
|
||||
}
|
||||
O = O.asObject()->getPrototype(state);
|
||||
}
|
||||
} else {
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::TypeError, errorMessage_InstanceOf_InvalidPrototypeProperty);
|
||||
}
|
||||
}
|
||||
return Value(false);
|
||||
}
|
||||
|
||||
inline bool ByteCodeInterpreter::abstractRelationalComparison(ExecutionState& state, const Value& left, const Value& right, bool leftFirst)
|
||||
{
|
||||
// consume very fast case
|
||||
|
|
@ -1114,6 +1176,9 @@ ALWAYS_INLINE std::pair<bool, Value> ByteCodeInterpreter::getObjectPrecomputedCa
|
|||
{
|
||||
Object* targetObj = obj;
|
||||
unsigned currentCacheIndex = 0;
|
||||
ObjectStructureChainItem testItem;
|
||||
testItem.m_objectStructure = obj->structure();
|
||||
testItem.m_version = obj->structure()->version();
|
||||
const size_t cacheFillCount = inlineCache.m_cache.size();
|
||||
for (; currentCacheIndex < cacheFillCount; currentCacheIndex++) {
|
||||
const GetObjectInlineCacheData& data = inlineCache.m_cache[currentCacheIndex];
|
||||
|
|
@ -1121,7 +1186,9 @@ ALWAYS_INLINE std::pair<bool, Value> ByteCodeInterpreter::getObjectPrecomputedCa
|
|||
const size_t& cachedIndex = data.m_cachedIndex;
|
||||
const size_t cSiz = cachedHiddenClassChain->size() - 1;
|
||||
for (size_t i = 0; i < cSiz; i++) {
|
||||
if (UNLIKELY((*cachedHiddenClassChain)[i].first != obj->structure() || (*cachedHiddenClassChain)[i].second != obj->structure()->version())) {
|
||||
testItem.m_objectStructure = obj->structure();
|
||||
testItem.m_version = obj->structure()->version();
|
||||
if (UNLIKELY((*cachedHiddenClassChain)[i] != testItem)) {
|
||||
return getObjectPrecomputedCaseOperationCacheMiss(state, targetObj, name, inlineCache);
|
||||
}
|
||||
const Value& proto = obj->getPrototype(state);
|
||||
|
|
@ -1131,7 +1198,10 @@ ALWAYS_INLINE std::pair<bool, Value> ByteCodeInterpreter::getObjectPrecomputedCa
|
|||
return getObjectPrecomputedCaseOperationCacheMiss(state, targetObj, name, inlineCache);
|
||||
}
|
||||
}
|
||||
if (LIKELY((*cachedHiddenClassChain)[cSiz].first == obj->structure() && (*cachedHiddenClassChain)[cSiz].second == obj->structure()->version())) {
|
||||
|
||||
testItem.m_objectStructure = obj->structure();
|
||||
testItem.m_version = obj->structure()->version();
|
||||
if (LIKELY((*cachedHiddenClassChain)[cSiz] == testItem)) {
|
||||
if (LIKELY(cachedIndex != SIZE_MAX)) {
|
||||
return std::make_pair(true, obj->getOwnPropertyUtilForObject(state, cachedIndex, targetObj));
|
||||
} else {
|
||||
|
|
@ -1160,8 +1230,13 @@ std::pair<bool, Value> ByteCodeInterpreter::getObjectPrecomputedCaseOperationCac
|
|||
ASSERT(&inlineCache.m_cache[0] == &inlineCache.m_cache[0]);
|
||||
ObjectStructureChain* cachedHiddenClassChain = &inlineCache.m_cache[0].m_cachedhiddenClassChain;
|
||||
size_t* cachedHiddenClassIndex = &inlineCache.m_cache[0].m_cachedIndex;
|
||||
|
||||
ObjectStructureChainItem newItem;
|
||||
while (true) {
|
||||
cachedHiddenClassChain->push_back(std::make_pair(obj->structure(), obj->structure()->version()));
|
||||
newItem.m_objectStructure = obj->structure();
|
||||
newItem.m_version = obj->structure()->version();
|
||||
|
||||
cachedHiddenClassChain->push_back(newItem);
|
||||
size_t idx = obj->structure()->findProperty(state, name);
|
||||
if (idx != SIZE_MAX) {
|
||||
*cachedHiddenClassIndex = idx;
|
||||
|
|
@ -1184,7 +1259,12 @@ std::pair<bool, Value> ByteCodeInterpreter::getObjectPrecomputedCaseOperationCac
|
|||
ALWAYS_INLINE void ByteCodeInterpreter::setObjectPreComputedCaseOperation(ExecutionState& state, Object* obj, const PropertyName& name, const Value& value, SetObjectInlineCache& inlineCache)
|
||||
{
|
||||
Object* originalObject = obj;
|
||||
if (inlineCache.m_cachedIndex != SIZE_MAX && inlineCache.m_cachedhiddenClassChain[0].first == obj->structure() && inlineCache.m_cachedhiddenClassChain[0].second == obj->structure()->version()) {
|
||||
|
||||
ObjectStructureChainItem testItem;
|
||||
testItem.m_objectStructure = obj->structure();
|
||||
testItem.m_version = obj->structure()->version();
|
||||
|
||||
if (inlineCache.m_cachedIndex != SIZE_MAX && inlineCache.m_cachedhiddenClassChain[0] == testItem) {
|
||||
ASSERT(inlineCache.m_cachedhiddenClassChain.size() == 1);
|
||||
// cache hit!
|
||||
obj->setOwnPropertyThrowsExceptionWhenStrictMode(state, inlineCache.m_cachedIndex, value);
|
||||
|
|
@ -1193,7 +1273,7 @@ ALWAYS_INLINE void ByteCodeInterpreter::setObjectPreComputedCaseOperation(Execut
|
|||
int cSiz = inlineCache.m_cachedhiddenClassChain.size();
|
||||
bool miss = false;
|
||||
for (int i = 0; i < cSiz - 1; i++) {
|
||||
if (inlineCache.m_cachedhiddenClassChain[i].first != obj->structure()) {
|
||||
if (inlineCache.m_cachedhiddenClassChain[i].m_objectStructure != obj->structure()) {
|
||||
miss = true;
|
||||
break;
|
||||
} else {
|
||||
|
|
@ -1206,7 +1286,7 @@ ALWAYS_INLINE void ByteCodeInterpreter::setObjectPreComputedCaseOperation(Execut
|
|||
}
|
||||
}
|
||||
if (!miss) {
|
||||
if (inlineCache.m_cachedhiddenClassChain[cSiz - 1].first == obj->structure()) {
|
||||
if (inlineCache.m_cachedhiddenClassChain[cSiz - 1].m_objectStructure == obj->structure()) {
|
||||
// cache hit!
|
||||
obj = originalObject;
|
||||
ASSERT(!obj->structure()->isStructureWithFastAccess());
|
||||
|
|
@ -1230,8 +1310,13 @@ void ByteCodeInterpreter::setObjectPreComputedCaseOperationCacheMiss(ExecutionSt
|
|||
size_t idx = obj->structure()->findProperty(state, name);
|
||||
if (idx != SIZE_MAX) {
|
||||
// own property
|
||||
ObjectStructureChainItem newItem;
|
||||
newItem.m_objectStructure = obj->structure();
|
||||
newItem.m_version = obj->structure()->version();
|
||||
|
||||
inlineCache.m_cachedIndex = idx;
|
||||
inlineCache.m_cachedhiddenClassChain.push_back(std::make_pair(obj->structure(), obj->structure()->version()));
|
||||
inlineCache.m_cachedhiddenClassChain.push_back(newItem);
|
||||
|
||||
obj->setOwnPropertyThrowsExceptionWhenStrictMode(state, inlineCache.m_cachedIndex, value);
|
||||
} else {
|
||||
Object* orgObject = obj;
|
||||
|
|
@ -1240,7 +1325,11 @@ void ByteCodeInterpreter::setObjectPreComputedCaseOperationCacheMiss(ExecutionSt
|
|||
orgObject->setThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, name), value, orgObject);
|
||||
return;
|
||||
}
|
||||
inlineCache.m_cachedhiddenClassChain.push_back(std::make_pair(obj->structure(), obj->structure()->version()));
|
||||
ASSERT(obj->structure()->version() == 0);
|
||||
ObjectStructureChainItem newItem;
|
||||
newItem.m_objectStructure = obj->structure();
|
||||
newItem.m_version = obj->structure()->version();
|
||||
inlineCache.m_cachedhiddenClassChain.push_back(newItem);
|
||||
Value proto = obj->getPrototype(state);
|
||||
while (proto.isObject()) {
|
||||
obj = proto.asObject();
|
||||
|
|
@ -1249,7 +1338,9 @@ void ByteCodeInterpreter::setObjectPreComputedCaseOperationCacheMiss(ExecutionSt
|
|||
orgObject->setThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, name), value, orgObject);
|
||||
return;
|
||||
}
|
||||
inlineCache.m_cachedhiddenClassChain.push_back(std::make_pair(obj->structure(), obj->structure()->version()));
|
||||
newItem.m_objectStructure = obj->structure();
|
||||
newItem.m_version = obj->structure()->version();
|
||||
inlineCache.m_cachedhiddenClassChain.push_back(newItem);
|
||||
proto = obj->getPrototype(state);
|
||||
}
|
||||
bool s = orgObject->set(state, ObjectPropertyName(state, name), value, obj);
|
||||
|
|
@ -1285,7 +1376,11 @@ EnumerateObjectData* ByteCodeInterpreter::executeEnumerateObject(ExecutionState&
|
|||
}
|
||||
return true;
|
||||
});
|
||||
data->m_hiddenClassChain.push_back(std::make_pair(target.asObject()->structure(), target.asObject()->structure()->version()));
|
||||
ObjectStructureChainItem newItem;
|
||||
newItem.m_objectStructure = target.asObject()->structure();
|
||||
newItem.m_version = target.asObject()->structure()->version();
|
||||
|
||||
data->m_hiddenClassChain.push_back(newItem);
|
||||
|
||||
std::unordered_set<String*, std::hash<String*>, std::equal_to<String*>, gc_malloc_ignore_off_page_allocator<String*>> keyStringSet;
|
||||
|
||||
|
|
@ -1300,7 +1395,9 @@ EnumerateObjectData* ByteCodeInterpreter::executeEnumerateObject(ExecutionState&
|
|||
return true;
|
||||
});
|
||||
}
|
||||
data->m_hiddenClassChain.push_back(std::make_pair(target.asObject()->structure(), target.asObject()->structure()->version()));
|
||||
newItem.m_objectStructure = target.asObject()->structure();
|
||||
newItem.m_version = target.asObject()->structure()->version();
|
||||
data->m_hiddenClassChain.push_back(newItem);
|
||||
target = target.asObject()->getPrototype(state);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ public:
|
|||
static Value plusSlowCase(ExecutionState& state, const Value& a, const Value& b);
|
||||
static Value modOperation(ExecutionState& state, const Value& left, const Value& right);
|
||||
static Value newOperation(ExecutionState& state, const Value& callee, size_t argc, Value* argv);
|
||||
static Value instanceOfOperation(ExecutionState& state, const Value& left, const Value& right);
|
||||
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-11.8.5
|
||||
static bool abstractRelationalComparisonSlowCase(ExecutionState& state, const Value& left, const Value& right, bool leftFirst);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,18 @@ public:
|
|||
m_right = (ExpressionNode*)right;
|
||||
}
|
||||
|
||||
virtual void generateExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context)
|
||||
{
|
||||
m_left->generateExpressionByteCode(codeBlock, context);
|
||||
m_right->generateExpressionByteCode(codeBlock, context);
|
||||
|
||||
size_t src1 = context->getLastRegisterIndex();
|
||||
context->giveUpRegister();
|
||||
size_t src0 = context->getLastRegisterIndex();
|
||||
|
||||
codeBlock->pushCode(BinaryInOperation(ByteCodeLOC(m_loc.index), src0, src1), context, this);
|
||||
}
|
||||
|
||||
virtual ASTNodeType type() { return ASTNodeType::BinaryExpressionIn; }
|
||||
protected:
|
||||
ExpressionNode* m_left;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,18 @@ public:
|
|||
}
|
||||
|
||||
virtual ASTNodeType type() { return ASTNodeType::BinaryExpressionInstanceOf; }
|
||||
virtual void generateExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context)
|
||||
{
|
||||
m_left->generateExpressionByteCode(codeBlock, context);
|
||||
m_right->generateExpressionByteCode(codeBlock, context);
|
||||
|
||||
size_t src1 = context->getLastRegisterIndex();
|
||||
context->giveUpRegister();
|
||||
size_t src0 = context->getLastRegisterIndex();
|
||||
|
||||
codeBlock->pushCode(BinaryInstanceOfOperation(ByteCodeLOC(m_loc.index), src0, src1), context, this);
|
||||
}
|
||||
|
||||
protected:
|
||||
ExpressionNode* m_left;
|
||||
ExpressionNode* m_right;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,16 @@ public:
|
|||
m_computed = computed;
|
||||
}
|
||||
|
||||
Node* object()
|
||||
{
|
||||
return m_object;
|
||||
}
|
||||
|
||||
Node* property()
|
||||
{
|
||||
return m_property;
|
||||
}
|
||||
|
||||
virtual ASTNodeType type() { return ASTNodeType::MemberExpression; }
|
||||
bool isPreComputedCase()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@ public:
|
|||
ASTScopeContext* scopeContext() { return m_scopeContext; }
|
||||
virtual void generateStatementByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context)
|
||||
{
|
||||
codeBlock->pushCode(ResetExecuteResult(ByteCodeLOC(SIZE_MAX)), context, this);
|
||||
size_t len = m_body.size();
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
m_body[i]->generateStatementByteCode(codeBlock, context);
|
||||
}
|
||||
|
||||
codeBlock->pushCode(End(ByteCodeLOC(SIZE_MAX)), context, this);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,46 @@ public:
|
|||
}
|
||||
|
||||
virtual ASTNodeType type() { return ASTNodeType::UnaryExpressionDelete; }
|
||||
virtual void generateExpressionByteCode(ByteCodeBlock* codeBlock, ByteCodeGenerateContext* context)
|
||||
{
|
||||
size_t base = context->m_baseRegisterCount;
|
||||
if (m_argument->isIdentifier()) {
|
||||
AtomicString name = m_argument->asIdentifier()->name();
|
||||
bool nameCase = false;
|
||||
if (!context->m_codeBlock->canUseIndexedVariableStorage()) {
|
||||
nameCase = true;
|
||||
} else {
|
||||
CodeBlock::IndexedIdentifierInfo info = context->m_codeBlock->indexedIdentifierInfo(name);
|
||||
if (!info.m_isResultSaved) {
|
||||
nameCase = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (nameCase) {
|
||||
codeBlock->pushCode(UnaryDelete(ByteCodeLOC(m_loc.index), context->getRegister(), SIZE_MAX, name), context, this);
|
||||
} else {
|
||||
codeBlock->pushCode(LoadLiteral(ByteCodeLOC(m_loc.index), context->getRegister(), Value(false)), context, this);
|
||||
}
|
||||
} else if (m_argument->isMemberExpression()) {
|
||||
((MemberExpressionNode*)m_argument)->object()->generateExpressionByteCode(codeBlock, context);
|
||||
size_t o = context->getLastRegisterIndex();
|
||||
if (((MemberExpressionNode*)m_argument)->isPreComputedCase())
|
||||
codeBlock->pushCode(LoadLiteral(ByteCodeLOC(m_loc.index), context->getRegister(), Value(((MemberExpressionNode*)m_argument)->property()->asIdentifier()->name().string())), context, this);
|
||||
else
|
||||
((MemberExpressionNode*)m_argument)->property()->generateExpressionByteCode(codeBlock, context);
|
||||
size_t p = context->getLastRegisterIndex();
|
||||
|
||||
codeBlock->pushCode(UnaryDelete(ByteCodeLOC(m_loc.index), o, p, AtomicString()), context, this);
|
||||
context->giveUpRegister();
|
||||
} else {
|
||||
m_argument->generateExpressionByteCode(codeBlock, context);
|
||||
context->giveUpRegister();
|
||||
codeBlock->pushCode(LoadLiteral(ByteCodeLOC(m_loc.index), context->getRegister(), Value(true)), context, this);
|
||||
}
|
||||
|
||||
ASSERT(base + 1 == context->m_baseRegisterCount);
|
||||
}
|
||||
|
||||
protected:
|
||||
ExpressionNode* m_argument;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,9 +44,11 @@ public:
|
|||
if (!context->m_codeBlock->hasName(name))
|
||||
codeBlock->pushCode(DeclareVarVariable(ByteCodeLOC(m_loc.index), name), context, this);
|
||||
if (m_init) {
|
||||
context->getRegister();
|
||||
m_init->generateExpressionByteCode(codeBlock, context);
|
||||
m_id->generateStoreByteCode(codeBlock, context);
|
||||
context->giveUpRegister();
|
||||
context->giveUpRegister();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3763,7 +3763,7 @@ public:
|
|||
this->context->isAssignmentTarget = false;
|
||||
this->context->isBindingElement = false;
|
||||
|
||||
if (exprOld->isIdentifier()) {
|
||||
if (this->context->strict && exprOld->isIdentifier()) {
|
||||
this->tolerateError(Messages::StrictDelete);
|
||||
}
|
||||
} else if (this->matchKeyword(Void)) {
|
||||
|
|
@ -3911,7 +3911,7 @@ public:
|
|||
while ((stack.size() > 2) && (prec <= ((ScannerResult*)stack[stack.size() - 2])->prec)) {
|
||||
right = (Node*)stack.back();
|
||||
stack.pop_back();
|
||||
PunctuatorsKind operator_ = ((ScannerResult*)stack.back())->valuePunctuatorsKind;
|
||||
ScannerResult* operator_ = ((ScannerResult*)stack.back());
|
||||
stack.pop_back();
|
||||
left = (Node*)stack.back();
|
||||
stack.pop_back();
|
||||
|
|
@ -3934,7 +3934,7 @@ public:
|
|||
markers.pop_back();
|
||||
while (i > 1) {
|
||||
MetaNode node = this->startNode(markers.back());
|
||||
expr = this->finalize(node, finishBinaryExpression((Node*)stack[i - 2], expr, ((ScannerResult*)stack[i - 1])->valuePunctuatorsKind));
|
||||
expr = this->finalize(node, finishBinaryExpression((Node*)stack[i - 2], expr, ((ScannerResult*)stack[i - 1])));
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -3942,70 +3942,74 @@ public:
|
|||
return expr;
|
||||
}
|
||||
|
||||
Node* finishBinaryExpression(Node* left, Node* right, PunctuatorsKind oper)
|
||||
Node* finishBinaryExpression(Node* left, Node* right, ScannerResult* token)
|
||||
{
|
||||
// Additive Operators
|
||||
Node* nd;
|
||||
if (oper == Plus)
|
||||
nd = new BinaryExpressionPlusNode(left, right);
|
||||
else if (oper == Minus)
|
||||
nd = new BinaryExpressionMinusNode(left, right);
|
||||
if (token->type == Token::PunctuatorToken) {
|
||||
PunctuatorsKind oper = token->valuePunctuatorsKind;
|
||||
// Additive Operators
|
||||
if (oper == Plus)
|
||||
nd = new BinaryExpressionPlusNode(left, right);
|
||||
else if (oper == Minus)
|
||||
nd = new BinaryExpressionMinusNode(left, right);
|
||||
|
||||
// Bitwise Shift Operators
|
||||
else if (oper == LeftShift)
|
||||
nd = new BinaryExpressionLeftShiftNode(left, right);
|
||||
else if (oper == RightShift)
|
||||
nd = new BinaryExpressionSignedRightShiftNode(left, right);
|
||||
else if (oper == UnsignedRightShift)
|
||||
nd = new BinaryExpressionUnsignedRightShiftNode(left, right);
|
||||
// Bitwise Shift Operators
|
||||
else if (oper == LeftShift)
|
||||
nd = new BinaryExpressionLeftShiftNode(left, right);
|
||||
else if (oper == RightShift)
|
||||
nd = new BinaryExpressionSignedRightShiftNode(left, right);
|
||||
else if (oper == UnsignedRightShift)
|
||||
nd = new BinaryExpressionUnsignedRightShiftNode(left, right);
|
||||
|
||||
// Multiplicative Operators
|
||||
else if (oper == Multiply)
|
||||
nd = new BinaryExpressionMultiplyNode(left, right);
|
||||
else if (oper == Divide)
|
||||
nd = new BinaryExpressionDivisionNode(left, right);
|
||||
else if (oper == Mod)
|
||||
nd = new BinaryExpressionModNode(left, right);
|
||||
// Multiplicative Operators
|
||||
else if (oper == Multiply)
|
||||
nd = new BinaryExpressionMultiplyNode(left, right);
|
||||
else if (oper == Divide)
|
||||
nd = new BinaryExpressionDivisionNode(left, right);
|
||||
else if (oper == Mod)
|
||||
nd = new BinaryExpressionModNode(left, right);
|
||||
|
||||
// Relational Operators
|
||||
else if (oper == LeftInequality)
|
||||
nd = new BinaryExpressionLessThanNode(left, right);
|
||||
else if (oper == RightInequality)
|
||||
nd = new BinaryExpressionGreaterThanNode(left, right);
|
||||
else if (oper == LeftInequalityEqual)
|
||||
nd = new BinaryExpressionLessThanOrEqualNode(left, right);
|
||||
else if (oper == RightInequalityEqual)
|
||||
nd = new BinaryExpressionGreaterThanOrEqualNode(left, right);
|
||||
// Relational Operators
|
||||
else if (oper == LeftInequality)
|
||||
nd = new BinaryExpressionLessThanNode(left, right);
|
||||
else if (oper == RightInequality)
|
||||
nd = new BinaryExpressionGreaterThanNode(left, right);
|
||||
else if (oper == LeftInequalityEqual)
|
||||
nd = new BinaryExpressionLessThanOrEqualNode(left, right);
|
||||
else if (oper == RightInequalityEqual)
|
||||
nd = new BinaryExpressionGreaterThanOrEqualNode(left, right);
|
||||
|
||||
// Equality Operators
|
||||
else if (oper == Equal)
|
||||
nd = new BinaryExpressionEqualNode(left, right);
|
||||
else if (oper == NotEqual)
|
||||
nd = new BinaryExpressionNotEqualNode(left, right);
|
||||
else if (oper == StrictEqual)
|
||||
nd = new BinaryExpressionStrictEqualNode(left, right);
|
||||
else if (oper == NotStrictEqual)
|
||||
nd = new BinaryExpressionNotStrictEqualNode(left, right);
|
||||
|
||||
// Binary Bitwise Operator
|
||||
else if (oper == BitwiseAnd)
|
||||
nd = new BinaryExpressionBitwiseAndNode(left, right);
|
||||
else if (oper == BitwiseXor)
|
||||
nd = new BinaryExpressionBitwiseXorNode(left, right);
|
||||
else if (oper == BitwiseOr)
|
||||
nd = new BinaryExpressionBitwiseOrNode(left, right);
|
||||
else if (oper == LogicalOr)
|
||||
nd = new BinaryExpressionLogicalOrNode(left, right);
|
||||
else if (oper == LogicalAnd)
|
||||
nd = new BinaryExpressionLogicalAndNode(left, right);
|
||||
else if (oper == InPunctuator)
|
||||
nd = new BinaryExpressionInNode(left, right);
|
||||
else if (oper == InstanceOfPunctuator)
|
||||
nd = new BinaryExpressionInstanceOfNode(left, right);
|
||||
// TODO
|
||||
else
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
// Equality Operators
|
||||
else if (oper == Equal)
|
||||
nd = new BinaryExpressionEqualNode(left, right);
|
||||
else if (oper == NotEqual)
|
||||
nd = new BinaryExpressionNotEqualNode(left, right);
|
||||
else if (oper == StrictEqual)
|
||||
nd = new BinaryExpressionStrictEqualNode(left, right);
|
||||
else if (oper == NotStrictEqual)
|
||||
nd = new BinaryExpressionNotStrictEqualNode(left, right);
|
||||
|
||||
// Binary Bitwise Operator
|
||||
else if (oper == BitwiseAnd)
|
||||
nd = new BinaryExpressionBitwiseAndNode(left, right);
|
||||
else if (oper == BitwiseXor)
|
||||
nd = new BinaryExpressionBitwiseXorNode(left, right);
|
||||
else if (oper == BitwiseOr)
|
||||
nd = new BinaryExpressionBitwiseOrNode(left, right);
|
||||
else if (oper == LogicalOr)
|
||||
nd = new BinaryExpressionLogicalOrNode(left, right);
|
||||
else if (oper == LogicalAnd)
|
||||
nd = new BinaryExpressionLogicalAndNode(left, right);
|
||||
else
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
} else {
|
||||
if (token->valueKeywordKind == KeywordKind::In)
|
||||
nd = new BinaryExpressionInNode(left, right);
|
||||
else if (token->valueKeywordKind == KeywordKind::InstanceofKeyword)
|
||||
nd = new BinaryExpressionInstanceOfNode(left, right);
|
||||
else
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
}
|
||||
return nd;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ bool ArrayObject::defineOwnProperty(ExecutionState& state, const ObjectPropertyN
|
|||
return Object::defineOwnProperty(state, P, desc);
|
||||
}
|
||||
|
||||
void ArrayObject::deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
||||
bool ArrayObject::deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
||||
{
|
||||
if (LIKELY(isFastModeArray())) {
|
||||
uint32_t idx;
|
||||
|
|
@ -54,7 +54,7 @@ void ArrayObject::deleteOwnProperty(ExecutionState& state, const ObjectPropertyN
|
|||
ASSERT(len == getLength(state));
|
||||
if (idx < len) {
|
||||
m_fastModeData[idx] = Value(Value::EmptyValue);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ public:
|
|||
|
||||
virtual ObjectGetResult getOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual bool defineOwnProperty(ExecutionState& state, const ObjectPropertyName& P, const ObjectPropertyDescriptor& desc) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual void deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual bool deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual void enumeration(ExecutionState& state, std::function<bool(const ObjectPropertyName&, const ObjectStructurePropertyDescriptor& desc)> callback) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual uint32_t length(ExecutionState& state)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,6 +40,18 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
bool deleteBinding(ExecutionState& state, const AtomicString& name)
|
||||
{
|
||||
LexicalEnvironment* env = this;
|
||||
while (env) {
|
||||
if (LIKELY(env->record()->hasBinding(state, name).m_index != SIZE_MAX)) {
|
||||
return env->record()->deleteBinding(state, name);
|
||||
}
|
||||
env = env->outerEnvironment();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
EnvironmentRecord* m_record;
|
||||
LexicalEnvironment* m_outerEnvironment;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,16 @@ void GlobalEnvironmentRecord::setMutableBinding(ExecutionState& state, const Ato
|
|||
m_globalObject->setThrowsExceptionWhenStrictMode(state, name, V, m_globalObject);
|
||||
}
|
||||
|
||||
bool GlobalEnvironmentRecord::deleteBinding(ExecutionState& state, const AtomicString& name)
|
||||
{
|
||||
return m_globalObject->deleteOwnProperty(state, name);
|
||||
}
|
||||
|
||||
EnvironmentRecord::BindingSlot GlobalEnvironmentRecord::hasBinding(ExecutionState& state, const AtomicString& atomicName)
|
||||
{
|
||||
return EnvironmentRecord::BindingSlot(this, m_globalObject->findPropertyIndex(state, atomicName));
|
||||
}
|
||||
|
||||
void DeclarativeEnvironmentRecordNotIndexded::createMutableBinding(ExecutionState& state, const AtomicString& name, bool canDelete)
|
||||
{
|
||||
ASSERT(canDelete == false);
|
||||
|
|
|
|||
|
|
@ -169,6 +169,11 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual bool deleteBinding(ExecutionState& state, const AtomicString& name)
|
||||
{
|
||||
return m_bindingObject->deleteOwnProperty(state, name);
|
||||
}
|
||||
|
||||
protected:
|
||||
Object* m_bindingObject;
|
||||
};
|
||||
|
|
@ -192,6 +197,8 @@ public:
|
|||
virtual void createMutableBinding(ExecutionState& state, const AtomicString& name, bool canDelete = false);
|
||||
virtual GetBindingValueResult getBindingValue(ExecutionState& state, const AtomicString& name);
|
||||
virtual void setMutableBinding(ExecutionState& state, const AtomicString& name, const Value& V);
|
||||
virtual bool deleteBinding(ExecutionState& state, const AtomicString& name);
|
||||
virtual BindingSlot hasBinding(ExecutionState& state, const AtomicString& atomicName);
|
||||
|
||||
CodeBlock* globalCodeBlock()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ const char* errorMessage_Get_FromNull = "Cannot get property '%s' of null";
|
|||
const char* errorMessage_Set_ToUndefined = "Cannot set property '%s' of undefined";
|
||||
const char* errorMessage_Set_ToNull = "Cannot set property '%s' of null";
|
||||
const char* errorMessage_New_NotConstructor = "%s is not a constructor";
|
||||
const char* errorMessage_InstanceOf_NotFunction = "Invalid operand to 'instanceof': Callee is not a function object";
|
||||
const char* errorMessage_InstanceOf_InvalidPrototypeProperty = "instanceof called on an object with an invalid prototype property";
|
||||
const char* errorMessage_ArgumentsOrCaller_InStrictMode = "'caller' and 'arguments' are restricted function properties and cannot be accessed in this context.";
|
||||
const char* errorMessage_GlobalObject_ThisUndefinedOrNull = "%s: this value is undefined or null";
|
||||
const char* errorMessage_GlobalObject_ThisNotObject = "%s: this value is not an object";
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ extern const char* errorMessage_Get_FromNull;
|
|||
extern const char* errorMessage_Set_ToUndefined;
|
||||
extern const char* errorMessage_Set_ToNull;
|
||||
extern const char* errorMessage_New_NotConstructor;
|
||||
extern const char* errorMessage_InstanceOf_NotFunction;
|
||||
extern const char* errorMessage_InstanceOf_InvalidPrototypeProperty;
|
||||
extern const char* errorMessage_ArgumentsOrCaller_InStrictMode;
|
||||
extern const char* errorMessage_GlobalObject_ThisUndefinedOrNull;
|
||||
extern const char* errorMessage_GlobalObject_ThisNotObject;
|
||||
|
|
|
|||
|
|
@ -186,22 +186,22 @@ void GlobalObject::installOthers(ExecutionState& state)
|
|||
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().parseInt),
|
||||
ObjectPropertyDescriptor(new FunctionObject(state,
|
||||
NativeFunctionInfo(state.context()->staticStrings().parseInt, builtinParseInt, 2, nullptr, NativeFunctionInfo::Strict), false),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
NativeFunctionInfo(state.context()->staticStrings().parseInt, builtinParseInt, 2, nullptr, NativeFunctionInfo::Strict), false),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
#ifdef ESCARGOT_SHELL
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().print),
|
||||
ObjectPropertyDescriptor(new FunctionObject(state,
|
||||
NativeFunctionInfo(state.context()->staticStrings().print, builtinPrint, 1, nullptr, NativeFunctionInfo::Strict), false),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::AllPresent)));
|
||||
NativeFunctionInfo(state.context()->staticStrings().print, builtinPrint, 1, nullptr, NativeFunctionInfo::Strict), false),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::AllPresent)));
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().load),
|
||||
ObjectPropertyDescriptor(new FunctionObject(state,
|
||||
NativeFunctionInfo(state.context()->staticStrings().load, builtinLoad, 1, nullptr, NativeFunctionInfo::Strict), false),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::AllPresent)));
|
||||
NativeFunctionInfo(state.context()->staticStrings().load, builtinLoad, 1, nullptr, NativeFunctionInfo::Strict), false),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::AllPresent)));
|
||||
#endif
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().gc),
|
||||
ObjectPropertyDescriptor(new FunctionObject(state,
|
||||
NativeFunctionInfo(state.context()->staticStrings().gc, builtinGc, 0, nullptr, NativeFunctionInfo::Strict), false),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::AllPresent)));
|
||||
NativeFunctionInfo(state.context()->staticStrings().gc, builtinGc, 0, nullptr, NativeFunctionInfo::Strict), false),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::AllPresent)));
|
||||
|
||||
#ifdef PROFILE_BDWGC
|
||||
AtomicString dumpBackTrace(state, "dumpBackTrace");
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class FunctionObject;
|
|||
class GlobalObject : public Object {
|
||||
public:
|
||||
friend class ByteCodeInterpreter;
|
||||
friend class GlobalEnvironmentRecord;
|
||||
|
||||
GlobalObject(ExecutionState& state)
|
||||
: Object(state, ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER, false)
|
||||
|
|
|
|||
|
|
@ -209,22 +209,22 @@ void GlobalObject::installDate(ExecutionState& state)
|
|||
|
||||
m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().getTime),
|
||||
ObjectPropertyDescriptor(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().getTime, builtinDateGetTime, 0, nullptr, NativeFunctionInfo::Strict)),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().valueOf),
|
||||
ObjectPropertyDescriptor(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().valueOf, builtinDateValueOf, 0, nullptr, NativeFunctionInfo::Strict)),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toString),
|
||||
ObjectPropertyDescriptor(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinDateToString, 0, nullptr, NativeFunctionInfo::Strict)),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().setTime),
|
||||
ObjectPropertyDescriptor(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().setTime, builtinDateSetTime, 1, nullptr, NativeFunctionInfo::Strict)),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
|
||||
|
||||
#define DATE_DEFINE_GETTER(dname) \
|
||||
m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().get##dname), \
|
||||
#define DATE_DEFINE_GETTER(dname) \
|
||||
m_datePrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().get##dname), \
|
||||
ObjectPropertyDescriptor(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().get##dname, builtinDateGet##dname, 0, nullptr, NativeFunctionInfo::Strict)), \
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
|
||||
DATE_DEFINE_GETTER(Date);
|
||||
DATE_DEFINE_GETTER(Day);
|
||||
|
|
|
|||
|
|
@ -88,17 +88,17 @@ void GlobalObject::installError(ExecutionState& state)
|
|||
m_errorPrototype->defineOwnPropertyThrowsException(state, state.context()->staticStrings().toString, ObjectPropertyDescriptor(errorToStringFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
|
||||
// m_##name##Error->defineAccessorProperty(strings->prototype.string(), ESVMInstance::currentInstance()->functionPrototypeAccessorData(), false, false, false);
|
||||
#define DEFINE_ERROR(errorname, bname) \
|
||||
m_##errorname##Error = new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().bname##Error, builtinErrorConstructor, 1, [](ExecutionState& state, size_t argc, Value* argv) -> Object* { \
|
||||
return new bname##ErrorObject(state, String::emptyString); \
|
||||
})); \
|
||||
m_##errorname##Error->setPrototype(state, m_functionPrototype); \
|
||||
m_##errorname##ErrorPrototype = new ErrorObject(state, String::emptyString); \
|
||||
#define DEFINE_ERROR(errorname, bname) \
|
||||
m_##errorname##Error = new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().bname##Error, builtinErrorConstructor, 1, [](ExecutionState& state, size_t argc, Value* argv) -> Object* { \
|
||||
return new bname##ErrorObject(state, String::emptyString); \
|
||||
})); \
|
||||
m_##errorname##Error->setPrototype(state, m_functionPrototype); \
|
||||
m_##errorname##ErrorPrototype = new ErrorObject(state, String::emptyString); \
|
||||
m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().constructor, ObjectPropertyDescriptor(m_##errorname##Error, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::EnumerablePresent))); \
|
||||
m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().message, ObjectPropertyDescriptor(String::emptyString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::EnumerablePresent))); \
|
||||
m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().name, ObjectPropertyDescriptor(String::emptyString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::EnumerablePresent))); \
|
||||
m_##errorname##Error->setFunctionPrototype(state, m_##errorname##ErrorPrototype); \
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().bname##Error), \
|
||||
m_##errorname##Error->setFunctionPrototype(state, m_##errorname##ErrorPrototype); \
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().bname##Error), \
|
||||
ObjectPropertyDescriptor(m_function, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectStructurePropertyDescriptor::EnumerablePresent)));
|
||||
|
||||
DEFINE_ERROR(reference, Reference);
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ void GlobalObject::installObject(ExecutionState& state)
|
|||
|
||||
m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toString),
|
||||
ObjectPropertyDescriptor(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinObjectToString, 0, nullptr, NativeFunctionInfo::Strict)),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
|
||||
|
||||
// $19.1.3.2 Object.prototype.hasOwnProperty(V)
|
||||
m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().hasOwnProperty),
|
||||
|
|
|
|||
|
|
@ -259,11 +259,14 @@ bool Object::defineOwnProperty(ExecutionState& state, const ObjectPropertyName&
|
|||
}
|
||||
}
|
||||
|
||||
void Object::deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
||||
bool Object::deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
||||
{
|
||||
ASSERT(getOwnProperty(state, P).hasValue());
|
||||
ASSERT(getOwnProperty(state, P).isConfigurable());
|
||||
deleteOwnProperty(state, m_structure->findProperty(state, P.toPropertyName(state)));
|
||||
auto result = getOwnProperty(state, P);
|
||||
if (result.hasValue() && result.isConfigurable()) {
|
||||
deleteOwnProperty(state, m_structure->findProperty(state, P.toPropertyName(state)));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Object::enumeration(ExecutionState& state, std::function<bool(const ObjectPropertyName&, const ObjectStructurePropertyDescriptor& desc)> fn) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ public:
|
|||
|
||||
virtual ObjectGetResult getOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual bool defineOwnProperty(ExecutionState& state, const ObjectPropertyName& P, const ObjectPropertyDescriptor& desc) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual void deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual bool deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
// enumeration every property!
|
||||
// callback function should skip un-Enumerable property if needs
|
||||
virtual void enumeration(ExecutionState& state, std::function<bool(const ObjectPropertyName&, const ObjectStructurePropertyDescriptor& desc)> callback) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@ bool StringObject::defineOwnProperty(ExecutionState& state, const ObjectProperty
|
|||
return Object::defineOwnProperty(state, P, desc);
|
||||
}
|
||||
|
||||
void StringObject::deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
||||
bool StringObject::deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
||||
{
|
||||
auto r = getOwnProperty(state, P);
|
||||
if (r.hasValue() && !r.isConfigurable())
|
||||
return;
|
||||
return false;
|
||||
return Object::deleteOwnProperty(state, P);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public:
|
|||
|
||||
virtual ObjectGetResult getOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual bool defineOwnProperty(ExecutionState& state, const ObjectPropertyName& P, const ObjectPropertyDescriptor& desc) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual void deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual bool deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual void enumeration(ExecutionState& state, std::function<bool(const ObjectPropertyName&, const ObjectStructurePropertyDescriptor& desc)> callback) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual uint32_t length(ExecutionState& state)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue