diff options
Diffstat (limited to 'JavaScriptCore/runtime/JSObject.cpp')
| -rw-r--r-- | JavaScriptCore/runtime/JSObject.cpp | 94 |
1 files changed, 65 insertions, 29 deletions
diff --git a/JavaScriptCore/runtime/JSObject.cpp b/JavaScriptCore/runtime/JSObject.cpp index d9500aa..30e40e4 100644 --- a/JavaScriptCore/runtime/JSObject.cpp +++ b/JavaScriptCore/runtime/JSObject.cpp @@ -27,6 +27,7 @@ #include "DatePrototype.h" #include "ErrorConstructor.h" #include "GetterSetter.h" +#include "JSFunction.h" #include "JSGlobalObject.h" #include "NativeErrorConstructor.h" #include "ObjectPrototype.h" @@ -42,6 +43,8 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSObject); +const char* StrictModeReadonlyPropertyWriteError = "Attempted to assign to readonly property."; + static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode) { // Add properties from the static hashtables of properties @@ -90,7 +93,7 @@ bool JSObject::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Proper static void throwSetterError(ExecState* exec) { - throwError(exec, TypeError, "setting a property that has only a getter"); + throwError(exec, createTypeError(exec, "setting a property that has only a getter")); } // ECMA 8.6.2.2 @@ -103,18 +106,8 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla. if (!value.isObject() && !value.isNull()) return; - - JSValue nextPrototypeValue = value; - while (nextPrototypeValue && nextPrototypeValue.isObject()) { - JSObject* nextPrototype = asObject(nextPrototypeValue)->unwrappedObject(); - if (nextPrototype == this) { - throwError(exec, GeneralError, "cyclic __proto__ value"); - return; - } - nextPrototypeValue = nextPrototype->prototype(); - } - - setPrototype(value); + if (!setPrototypeWithCycleCheck(value)) + throwError(exec, createError(exec, "cyclic __proto__ value")); return; } @@ -123,15 +116,19 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu for (JSObject* obj = this; !obj->structure()->hasGetterSetterProperties(); obj = asObject(prototype)) { prototype = obj->prototype(); if (prototype.isNull()) { - putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot); + if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } } unsigned attributes; JSCell* specificValue; - if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) + if ((m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) && attributes & ReadOnly) { + if (slot.isStrictMode()) + throwError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError)); return; + } for (JSObject* obj = this; ; obj = asObject(prototype)) { if (JSValue gs = obj->getDirect(propertyName)) { @@ -160,7 +157,8 @@ void JSObject::put(ExecState* exec, const Identifier& propertyName, JSValue valu break; } - putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot); + if (!putDirectInternal(exec->globalData(), propertyName, value, 0, true, slot) && slot.isStrictMode()) + throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; } @@ -170,6 +168,21 @@ void JSObject::put(ExecState* exec, unsigned propertyName, JSValue value) put(exec, Identifier::from(exec, propertyName), value, slot); } +void JSObject::putWithAttributes(JSGlobalData* globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +{ + putDirectInternal(*globalData, propertyName, value, attributes, checkReadOnly, slot); +} + +void JSObject::putWithAttributes(JSGlobalData* globalData, const Identifier& propertyName, JSValue value, unsigned attributes) +{ + putDirectInternal(*globalData, propertyName, value, attributes); +} + +void JSObject::putWithAttributes(JSGlobalData* globalData, unsigned propertyName, JSValue value, unsigned attributes) +{ + putWithAttributes(globalData, Identifier::from(globalData, propertyName), value, attributes); +} + void JSObject::putWithAttributes(ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) { putDirectInternal(exec->globalData(), propertyName, value, attributes, checkReadOnly, slot); @@ -233,7 +246,7 @@ static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSO { JSValue function = object->get(exec, propertyName); CallData callData; - CallType callType = function.getCallData(callData); + CallType callType = getCallData(function, callData); if (callType == CallTypeNone) return exec->exception(); @@ -280,7 +293,7 @@ JSValue JSObject::defaultValue(ExecState* exec, PreferredPrimitiveType hint) con ASSERT(!exec->hadException()); - return throwError(exec, TypeError, "No default value"); + return throwError(exec, createTypeError(exec, "No default value")); } const HashEntry* JSObject::findPropertyHashEntry(ExecState* exec, const Identifier& propertyName) const @@ -392,7 +405,7 @@ bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue proto) return false; if (!proto.isObject()) { - throwError(exec, TypeError, "instanceof called on an object with an invalid prototype property."); + throwError(exec, createTypeError(exec, "instanceof called on an object with an invalid prototype property.")); return false; } @@ -483,6 +496,11 @@ JSObject* JSObject::toThisObject(ExecState*) const return const_cast<JSObject*>(this); } +JSValue JSObject::toStrictThisObject(ExecState*) const +{ + return const_cast<JSObject*>(this); +} + JSObject* JSObject::unwrappedObject() { return this; @@ -509,16 +527,29 @@ void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, un putDirectFunction(Identifier(exec, function->name(exec)), function, attr); } +void JSObject::putDirectFunction(ExecState* exec, JSFunction* function, unsigned attr) +{ + putDirectFunction(Identifier(exec, function->name(exec)), function, attr); +} + void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr) { putDirectFunctionWithoutTransition(Identifier(exec, function->name(exec)), function, attr); } +void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, JSFunction* function, unsigned attr) +{ + putDirectFunctionWithoutTransition(Identifier(exec, function->name(exec)), function, attr); +} + NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue* location) { - if (JSObject* getterFunction = asGetterSetter(*location)->getter()) - slot.setGetterSlot(getterFunction); - else + if (JSObject* getterFunction = asGetterSetter(*location)->getter()) { + if (!structure()->isDictionary()) + slot.setCacheableGetterSlot(this, getterFunction, offsetForLocation(location)); + else + slot.setGetterSlot(getterFunction); + } else slot.setUndefined(); } @@ -590,12 +621,12 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName if (!current.configurable()) { if (descriptor.configurable()) { if (throwException) - throwError(exec, TypeError, "Attempting to configurable attribute of unconfigurable property."); + throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property.")); return false; } if (descriptor.enumerablePresent() && descriptor.enumerable() != current.enumerable()) { if (throwException) - throwError(exec, TypeError, "Attempting to change enumerable attribute of unconfigurable property."); + throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property.")); return false; } } @@ -613,7 +644,7 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName if (descriptor.isDataDescriptor() != current.isDataDescriptor()) { if (!current.configurable()) { if (throwException) - throwError(exec, TypeError, "Attempting to change access mechanism for an unconfigurable property."); + throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property.")); return false; } deleteProperty(exec, propertyName); @@ -625,13 +656,13 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName if (!current.configurable()) { if (!current.writable() && descriptor.writable()) { if (throwException) - throwError(exec, TypeError, "Attempting to change writable attribute of unconfigurable property."); + throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property.")); return false; } if (!current.writable()) { if (descriptor.value() || !JSValue::strictEqual(exec, current.value(), descriptor.value())) { if (throwException) - throwError(exec, TypeError, "Attempting to change value of a readonly property."); + throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property.")); return false; } } @@ -653,12 +684,12 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName if (!current.configurable()) { if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) { if (throwException) - throwError(exec, TypeError, "Attempting to change the setter of an unconfigurable property."); + throwError(exec, createTypeError(exec, "Attempting to change the setter of an unconfigurable property.")); return false; } if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) { if (throwException) - throwError(exec, TypeError, "Attempting to change the getter of an unconfigurable property."); + throwError(exec, createTypeError(exec, "Attempting to change the getter of an unconfigurable property.")); return false; } } @@ -683,4 +714,9 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName return true; } +JSObject* throwTypeError(ExecState* exec, const UString& message) +{ + return throwError(exec, createTypeError(exec, message)); +} + } // namespace JSC |
