mirror of
https://github.com/Samsung/escargot.git
synced 2026-06-22 10:01:50 +00:00
1. redesign Object api
2. implement ObjectPropertyName type Signed-off-by: seonghyun kim <sh8281.kim@samsung.com>
This commit is contained in:
parent
3946953e1d
commit
f2e8463092
18 changed files with 296 additions and 256 deletions
|
|
@ -462,7 +462,7 @@ void ByteCodeInterpreter::interpret(ExecutionState& state, CodeBlock* codeBlock)
|
|||
GetObject* code = (GetObject*)currentCode;
|
||||
const Value& willBeObject = registerFile[code->m_objectRegisterIndex];
|
||||
const Value& property = registerFile[code->m_objectRegisterIndex + 1];
|
||||
registerFile[code->m_objectRegisterIndex] = willBeObject.toObject(state)->get(state, property.toString(state)).m_value;
|
||||
registerFile[code->m_objectRegisterIndex] = willBeObject.toObject(state)->get(state, ObjectPropertyName(state, property)).value();
|
||||
executeNextCode<GetObject>(programCounter);
|
||||
NEXT_INSTRUCTION();
|
||||
}
|
||||
|
|
@ -472,7 +472,8 @@ void ByteCodeInterpreter::interpret(ExecutionState& state, CodeBlock* codeBlock)
|
|||
SetObject* code = (SetObject*)currentCode;
|
||||
const Value& willBeObject = registerFile[code->m_objectRegisterIndex];
|
||||
const Value& property = registerFile[code->m_propertyRegisterIndex];
|
||||
willBeObject.toObject(state)->set(state, property.toString(state), registerFile[code->m_loadRegisterIndex]);
|
||||
Object* obj = willBeObject.toObject(state);
|
||||
obj->setThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, property), registerFile[code->m_loadRegisterIndex], obj);
|
||||
executeNextCode<SetObject>(programCounter);
|
||||
NEXT_INSTRUCTION();
|
||||
}
|
||||
|
|
@ -932,7 +933,7 @@ GetObjectPreComputedCaseInlineCacheOperation:
|
|||
}
|
||||
if (LIKELY((*cachedHiddenClassChain)[cSiz] == obj->structure())) {
|
||||
if (cachedIndex != SIZE_MAX) {
|
||||
return std::make_pair(true, obj->getOwnProperty(state, cachedIndex, targetObj));
|
||||
return std::make_pair(true, obj->getOwnPropertyUtilForObject(state, cachedIndex, targetObj));
|
||||
} else {
|
||||
return std::make_pair(false, Value());
|
||||
}
|
||||
|
|
@ -942,8 +943,8 @@ GetObjectPreComputedCaseInlineCacheOperation:
|
|||
// cache miss.
|
||||
inlineCache.m_executeCount++;
|
||||
if (inlineCache.m_executeCount <= 3/* || UNLIKELY(willBeObject->toObject()->hasPropertyInterceptor())*/) {
|
||||
auto result = willBeObject.toObject(state)->get(state, name);
|
||||
return std::make_pair(result.m_hasValue, result.m_value);
|
||||
auto result = willBeObject.toObject(state)->get(state, ObjectPropertyName(state, name));
|
||||
return std::make_pair(result.hasValue(), result.value());
|
||||
}
|
||||
|
||||
obj = targetObj;
|
||||
|
|
@ -967,7 +968,7 @@ GetObjectPreComputedCaseInlineCacheOperation:
|
|||
}
|
||||
|
||||
if (*cachedHiddenClassIndex != SIZE_MAX) {
|
||||
return std::make_pair(true, obj->getOwnProperty(state, *cachedHiddenClassIndex, targetObj));
|
||||
return std::make_pair(true, obj->getOwnPropertyUtilForObject(state, *cachedHiddenClassIndex, targetObj));
|
||||
} else {
|
||||
return std::make_pair(false, Value());
|
||||
}
|
||||
|
|
@ -1064,7 +1065,7 @@ inline void ByteCodeInterpreter::setObjectPreComputedCaseOperation(ExecutionStat
|
|||
inlineCache.m_cachedhiddenClassChain.push_back(obj->structure());
|
||||
proto = obj->getPrototype(state);
|
||||
}
|
||||
bool s = orgObject->set(state, name, value, obj);
|
||||
bool s = orgObject->set(state, ObjectPropertyName(state, name), value, obj);
|
||||
if (UNLIKELY(!s)) {
|
||||
if (state.inStrictMode())
|
||||
obj->throwCannotWriteError(state, name);
|
||||
|
|
@ -1078,7 +1079,7 @@ inline void ByteCodeInterpreter::setObjectPreComputedCaseOperation(ExecutionStat
|
|||
}
|
||||
}
|
||||
Object* obj = willBeObject.toObject(state);
|
||||
obj->setThrowsExceptionWhenStrictMode(state, name, value, obj);
|
||||
obj->setThrowsExceptionWhenStrictMode(state, ObjectPropertyName(state, name), value, obj);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,9 +189,8 @@ bool CodeBlock::hasNonConfiguableNameOnGlobal(const AtomicString& name)
|
|||
}
|
||||
|
||||
ExecutionState state(m_context);
|
||||
size_t idx = m_context->globalObject()->findOwnProperty(state, PropertyName(state, name));
|
||||
if (idx != SIZE_MAX) {
|
||||
ObjectPropertyDescriptor desc = m_context->globalObject()->readPropertyDescriptor(state, idx);
|
||||
auto desc = m_context->globalObject()->getOwnProperty(state, ObjectPropertyName(state, name));
|
||||
if (desc.hasValue()) {
|
||||
if (!desc.isConfigurable()) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ GlobalEnvironmentRecord::GlobalEnvironmentRecord(ExecutionState& state, CodeBloc
|
|||
|
||||
void GlobalEnvironmentRecord::createMutableBinding(ExecutionState& state, const AtomicString& name, bool canDelete)
|
||||
{
|
||||
if (m_globalObject->findOwnProperty(state, name) == SIZE_MAX) {
|
||||
auto desc = m_globalObject->getOwnProperty(state, name);
|
||||
if (!desc.hasValue()) {
|
||||
ObjectPropertyDescriptor::PresentAttribute attribute = (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent);
|
||||
if (canDelete)
|
||||
attribute = (ObjectPropertyDescriptor::PresentAttribute)(attribute | ObjectPropertyDescriptor::ConfigurablePresent);
|
||||
|
|
@ -41,8 +42,11 @@ void GlobalEnvironmentRecord::createMutableBinding(ExecutionState& state, const
|
|||
|
||||
EnvironmentRecord::GetBindingValueResult GlobalEnvironmentRecord::getBindingValue(ExecutionState& state, const AtomicString& name)
|
||||
{
|
||||
auto result = m_globalObject->get(state, name);
|
||||
return EnvironmentRecord::GetBindingValueResult(result.m_hasValue, result.m_value);
|
||||
auto result = m_globalObject->get(state, name, m_globalObject);
|
||||
if (result.hasValue())
|
||||
return EnvironmentRecord::GetBindingValueResult(true, result.value());
|
||||
else
|
||||
return EnvironmentRecord::GetBindingValueResult(false, Value());
|
||||
}
|
||||
|
||||
void GlobalEnvironmentRecord::setMutableBinding(ExecutionState& state, const AtomicString& name, const Value& V)
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ ErrorObject::ErrorObject(ExecutionState& state, String* errorMessage)
|
|||
: Object(state)
|
||||
{
|
||||
if (errorMessage->length())
|
||||
set(state, PropertyName(state.context()->staticStrings().message), errorMessage);
|
||||
set(state, ObjectPropertyName(state.context()->staticStrings().message), errorMessage, this);
|
||||
setPrototype(state, state.context()->globalObject()->errorPrototype());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ FunctionObject::FunctionObject(ExecutionState& state, CodeBlock* codeBlock, bool
|
|||
|
||||
Value FunctionObject::getFunctionPrototypeSlowCase(ExecutionState& state)
|
||||
{
|
||||
return getOwnProperty(state, state.context()->staticStrings().prototype);
|
||||
return getOwnProperty(state, state.context()->staticStrings().prototype).value();
|
||||
}
|
||||
|
||||
bool FunctionObject::setFunctionPrototypeSlowCase(ExecutionState& state, const Value& v)
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ static Value builtinGc(ExecutionState& state, Value thisValue, size_t argc, Valu
|
|||
void GlobalObject::installOthers(ExecutionState& state)
|
||||
{
|
||||
#ifdef ESCARGOT_SHELL
|
||||
defineOwnProperty(state, PropertyName(state.context()->staticStrings().print),
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().print),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(new FunctionObject(state,
|
||||
NativeFunctionInfo(state.context()->staticStrings().print, builtinPrint, 1, nullptr, NativeFunctionInfo::Strict), false),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::AllPresent)));
|
||||
|
||||
#endif
|
||||
defineOwnProperty(state, PropertyName(state.context()->staticStrings().gc),
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().gc),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(new FunctionObject(state,
|
||||
NativeFunctionInfo(state.context()->staticStrings().gc, builtinGc, 0, nullptr, NativeFunctionInfo::Strict), false),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::AllPresent)));
|
||||
|
|
|
|||
|
|
@ -210,12 +210,12 @@ protected:
|
|||
|
||||
Value getPropertyOnIndex(ExecutionState& state, size_t idx)
|
||||
{
|
||||
return getOwnProperty(state, idx, this);
|
||||
return getOwnPropertyUtilForObject(state, idx, this);
|
||||
}
|
||||
|
||||
bool setPropertyOnIndex(ExecutionState& state, size_t idx, const Value& v)
|
||||
{
|
||||
return setOwnProperty(state, idx, v);
|
||||
return setOwnPropertyUtilForObject(state, idx, v);
|
||||
}
|
||||
|
||||
size_t findPropertyIndex(ExecutionState& state, const PropertyName& name)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ void GlobalObject::installBoolean(ExecutionState& state)
|
|||
|
||||
m_boolean->setFunctionPrototype(state, m_booleanPrototype);
|
||||
|
||||
defineOwnProperty(state, PropertyName(state.context()->staticStrings().Boolean),
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Boolean),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(m_boolean, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,14 +39,14 @@ static Value builtinErrorToString(ExecutionState& state, Value thisValue, size_t
|
|||
return ESValue(strings->emptyString.string());
|
||||
}*/
|
||||
|
||||
Value name = o->get(state, state.context()->staticStrings().name).m_value;
|
||||
Value name = o->get(state, state.context()->staticStrings().name, o).value();
|
||||
String* nameStr;
|
||||
if (name.isUndefined()) {
|
||||
nameStr = state.context()->staticStrings().Error.string();
|
||||
} else {
|
||||
nameStr = name.toString(state);
|
||||
}
|
||||
Value message = o->get(state, state.context()->staticStrings().message).m_value;
|
||||
Value message = o->get(state, state.context()->staticStrings().message, o).value();
|
||||
String* messageStr;
|
||||
if (message.isUndefined()) {
|
||||
messageStr = String::emptyString;
|
||||
|
|
@ -98,7 +98,7 @@ void GlobalObject::installError(ExecutionState& state)
|
|||
m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().message, Object::ObjectPropertyDescriptorForDefineOwnProperty(String::emptyString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent))); \
|
||||
m_##errorname##ErrorPrototype->defineOwnProperty(state, state.context()->staticStrings().name, Object::ObjectPropertyDescriptorForDefineOwnProperty(String::emptyString, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent))); \
|
||||
m_##errorname##Error->setFunctionPrototype(state, m_##errorname##ErrorPrototype); \
|
||||
defineOwnProperty(state, PropertyName(state.context()->staticStrings().bname##Error), \
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().bname##Error), \
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(m_function, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
|
||||
DEFINE_ERROR(reference, Reference);
|
||||
|
|
@ -108,7 +108,7 @@ void GlobalObject::installError(ExecutionState& state)
|
|||
DEFINE_ERROR(uri, URI);
|
||||
DEFINE_ERROR(eval, Eval);
|
||||
|
||||
defineOwnProperty(state, PropertyName(state.context()->staticStrings().Error),
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Error),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(m_function, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,10 +36,10 @@ void GlobalObject::installFunction(ExecutionState& state)
|
|||
|
||||
m_function->setPrototype(state, emptyFunction);
|
||||
m_function->setFunctionPrototype(state, emptyFunction);
|
||||
m_functionPrototype->defineOwnProperty(state, PropertyName(state.context()->staticStrings().constructor),
|
||||
m_functionPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(m_function, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
|
||||
defineOwnProperty(state, PropertyName(state.context()->staticStrings().Function),
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Function),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(m_function, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,10 +49,10 @@ void GlobalObject::installMath(ExecutionState& state)
|
|||
m_math->defineOwnPropertyThrowsException(state, strings->SQRT2, ObjectPropertyDescriptorForDefineOwnProperty(Value(1.4142135623730951), ObjectPropertyDescriptor::NotPresent));
|
||||
|
||||
// initialize math object: $20.2.2.24 Math.max()
|
||||
m_math->defineOwnPropertyThrowsException(state, PropertyName(state.context()->staticStrings().max),
|
||||
m_math->defineOwnPropertyThrowsException(state, ObjectPropertyName(state.context()->staticStrings().max),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().max, builtinMathMax, 2, nullptr, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
|
||||
defineOwnProperty(state, PropertyName(state.context()->staticStrings().Math),
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Math),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(m_math, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ void GlobalObject::installNumber(ExecutionState& state)
|
|||
|
||||
m_number->setFunctionPrototype(state, m_numberPrototype);
|
||||
|
||||
defineOwnProperty(state, PropertyName(state.context()->staticStrings().Number),
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Number),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(m_number, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ static Value builtinObjectHasOwnProperty(ExecutionState& state, Value thisValue,
|
|||
{
|
||||
String* keyString = argv[0].toPrimitive(state, Value::PrimitiveTypeHint::PreferString).toString(state);
|
||||
Object* obj = thisValue.toObject(state);
|
||||
return Value(obj->hasOwnProperty(state, keyString));
|
||||
return Value(obj->hasOwnProperty(state, ObjectPropertyName(state, keyString)));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -90,18 +90,18 @@ void GlobalObject::installObject(ExecutionState& state)
|
|||
m_object->setPrototype(state, emptyFunction);
|
||||
// TODO m_object->defineAccessorProperty(strings->prototype.string(), ESVMInstance::currentInstance()->functionPrototypeAccessorData(), false, false, false);
|
||||
m_object->setFunctionPrototype(state, m_objectPrototype);
|
||||
m_objectPrototype->defineOwnProperty(state, PropertyName(state.context()->staticStrings().constructor),
|
||||
m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(m_object, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
|
||||
m_objectPrototype->defineOwnProperty(state, PropertyName(state.context()->staticStrings().toString),
|
||||
m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().toString),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinObjectToString, 0, nullptr, NativeFunctionInfo::Strict)),
|
||||
(ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
|
||||
// $19.1.3.2 Object.prototype.hasOwnProperty(V)
|
||||
m_objectPrototype->defineOwnProperty(state, PropertyName(state.context()->staticStrings().hasOwnProperty),
|
||||
m_objectPrototype->defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().hasOwnProperty),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(new FunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().toString, builtinObjectHasOwnProperty, 1, nullptr, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
|
||||
defineOwnProperty(state, PropertyName(state.context()->staticStrings().Object),
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Object),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(m_object, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ void GlobalObject::installString(ExecutionState& state)
|
|||
|
||||
m_string->setFunctionPrototype(state, m_stringPrototype);
|
||||
|
||||
defineOwnProperty(state, PropertyName(state.context()->staticStrings().String),
|
||||
defineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().String),
|
||||
Object::ObjectPropertyDescriptorForDefineOwnProperty(m_string, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::EnumerablePresent)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,32 +46,27 @@ Object* Object::createFunctionPrototypeObject(ExecutionState& state, FunctionObj
|
|||
|
||||
Value Object::getPrototypeSlowCase(ExecutionState& state)
|
||||
{
|
||||
return getOwnProperty(state, state.context()->staticStrings().__proto__);
|
||||
return getOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().__proto__)).value();
|
||||
}
|
||||
|
||||
bool Object::setPrototypeSlowCase(ExecutionState& state, const Value& value)
|
||||
{
|
||||
return defineOwnProperty(state, state.context()->staticStrings().__proto__, ObjectPropertyDescriptorForDefineOwnProperty(value));
|
||||
}
|
||||
|
||||
Value Object::getOwnProperty(ExecutionState& state, String* P)
|
||||
{
|
||||
PropertyName propertyName(state, P);
|
||||
return getOwnProperty(state, propertyName);
|
||||
return defineOwnProperty(state, ObjectPropertyName(state, state.context()->staticStrings().__proto__), ObjectPropertyDescriptorForDefineOwnProperty(value));
|
||||
}
|
||||
|
||||
// http://www.ecma-international.org/ecma-262/6.0/#sec-ordinarygetownproperty
|
||||
Value Object::getOwnProperty(ExecutionState& state, const PropertyName& P)
|
||||
Object::ObjectGetResult Object::getOwnProperty(ExecutionState& state, const ObjectPropertyName& propertyName) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
||||
{
|
||||
PropertyName P = propertyName.toPropertyName(state);
|
||||
size_t idx = m_structure->findProperty(state, P);
|
||||
if (LIKELY(idx != SIZE_MAX)) {
|
||||
const ObjectStructureItem& item = m_structure->readProperty(state, idx);
|
||||
if (item.m_descriptor.isDataProperty()) {
|
||||
if (LIKELY(!item.m_descriptor.isNativeAccessorProperty())) {
|
||||
return m_values[idx];
|
||||
return Object::ObjectGetResult(m_values[idx], item.m_descriptor.isWritable(), item.m_descriptor.isEnumerable(), item.m_descriptor.isConfigurable());
|
||||
} else {
|
||||
ObjectPropertyNativeGetterSetterData* data = item.m_descriptor.nativeGetterSetterData();
|
||||
return data->m_getter(state, this);
|
||||
return Object::ObjectGetResult(data->m_getter(state, this), item.m_descriptor.isWritable(), item.m_descriptor.isEnumerable(), item.m_descriptor.isConfigurable());
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
|
|
@ -79,21 +74,169 @@ Value Object::getOwnProperty(ExecutionState& state, const PropertyName& P)
|
|||
RELEASE_ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
return Value();
|
||||
return Object::ObjectGetResult();
|
||||
}
|
||||
|
||||
size_t Object::findOwnProperty(ExecutionState& state, String* P)
|
||||
bool Object::defineOwnProperty(ExecutionState& state, const ObjectPropertyName& P, const ObjectPropertyDescriptorForDefineOwnProperty& desc) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
||||
{
|
||||
return m_structure->findProperty(state, P);
|
||||
if (isEverSetAsPrototypeObject()) {
|
||||
// TODO
|
||||
// implement bad time
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
PropertyName propertyName = P.toPropertyName(state);
|
||||
size_t oldIdx = m_structure->findProperty(state, propertyName);
|
||||
if (oldIdx == SIZE_MAX) {
|
||||
if (checkPropertyAlreadyDefinedWithNonWritableInPrototype(state, P)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (UNLIKELY(!isExtensible()))
|
||||
return false;
|
||||
|
||||
m_structure = m_structure->addProperty(state, propertyName, desc.descriptor());
|
||||
|
||||
// TODO implement JS getter setter
|
||||
RELEASE_ASSERT(desc.descriptor().isDataProperty());
|
||||
|
||||
m_values.pushBack(desc.value());
|
||||
return true;
|
||||
} else {
|
||||
size_t idx = oldIdx;
|
||||
const ObjectStructureItem& item = m_structure->readProperty(state, idx);
|
||||
if (!item.m_descriptor.isWritable())
|
||||
return false;
|
||||
|
||||
if (item.m_descriptor != desc.descriptor()) {
|
||||
if (!item.m_descriptor.isConfigurable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
deleteOwnProperty(state, P);
|
||||
defineOwnProperty(state, P, desc);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (item.m_descriptor.isDataProperty()) {
|
||||
if (LIKELY(!item.m_descriptor.isNativeAccessorProperty())) {
|
||||
m_values[idx] = desc.value();
|
||||
return true;
|
||||
} else {
|
||||
ObjectPropertyNativeGetterSetterData* data = item.m_descriptor.nativeGetterSetterData();
|
||||
return data->m_setter(state, this, desc.value());
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
// implement js getter, setter
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
size_t Object::findOwnProperty(ExecutionState& state, const PropertyName& P)
|
||||
void Object::deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
||||
{
|
||||
return m_structure->findProperty(state, P);
|
||||
ASSERT(getOwnProperty(state, P).hasValue());
|
||||
ASSERT(getOwnProperty(state, P).isConfigurable());
|
||||
deleteOwnProperty(state, m_structure->findProperty(state, P.toPropertyName(state)));
|
||||
}
|
||||
|
||||
bool Object::checkPropertyAlreadyDefinedWithNonWritableInPrototype(ExecutionState& state, const PropertyName& P)
|
||||
Object::ObjectGetResult Object::get(ExecutionState& state, const ObjectPropertyName& propertyName, Object* receiver)
|
||||
{
|
||||
Object* target = this;
|
||||
while (true) {
|
||||
auto result = target->getOwnProperty(state, propertyName);
|
||||
if (result.hasValue()) {
|
||||
return result;
|
||||
}
|
||||
Value __proto__ = target->getPrototype(state);
|
||||
if (__proto__.isObject()) {
|
||||
target = __proto__.asObject();
|
||||
} else {
|
||||
return Object::ObjectGetResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-set-p-v-receiver
|
||||
bool Object::set(ExecutionState& state, const ObjectPropertyName& propertyName, const Value& v, Object* receiver)
|
||||
{
|
||||
auto desc = getOwnProperty(state, propertyName);
|
||||
if (!desc.hasValue()) {
|
||||
Value target = this->getPrototype(state);
|
||||
while (target.isObject()) {
|
||||
Object* O = target.asObject();
|
||||
auto desc = O->getOwnProperty(state, propertyName);
|
||||
if (desc.hasValue()) {
|
||||
return set(state, propertyName, v, receiver);
|
||||
}
|
||||
target = O->getPrototype(state);
|
||||
}
|
||||
ObjectPropertyDescriptorForDefineOwnProperty desc(v);
|
||||
return defineOwnProperty(state, propertyName, desc);
|
||||
} else {
|
||||
// If IsDataDescriptor(ownDesc) is true, then
|
||||
if (desc.isDataProperty()) {
|
||||
// If ownDesc.[[Writable]] is false, return false.
|
||||
if (!desc.isWritable()) {
|
||||
return false;
|
||||
}
|
||||
// TODO If Type(Receiver) is not Object, return false.
|
||||
// Let existingDescriptor be Receiver.[[GetOwnProperty]](P).
|
||||
auto receiverDesc = receiver->getOwnProperty(state, propertyName);
|
||||
// If existingDescriptor is not undefined, then
|
||||
if (receiverDesc.hasValue()) {
|
||||
// If IsAccessorDescriptor(existingDescriptor) is true, return false.
|
||||
if (!receiverDesc.isDataProperty()) {
|
||||
return false;
|
||||
}
|
||||
// If existingDescriptor.[[Writable]] is false, return false
|
||||
if (!receiverDesc.isWritable()) {
|
||||
return false;
|
||||
}
|
||||
// Let valueDesc be the PropertyDescriptor{[[Value]]: V}.
|
||||
ObjectPropertyDescriptorForDefineOwnProperty desc(v);
|
||||
return receiver->defineOwnProperty(state, propertyName, desc);
|
||||
} else {
|
||||
// Else Receiver does not currently have a property P,
|
||||
// Return CreateDataProperty(Receiver, P, V).
|
||||
ObjectPropertyDescriptorForDefineOwnProperty desc(v);
|
||||
return defineOwnProperty(state, propertyName, desc);
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Object::setThrowsException(ExecutionState& state, const ObjectPropertyName& P, const Value& v, Object* receiver)
|
||||
{
|
||||
if (UNLIKELY(!set(state, P, v, receiver))) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, P.string(state), false, String::emptyString, errorMessage_DefineProperty_NotWritable);
|
||||
}
|
||||
}
|
||||
|
||||
void Object::setThrowsExceptionWhenStrictMode(ExecutionState& state, const ObjectPropertyName& P, const Value& v, Object* receiver)
|
||||
{
|
||||
if (UNLIKELY(!set(state, P, v, receiver)) && state.inStrictMode()) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, P.string(state), false, String::emptyString, errorMessage_DefineProperty_NotWritable);
|
||||
}
|
||||
}
|
||||
|
||||
void Object::throwCannotDefineError(ExecutionState& state, const PropertyName& P)
|
||||
{
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, P.string(), false, String::emptyString, errorMessage_DefineProperty_RedefineNotConfigurable);
|
||||
}
|
||||
|
||||
void Object::throwCannotWriteError(ExecutionState& state, const PropertyName& P)
|
||||
{
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, P.string(), false, String::emptyString, errorMessage_DefineProperty_NotWritable);
|
||||
}
|
||||
|
||||
bool Object::checkPropertyAlreadyDefinedWithNonWritableInPrototype(ExecutionState& state, const ObjectPropertyName& P)
|
||||
{
|
||||
Value __proto__Value = getPrototype(state);
|
||||
while (true) {
|
||||
|
|
@ -101,14 +244,13 @@ bool Object::checkPropertyAlreadyDefinedWithNonWritableInPrototype(ExecutionStat
|
|||
break;
|
||||
}
|
||||
Object* targetObj = __proto__Value.asObject();
|
||||
size_t t = targetObj->m_structure->findProperty(state, P);
|
||||
if (t != SIZE_MAX) {
|
||||
auto t = targetObj->getOwnProperty(state, P);
|
||||
if (t.hasValue()) {
|
||||
// http://www.ecma-international.org/ecma-262/5.1/#sec-8.12.5
|
||||
// If IsAccessorDescriptor(desc) is true, then
|
||||
// Let setter be desc.[[Set]] which cannot be undefined.
|
||||
// Call the [[Call]] internal method of setter providing O as the this value and providing V as the sole argument.
|
||||
const ObjectStructureItem& item = targetObj->m_structure->readProperty(state, t);
|
||||
if (!item.m_descriptor.isDataProperty()) {
|
||||
if (!t.isDataProperty()) {
|
||||
// TODO
|
||||
// implement js getter, setter
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
|
|
@ -137,193 +279,16 @@ bool Object::checkPropertyAlreadyDefinedWithNonWritableInPrototype(ExecutionStat
|
|||
}
|
||||
}*/
|
||||
} else {
|
||||
if (!item.m_descriptor.isWritable()) {
|
||||
if (!t.isWritable()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO
|
||||
/*else if (targetObj->isESStringObject()) {
|
||||
uint32_t idx = key.toIndex();
|
||||
if (idx != ESValue::ESInvalidIndexValue)
|
||||
if (idx < targetObj->asESStringObject()->length())
|
||||
return false;
|
||||
}*/
|
||||
__proto__Value = targetObj->getPrototype(state);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Object::defineOwnProperty(ExecutionState& state, const PropertyName& propertyName, const ObjectPropertyDescriptorForDefineOwnProperty& desc)
|
||||
{
|
||||
if (isEverSetAsPrototypeObject()) {
|
||||
// TODO
|
||||
// implement bad time
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
size_t oldIdx = m_structure->findProperty(state, propertyName);
|
||||
if (oldIdx == SIZE_MAX) {
|
||||
if (checkPropertyAlreadyDefinedWithNonWritableInPrototype(state, propertyName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (UNLIKELY(!isExtensible()))
|
||||
return false;
|
||||
|
||||
m_structure = m_structure->addProperty(state, propertyName, desc.descriptor());
|
||||
|
||||
// TODO implement JS getter setter
|
||||
RELEASE_ASSERT(desc.descriptor().isDataProperty());
|
||||
|
||||
m_values.pushBack(desc.value());
|
||||
return true;
|
||||
} else {
|
||||
size_t idx = oldIdx;
|
||||
const ObjectStructureItem& item = m_structure->readProperty(state, idx);
|
||||
if (!item.m_descriptor.isWritable())
|
||||
return false;
|
||||
|
||||
if (item.m_descriptor != desc.descriptor()) {
|
||||
if (!item.m_descriptor.isConfigurable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
deleteOwnProperty(state, idx);
|
||||
defineOwnProperty(state, propertyName, desc);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (item.m_descriptor.isDataProperty()) {
|
||||
if (LIKELY(!item.m_descriptor.isNativeAccessorProperty())) {
|
||||
m_values[idx] = desc.value();
|
||||
return true;
|
||||
} else {
|
||||
ObjectPropertyNativeGetterSetterData* data = item.m_descriptor.nativeGetterSetterData();
|
||||
return data->m_setter(state, this, desc.value());
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
// implement js getter, setter
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Object::defineOwnProperty(ExecutionState& state, String* P, const ObjectPropertyDescriptorForDefineOwnProperty& desc)
|
||||
{
|
||||
PropertyName propertyName(state, P);
|
||||
return defineOwnProperty(state, propertyName, desc);
|
||||
}
|
||||
|
||||
Object::ObjectGetResult Object::get(ExecutionState& state, String* P, Object* receiver)
|
||||
{
|
||||
PropertyName propertyName(state, P);
|
||||
return get(state, propertyName, receiver);
|
||||
}
|
||||
|
||||
Object::ObjectGetResult Object::get(ExecutionState& state, const PropertyName& propertyName, Object* receiver)
|
||||
{
|
||||
Object* target = this;
|
||||
while (true) {
|
||||
size_t idx = target->findOwnProperty(state, propertyName);
|
||||
if (idx != SIZE_MAX) {
|
||||
return ObjectGetResult(target->getOwnProperty(state, idx, receiver));
|
||||
}
|
||||
Value __proto__ = target->getPrototype(state);
|
||||
if (__proto__.isObject()) {
|
||||
target = __proto__.asObject();
|
||||
} else {
|
||||
return ObjectGetResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Object::set(ExecutionState& state, String* P, const Value& v, Object* receiver)
|
||||
{
|
||||
PropertyName propertyName(state, P);
|
||||
return set(state, propertyName, v, receiver);
|
||||
}
|
||||
|
||||
// http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-set-p-v-receiver
|
||||
bool Object::set(ExecutionState& state, const PropertyName& propertyName, const Value& v, Object* receiver)
|
||||
{
|
||||
size_t idx = findOwnProperty(state, propertyName);
|
||||
if (idx == SIZE_MAX) {
|
||||
Value target = this->getPrototype(state);
|
||||
while (target.isObject()) {
|
||||
Object* O = target.asObject();
|
||||
size_t idx = O->findOwnProperty(state, propertyName);
|
||||
if (idx != SIZE_MAX) {
|
||||
return set(state, propertyName, v, receiver);
|
||||
}
|
||||
target = O->getPrototype(state);
|
||||
}
|
||||
ObjectPropertyDescriptorForDefineOwnProperty desc(v);
|
||||
return defineOwnProperty(state, propertyName, desc);
|
||||
} else {
|
||||
const ObjectStructureItem& ownDesc = m_structure->readProperty(state, idx);
|
||||
// If IsDataDescriptor(ownDesc) is true, then
|
||||
if (ownDesc.m_descriptor.isDataProperty()) {
|
||||
// If ownDesc.[[Writable]] is false, return false.
|
||||
if (!ownDesc.m_descriptor.isWritable()) {
|
||||
return false;
|
||||
}
|
||||
// TODO If Type(Receiver) is not Object, return false.
|
||||
// Let existingDescriptor be Receiver.[[GetOwnProperty]](P).
|
||||
size_t receiverIdx = receiver->m_structure->findProperty(propertyName);
|
||||
// If existingDescriptor is not undefined, then
|
||||
if (receiverIdx != SIZE_MAX) {
|
||||
const ObjectStructureItem& existingDescriptor = receiver->m_structure->readProperty(state, receiverIdx);
|
||||
// If IsAccessorDescriptor(existingDescriptor) is true, return false.
|
||||
if (existingDescriptor.m_descriptor.isAccessorProperty()) {
|
||||
return false;
|
||||
}
|
||||
// If existingDescriptor.[[Writable]] is false, return false
|
||||
if (!existingDescriptor.m_descriptor.isWritable()) {
|
||||
return false;
|
||||
}
|
||||
// Let valueDesc be the PropertyDescriptor{[[Value]]: V}.
|
||||
ObjectPropertyDescriptorForDefineOwnProperty desc(v);
|
||||
return receiver->defineOwnProperty(state, propertyName, desc);
|
||||
} else {
|
||||
// Else Receiver does not currently have a property P,
|
||||
// Return CreateDataProperty(Receiver, P, V).
|
||||
ObjectPropertyDescriptorForDefineOwnProperty desc(v);
|
||||
return defineOwnProperty(state, propertyName, desc);
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Object::setThrowsException(ExecutionState& state, const PropertyName& P, const Value& v, Object* receiver)
|
||||
{
|
||||
if (UNLIKELY(!set(state, P, v, receiver))) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, P.string(), false, String::emptyString, errorMessage_DefineProperty_NotWritable);
|
||||
}
|
||||
}
|
||||
|
||||
void Object::setThrowsExceptionWhenStrictMode(ExecutionState& state, const PropertyName& P, const Value& v, Object* receiver)
|
||||
{
|
||||
if (UNLIKELY(!set(state, P, v, receiver)) && state.inStrictMode()) {
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, P.string(), false, String::emptyString, errorMessage_DefineProperty_NotWritable);
|
||||
}
|
||||
}
|
||||
|
||||
void Object::throwCannotDefineError(ExecutionState& state, const PropertyName& P)
|
||||
{
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, P.string(), false, String::emptyString, errorMessage_DefineProperty_RedefineNotConfigurable);
|
||||
}
|
||||
|
||||
void Object::throwCannotWriteError(ExecutionState& state, const PropertyName& P)
|
||||
{
|
||||
ErrorObject::throwBuiltinError(state, ErrorObject::Code::TypeError, P.string(), false, String::emptyString, errorMessage_DefineProperty_NotWritable);
|
||||
}
|
||||
|
||||
void Object::deleteOwnProperty(ExecutionState& state, size_t idx)
|
||||
{
|
||||
|
|
@ -339,7 +304,6 @@ void Object::deleteOwnProperty(ExecutionState& state, size_t idx)
|
|||
|
||||
m_structure = m_structure->removeProperty(state, idx);
|
||||
m_values.erase(idx);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,72 @@ struct ObjectRareData {
|
|||
}
|
||||
};
|
||||
|
||||
#define ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER 1
|
||||
class ObjectPropertyName {
|
||||
MAKE_STACK_ALLOCATED()
|
||||
public:
|
||||
ObjectPropertyName(ExecutionState& state, const Value& v)
|
||||
{
|
||||
if (v.isUInt32()) {
|
||||
m_isUIntType = true;
|
||||
m_value.m_uint = v.asUInt32();
|
||||
} else {
|
||||
m_isUIntType = false;
|
||||
m_value.m_name = PropertyName(state, v.toString(state));
|
||||
}
|
||||
}
|
||||
|
||||
ObjectPropertyName(const AtomicString& v)
|
||||
{
|
||||
m_isUIntType = false;
|
||||
m_value.m_name = v;
|
||||
}
|
||||
|
||||
ObjectPropertyName(ExecutionState& state, const PropertyName& v)
|
||||
{
|
||||
m_isUIntType = false;
|
||||
m_value.m_name = v;
|
||||
}
|
||||
|
||||
bool isUIntType() const
|
||||
{
|
||||
return m_isUIntType;
|
||||
}
|
||||
|
||||
const PropertyName& propertyName() const
|
||||
{
|
||||
ASSERT(!isUIntType());
|
||||
return m_value.m_name;
|
||||
}
|
||||
|
||||
const uint32_t& uintValue() const
|
||||
{
|
||||
ASSERT(isUIntType());
|
||||
return m_value.m_uint;
|
||||
}
|
||||
|
||||
PropertyName toPropertyName(ExecutionState& state) const
|
||||
{
|
||||
if (isUIntType()) {
|
||||
return PropertyName(state, String::fromDouble(uintValue()));
|
||||
}
|
||||
return propertyName();
|
||||
}
|
||||
|
||||
String* string(ExecutionState& state) const
|
||||
{
|
||||
return toPropertyName(state).string();
|
||||
}
|
||||
protected:
|
||||
bool m_isUIntType;
|
||||
union ObjectPropertyNameData {
|
||||
ObjectPropertyNameData() { m_uint = 0; }
|
||||
PropertyName m_name;
|
||||
uint32_t m_uint;
|
||||
} m_value;
|
||||
};
|
||||
|
||||
#define ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER 1
|
||||
#define ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE
|
||||
class Object : public PointerValue {
|
||||
friend class Context;
|
||||
friend class GlobalObject;
|
||||
|
|
@ -54,6 +118,19 @@ public:
|
|||
return (ErrorObject*)this;
|
||||
}
|
||||
|
||||
// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-ordinary-object-internal-methods-and-internal-slots-isextensible
|
||||
bool isExtensible()
|
||||
{
|
||||
return m_rareData == nullptr ? true : m_rareData->m_isExtensible;
|
||||
}
|
||||
|
||||
// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-ordinary-object-internal-methods-and-internal-slots-preventextensions
|
||||
void preventExtensions()
|
||||
{
|
||||
ensureObjectRareData();
|
||||
m_rareData->m_isExtensible = true;
|
||||
}
|
||||
|
||||
Value getPrototype(ExecutionState& state)
|
||||
{
|
||||
if (LIKELY(isPlainObject())) {
|
||||
|
|
@ -72,33 +149,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-ordinary-object-internal-methods-and-internal-slots-isextensible
|
||||
bool isExtensible()
|
||||
{
|
||||
return m_rareData == nullptr ? true : m_rareData->m_isExtensible;
|
||||
}
|
||||
|
||||
// http://www.ecma-international.org/ecma-262/6.0/index.html#sec-ordinary-object-internal-methods-and-internal-slots-preventextensions
|
||||
void preventExtensions()
|
||||
{
|
||||
ensureObjectRareData();
|
||||
m_rareData->m_isExtensible = true;
|
||||
}
|
||||
|
||||
Value getOwnProperty(ExecutionState& state, String* P);
|
||||
Value getOwnProperty(ExecutionState& state, const PropertyName& P);
|
||||
size_t findOwnProperty(ExecutionState& state, String* P);
|
||||
size_t findOwnProperty(ExecutionState& state, const PropertyName& P);
|
||||
|
||||
size_t hasOwnProperty(ExecutionState& state, String* P)
|
||||
{
|
||||
return findOwnProperty(state, P) != SIZE_MAX;
|
||||
}
|
||||
size_t hasOwnProperty(ExecutionState& state, const PropertyName& P)
|
||||
{
|
||||
return findOwnProperty(state, P) != SIZE_MAX;
|
||||
}
|
||||
|
||||
class ObjectPropertyDescriptorForDefineOwnProperty {
|
||||
public:
|
||||
// for plain data property
|
||||
|
|
@ -128,75 +178,109 @@ public:
|
|||
Value m_value;
|
||||
};
|
||||
|
||||
void defineOwnPropertyThrowsException(ExecutionState& state, const PropertyName& P, const ObjectPropertyDescriptorForDefineOwnProperty& desc)
|
||||
{
|
||||
if (!defineOwnProperty(state, P, desc)) {
|
||||
throwCannotDefineError(state, P);
|
||||
}
|
||||
}
|
||||
|
||||
void defineOwnPropertyThrowsExceptionWhenStrictMode(ExecutionState& state, const PropertyName& P, const ObjectPropertyDescriptorForDefineOwnProperty& desc)
|
||||
{
|
||||
if (!defineOwnProperty(state, P, desc) && state.inStrictMode()) {
|
||||
throwCannotDefineError(state, P);
|
||||
}
|
||||
}
|
||||
|
||||
// 9.1.7 [[HasProperty]](P)
|
||||
|
||||
// http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-get-p-receiver
|
||||
struct ObjectGetResult {
|
||||
bool m_hasValue;
|
||||
Value m_value;
|
||||
class ObjectGetResult {
|
||||
public:
|
||||
// TODO implement js getter case
|
||||
ObjectGetResult()
|
||||
: m_hasValue(false)
|
||||
, m_isWritable(false)
|
||||
, m_isEnumerable(false)
|
||||
, m_isConfigurable(false)
|
||||
, m_isDataProperty(false)
|
||||
, m_value(Value())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ObjectGetResult(const Value& v)
|
||||
ObjectGetResult(const Value& v, bool isWritable, bool isEnumerable, bool isConfigurable)
|
||||
: m_hasValue(true)
|
||||
, m_isWritable(isWritable)
|
||||
, m_isEnumerable(isEnumerable)
|
||||
, m_isConfigurable(isConfigurable)
|
||||
, m_isDataProperty(true)
|
||||
, m_value(v)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Value value() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
bool hasValue() const
|
||||
{
|
||||
return m_hasValue;
|
||||
}
|
||||
|
||||
bool isWritable() const
|
||||
{
|
||||
ASSERT(hasValue());
|
||||
return m_isWritable;
|
||||
}
|
||||
|
||||
bool isEnumerable() const
|
||||
{
|
||||
ASSERT(hasValue());
|
||||
return m_isEnumerable;
|
||||
}
|
||||
|
||||
bool isConfigurable() const
|
||||
{
|
||||
ASSERT(hasValue());
|
||||
return m_isConfigurable;
|
||||
}
|
||||
|
||||
bool isDataProperty() const
|
||||
{
|
||||
ASSERT(hasValue());
|
||||
return m_isDataProperty;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool m_hasValue : 1;
|
||||
bool m_isWritable : 1;
|
||||
bool m_isEnumerable : 1;
|
||||
bool m_isConfigurable : 1;
|
||||
bool m_isDataProperty : 1;
|
||||
Value m_value;
|
||||
};
|
||||
|
||||
ObjectGetResult get(ExecutionState& state, String* P)
|
||||
virtual ObjectGetResult getOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual bool defineOwnProperty(ExecutionState& state, const ObjectPropertyName& P, const ObjectPropertyDescriptorForDefineOwnProperty& desc) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
virtual void deleteOwnProperty(ExecutionState& state, const ObjectPropertyName& P) ESCARGOT_OBJECT_SUBCLASS_MUST_REDEFINE;
|
||||
|
||||
bool hasOwnProperty(ExecutionState& state, const ObjectPropertyName& propertyName)
|
||||
{
|
||||
return getOwnProperty(state, propertyName).hasValue();
|
||||
}
|
||||
|
||||
ObjectGetResult get(ExecutionState& state, const ObjectPropertyName& P, Object* receiver);
|
||||
ObjectGetResult get(ExecutionState& state, const ObjectPropertyName& P)
|
||||
{
|
||||
return get(state, P, this);
|
||||
}
|
||||
|
||||
ObjectGetResult get(ExecutionState& state, const PropertyName& P)
|
||||
void setThrowsException(ExecutionState& state, const ObjectPropertyName& P, const Value& v, Object* receiver);
|
||||
void setThrowsExceptionWhenStrictMode(ExecutionState& state, const ObjectPropertyName& P, const Value& v, Object* receiver);
|
||||
void defineOwnPropertyThrowsException(ExecutionState& state, const ObjectPropertyName& P, const ObjectPropertyDescriptorForDefineOwnProperty& desc)
|
||||
{
|
||||
return get(state, P, this);
|
||||
if (!defineOwnProperty(state, P, desc)) {
|
||||
throwCannotDefineError(state, P.toPropertyName(state));
|
||||
}
|
||||
}
|
||||
|
||||
ObjectGetResult get(ExecutionState& state, String* P, Object* receiver);
|
||||
ObjectGetResult get(ExecutionState& state, const PropertyName& P, Object* receiver);
|
||||
void defineOwnPropertyThrowsExceptionWhenStrictMode(ExecutionState& state, const ObjectPropertyName& P, const ObjectPropertyDescriptorForDefineOwnProperty& desc)
|
||||
{
|
||||
if (!defineOwnProperty(state, P, desc) && state.inStrictMode()) {
|
||||
throwCannotDefineError(state, P.toPropertyName(state));
|
||||
}
|
||||
}
|
||||
|
||||
void setThrowsException(ExecutionState& state, const PropertyName& P, const Value& v, Object* receiver);
|
||||
void setThrowsExceptionWhenStrictMode(ExecutionState& state, const PropertyName& P, const Value& v, Object* receiver);
|
||||
|
||||
ObjectPropertyDescriptor readPropertyDescriptor(ExecutionState& state, String* propertyName)
|
||||
{
|
||||
return readPropertyDescriptor(state, PropertyName(state, propertyName));
|
||||
}
|
||||
ObjectPropertyDescriptor readPropertyDescriptor(ExecutionState& state, const PropertyName& name)
|
||||
{
|
||||
return readPropertyDescriptor(state, findOwnProperty(state, name));
|
||||
}
|
||||
ObjectPropertyDescriptor readPropertyDescriptor(ExecutionState& state, const size_t& idx)
|
||||
{
|
||||
return m_structure->readProperty(state, idx).m_descriptor;
|
||||
}
|
||||
|
||||
void markThisObjectDontNeedStructureTransitionTable(ExecutionState& state)
|
||||
{
|
||||
ASSERT(structure()->inTransitionMode());
|
||||
m_structure = m_structure->escapeTransitionMode(state);
|
||||
}
|
||||
|
||||
protected:
|
||||
Object(ExecutionState& state, size_t defaultSpace, bool initPlainArea);
|
||||
void initPlainObject(ExecutionState& state);
|
||||
|
|
@ -208,7 +292,7 @@ protected:
|
|||
{
|
||||
return m_structure;
|
||||
}
|
||||
bool checkPropertyAlreadyDefinedWithNonWritableInPrototype(ExecutionState& state, const PropertyName& P);
|
||||
bool checkPropertyAlreadyDefinedWithNonWritableInPrototype(ExecutionState& state, const ObjectPropertyName& P);
|
||||
void ensureObjectRareData()
|
||||
{
|
||||
if (m_rareData == nullptr) {
|
||||
|
|
@ -228,12 +312,12 @@ protected:
|
|||
m_values[idx] = newValue;
|
||||
}
|
||||
|
||||
Value getOwnDataProperty(ExecutionState& state, size_t idx)
|
||||
Value getOwnDataPropertyUtilForObject(ExecutionState& state, size_t idx)
|
||||
{
|
||||
return getOwnDataProperty(state, idx, this);
|
||||
return getOwnDataPropertyUtilForObject(state, idx, this);
|
||||
}
|
||||
|
||||
Value getOwnDataProperty(ExecutionState& state, size_t idx, Object* receiver)
|
||||
Value getOwnDataPropertyUtilForObject(ExecutionState& state, size_t idx, Object* receiver)
|
||||
{
|
||||
ASSERT(m_structure->readProperty(state, idx).m_descriptor.isDataProperty());
|
||||
const ObjectStructureItem& item = m_structure->readProperty(state, idx);
|
||||
|
|
@ -244,7 +328,7 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
bool setOwnDataProperty(ExecutionState& state, size_t idx, const Value& newValue)
|
||||
bool setOwnDataPropertyUtilForObject(ExecutionState& state, size_t idx, const Value& newValue)
|
||||
{
|
||||
const ObjectStructureItem& item = m_structure->readProperty(state, idx);
|
||||
if (LIKELY(item.m_descriptor.isWritable())) {
|
||||
|
|
@ -259,21 +343,21 @@ protected:
|
|||
}
|
||||
}
|
||||
|
||||
Value getOwnProperty(ExecutionState& state, size_t idx, Object* receiver)
|
||||
Value getOwnPropertyUtilForObject(ExecutionState& state, size_t idx, Object* receiver)
|
||||
{
|
||||
const ObjectStructureItem& item = m_structure->readProperty(state, idx);
|
||||
if (item.m_descriptor.isDataProperty()) {
|
||||
return getOwnDataProperty(state, idx, receiver);
|
||||
return getOwnDataPropertyUtilForObject(state, idx, receiver);
|
||||
} else {
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
bool setOwnProperty(ExecutionState& state, size_t idx, const Value& newValue)
|
||||
bool setOwnPropertyUtilForObject(ExecutionState& state, size_t idx, const Value& newValue)
|
||||
{
|
||||
const ObjectStructureItem& item = m_structure->readProperty(state, idx);
|
||||
if (item.m_descriptor.isDataProperty()) {
|
||||
return setOwnDataProperty(state, idx, newValue);
|
||||
return setOwnDataPropertyUtilForObject(state, idx, newValue);
|
||||
} else {
|
||||
RELEASE_ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
|
@ -281,7 +365,7 @@ protected:
|
|||
|
||||
void setOwnPropertyThrowsExceptionWhenStrictMode(ExecutionState& state, size_t idx, const Value& newValue)
|
||||
{
|
||||
if (UNLIKELY(!setOwnProperty(state, idx, newValue))) {
|
||||
if (UNLIKELY(!setOwnPropertyUtilForObject(state, idx, newValue))) {
|
||||
throwCannotWriteError(state, m_structure->readProperty(state, idx).m_propertyName);
|
||||
}
|
||||
}
|
||||
|
|
@ -318,18 +402,7 @@ protected:
|
|||
Value getPrototypeSlowCase(ExecutionState& state);
|
||||
bool setPrototypeSlowCase(ExecutionState& state, const Value& value);
|
||||
|
||||
bool defineOwnProperty(ExecutionState& state, String* P, const ObjectPropertyDescriptorForDefineOwnProperty& desc);
|
||||
bool defineOwnProperty(ExecutionState& state, const PropertyName& P, const ObjectPropertyDescriptorForDefineOwnProperty& desc);
|
||||
bool set(ExecutionState& state, String* P, const Value& v)
|
||||
{
|
||||
return set(state, P, v, this);
|
||||
}
|
||||
bool set(ExecutionState& state, String* P, const Value& v, Object* receiver);
|
||||
bool set(ExecutionState& state, const PropertyName& P, const Value& v)
|
||||
{
|
||||
return set(state, P, v, this);
|
||||
}
|
||||
bool set(ExecutionState& state, const PropertyName& P, const Value& v, Object* receiver);
|
||||
bool set(ExecutionState& state, const ObjectPropertyName& P, const Value& v, Object* receiver);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ public:
|
|||
}
|
||||
|
||||
PropertyName(ExecutionState& state, String* string);
|
||||
|
||||
String* string() const
|
||||
{
|
||||
if (hasAtomicString()) {
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ Value Value::toPrimitiveSlowCase(ExecutionState& state, PrimitiveTypeHint prefer
|
|||
ASSERT(!isPrimitive());
|
||||
Object* obj = asObject();
|
||||
if (preferredType == PrimitiveTypeHint::PreferString) {
|
||||
Value toString = obj->get(state, PropertyName(state.context()->staticStrings().toString)).m_value;
|
||||
Value toString = obj->get(state, ObjectPropertyName(state.context()->staticStrings().toString)).value();
|
||||
if (toString.isFunction()) {
|
||||
Value ret = toString.asFunction()->call(state, obj, 0, NULL);
|
||||
if (ret.isPrimitive()) {
|
||||
|
|
@ -82,7 +82,7 @@ Value Value::toPrimitiveSlowCase(ExecutionState& state, PrimitiveTypeHint prefer
|
|||
}
|
||||
}
|
||||
|
||||
Value valueOf = obj->get(state, PropertyName(state.context()->staticStrings().valueOf)).m_value;
|
||||
Value valueOf = obj->get(state, ObjectPropertyName(state.context()->staticStrings().valueOf)).value();
|
||||
if (valueOf.isFunction()) {
|
||||
Value ret = valueOf.asFunction()->call(state, obj, 0, NULL);
|
||||
if (ret.isPrimitive()) {
|
||||
|
|
@ -90,7 +90,7 @@ Value Value::toPrimitiveSlowCase(ExecutionState& state, PrimitiveTypeHint prefer
|
|||
}
|
||||
}
|
||||
} else { // preferNumber
|
||||
Value valueOf = obj->get(state, PropertyName(state.context()->staticStrings().valueOf)).m_value;
|
||||
Value valueOf = obj->get(state, ObjectPropertyName(state.context()->staticStrings().valueOf)).value();
|
||||
if (valueOf.isFunction()) {
|
||||
Value ret = valueOf.asFunction()->call(state, obj, 0, NULL);
|
||||
if (ret.isPrimitive()) {
|
||||
|
|
@ -98,7 +98,7 @@ Value Value::toPrimitiveSlowCase(ExecutionState& state, PrimitiveTypeHint prefer
|
|||
}
|
||||
}
|
||||
|
||||
Value toString = obj->get(state, PropertyName(state.context()->staticStrings().toString)).m_value;
|
||||
Value toString = obj->get(state, ObjectPropertyName(state.context()->staticStrings().toString)).value();
|
||||
if (toString.isFunction()) {
|
||||
Value ret = toString.asFunction()->call(state, obj, 0, NULL);
|
||||
if (ret.isPrimitive()) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue