1. redesign Object api

2. implement ObjectPropertyName type

Signed-off-by: seonghyun kim <sh8281.kim@samsung.com>
This commit is contained in:
seonghyun kim 2016-12-07 22:10:23 +09:00
commit f2e8463092
18 changed files with 296 additions and 256 deletions

View file

@ -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);
}
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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());
}

View file

@ -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)

View file

@ -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)));

View file

@ -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)

View file

@ -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)));
}

View file

@ -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)));
}

View file

@ -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)));
}

View file

@ -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)));
}

View file

@ -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)));
}

View file

@ -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)));
}

View file

@ -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)));
}

View file

@ -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);
}
}

View file

@ -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);
};
}

View file

@ -28,7 +28,6 @@ public:
}
PropertyName(ExecutionState& state, String* string);
String* string() const
{
if (hasAtomicString()) {

View file

@ -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()) {