diff options
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSObject.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSObject.h | 140 |
1 files changed, 78 insertions, 62 deletions
diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index e26012dd9..433249c20 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -55,7 +55,7 @@ namespace JSC { class Structure; struct HashTable; - JSObject* throwTypeError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*, const UString&); extern JS_EXPORTDATA const char* StrictModeReadonlyPropertyWriteError; // ECMA 262-3 8.6.1 @@ -66,8 +66,7 @@ namespace JSC { DontEnum = 1 << 2, // property doesn't appear in (for .. in ..) DontDelete = 1 << 3, // property can't be deleted Function = 1 << 4, // property is a function - only used by static hashtables - Getter = 1 << 5, // property is a getter - Setter = 1 << 6 // property is a setter + Accessor = 1 << 5, // property is a getter/setter }; class JSObject : public JSCell { @@ -75,18 +74,21 @@ namespace JSC { friend class JIT; friend class JSCell; friend class MarkedBlock; - friend bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot); + JS_EXPORT_PRIVATE friend bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* thisObj, const Identifier& propertyName, PropertySlot& slot); + + enum PutMode { + PutModePut, + PutModeDefineOwnProperty, + }; public: typedef JSCell Base; - static void destroy(JSCell*); - - static void visitChildren(JSCell*, SlotVisitor&); + JS_EXPORT_PRIVATE static void destroy(JSCell*); - static UString className(const JSObject*); + JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); - static void finalize(JSCell*); + JS_EXPORT_PRIVATE static UString className(const JSObject*); JSValue prototype() const; void setPrototype(JSGlobalData&, JSValue prototype); @@ -99,43 +101,50 @@ namespace JSC { bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); - bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); + JS_EXPORT_PRIVATE bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); - static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); - static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); - - static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); - - static void putWithAttributes(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); - void putWithAttributes(JSGlobalData*, const Identifier& propertyName, JSValue, unsigned attributes); + JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); + JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); + + JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); + JS_EXPORT_PRIVATE static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue); + + // putDirect is effectively an unchecked vesion of 'defineOwnProperty': + // - the prototype chain is not consulted + // - accessors are not called. + // - attributes will be respected (after the call the property will exist with the given attributes) + JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); + void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0); + void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&); + void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes = 0); + void putDirectAccessor(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attributes); bool propertyIsEnumerable(ExecState*, const Identifier& propertyName) const; - bool hasProperty(ExecState*, const Identifier& propertyName) const; - bool hasProperty(ExecState*, unsigned propertyName) const; + JS_EXPORT_PRIVATE bool hasProperty(ExecState*, const Identifier& propertyName) const; + JS_EXPORT_PRIVATE bool hasProperty(ExecState*, unsigned propertyName) const; bool hasOwnProperty(ExecState*, const Identifier& propertyName) const; - static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); - static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); + JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, const Identifier& propertyName); + JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName); - static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); + JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); - static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty); + JS_EXPORT_PRIVATE static bool hasInstance(JSObject*, ExecState*, JSValue, JSValue prototypeProperty); - static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); - static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); + JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; - bool toBoolean(ExecState*) const; + JS_EXPORT_PRIVATE bool toBoolean(ExecState*) const; bool getPrimitiveNumber(ExecState*, double& number, JSValue&) const; - double toNumber(ExecState*) const; - UString toString(ExecState*) const; + JS_EXPORT_PRIVATE double toNumber(ExecState*) const; + JS_EXPORT_PRIVATE JSString* toString(ExecState*) const; // NOTE: JSObject and its subclasses must be able to gracefully handle ExecState* = 0, // because this call may come from inside the compiler. - static JSObject* toThisObject(JSCell*, ExecState*); + JS_EXPORT_PRIVATE static JSObject* toThisObject(JSCell*, ExecState*); JSObject* unwrappedObject(); bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const; @@ -171,35 +180,37 @@ namespace JSC { bool hasCustomProperties() { return structure()->didTransition(); } bool hasGetterSetterProperties() { return structure()->hasGetterSetterProperties(); } - bool putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&); - void putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr = 0); - bool putDirect(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&); - - void putDirectWithoutTransition(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr = 0); + // putOwnDataProperty has 'put' like semantics, however this method: + // - assumes the object contains no own getter/setter properties. + // - provides no special handling for __proto__ + // - does not walk the prototype chain (to check for accessors or non-writable properties). + // This is used by JSActivation. + bool putOwnDataProperty(JSGlobalData&, const Identifier& propertyName, JSValue, PutPropertySlot&); // Fast access to known property offsets. JSValue getDirectOffset(size_t offset) const { return propertyStorage()[offset].get(); } void putDirectOffset(JSGlobalData& globalData, size_t offset, JSValue value) { propertyStorage()[offset].set(globalData, this, value); } void putUndefinedAtDirectOffset(size_t offset) { propertyStorage()[offset].setUndefined(); } - void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase<Unknown>* location); + JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, WriteBarrierBase<Unknown>* location); void initializeGetterSetterProperty(ExecState*, const Identifier&, GetterSetter*, unsigned attributes); - static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0); - static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0); - JSValue lookupGetter(ExecState*, const Identifier& propertyName); - JSValue lookupSetter(ExecState*, const Identifier& propertyName); - static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); + JS_EXPORT_PRIVATE static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0); + JS_EXPORT_PRIVATE static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0); + JS_EXPORT_PRIVATE JSValue lookupGetter(ExecState*, const Identifier& propertyName); + JS_EXPORT_PRIVATE JSValue lookupSetter(ExecState*, const Identifier& propertyName); + JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); bool isGlobalObject() const; bool isVariableObject() const; + bool isStaticScopeObject() const; bool isActivationObject() const; bool isErrorInstance() const; bool isGlobalThis() const; void seal(JSGlobalData&); void freeze(JSGlobalData&); - void preventExtensions(JSGlobalData&); + JS_EXPORT_PRIVATE void preventExtensions(JSGlobalData&); bool isSealed(JSGlobalData& globalData) { return structure()->isSealed(globalData); } bool isFrozen(JSGlobalData& globalData) { return structure()->isFrozen(globalData); } bool isExtensible() { return structure()->isExtensible(); } @@ -207,7 +218,7 @@ namespace JSC { bool staticFunctionsReified() { return structure()->staticFunctionsReified(); } void reifyStaticFunctionsForDelete(ExecState* exec); - void allocatePropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize); + JS_EXPORT_PRIVATE void allocatePropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize); bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage.get()) == static_cast<const void*>(this + 1); } void* addressOfPropertyStorage() @@ -281,7 +292,8 @@ namespace JSC { return &propertyStorage()[offset]; } - bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, bool checkReadOnly, PutPropertySlot&, JSCell*); + template<PutMode> + bool putDirectInternal(JSGlobalData&, const Identifier& propertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*); bool inlineGetOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); @@ -317,7 +329,7 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } - static void destroy(JSCell*); + JS_EXPORT_PRIVATE static void destroy(JSCell*); protected: explicit JSNonFinalObject(JSGlobalData& globalData, Structure* structure) @@ -417,6 +429,11 @@ inline bool JSObject::isVariableObject() const return structure()->typeInfo().type() >= VariableObjectType; } +inline bool JSObject::isStaticScopeObject() const +{ + return structure()->typeInfo().type() == StaticScopeObjectType; +} + inline bool JSObject::isActivationObject() const { return structure()->typeInfo().type() == ActivationObjectType; @@ -628,9 +645,11 @@ inline JSValue JSObject::get(ExecState* exec, unsigned propertyName) const return jsUndefined(); } -inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot, JSCell* specificFunction) +template<JSObject::PutMode mode> +inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction) { ASSERT(value); + ASSERT(value.isGetterSetter() == !!(attributes & Accessor)); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); if (structure()->isDictionary()) { @@ -642,7 +661,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi // or the new value is different, then despecify. if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) structure()->despecifyDictionaryFunction(globalData, propertyName); - if (checkReadOnly && currentAttributes & ReadOnly) + if ((mode == PutModePut) && currentAttributes & ReadOnly) return false; putDirectOffset(globalData, offset, value); @@ -657,7 +676,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi return true; } - if (checkReadOnly && !isExtensible()) + if ((mode == PutModePut) && !isExtensible()) return false; size_t currentCapacity = structure()->propertyStorageCapacity(); @@ -693,7 +712,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi JSCell* currentSpecificFunction; offset = structure()->get(globalData, propertyName, currentAttributes, currentSpecificFunction); if (offset != WTF::notFound) { - if (checkReadOnly && currentAttributes & ReadOnly) + if ((mode == PutModePut) && currentAttributes & ReadOnly) return false; // There are three possibilities here: @@ -721,7 +740,7 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi return true; } - if (checkReadOnly && !isExtensible()) + if ((mode == PutModePut) && !isExtensible()) return false; Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset); @@ -739,27 +758,31 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi return true; } -inline bool JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes, bool checkReadOnly, PutPropertySlot& slot) +inline bool JSObject::putOwnDataProperty(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { ASSERT(value); ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this)); + ASSERT(!structure()->hasGetterSetterProperties()); - return putDirectInternal(globalData, propertyName, value, attributes, checkReadOnly, slot, getJSFunction(value)); + return putDirectInternal<PutModePut>(globalData, propertyName, value, 0, slot, getJSFunction(value)); } inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) { + ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); PutPropertySlot slot; - putDirectInternal(globalData, propertyName, value, attributes, false, slot, getJSFunction(value)); + putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, attributes, slot, getJSFunction(value)); } -inline bool JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) +inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { - return putDirectInternal(globalData, propertyName, value, 0, false, slot, getJSFunction(value)); + ASSERT(!value.isGetterSetter()); + putDirectInternal<PutModeDefineOwnProperty>(globalData, propertyName, value, 0, slot, getJSFunction(value)); } inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) { + ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); size_t currentCapacity = structure()->propertyStorageCapacity(); size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getJSFunction(value)); if (currentCapacity != structure()->propertyStorageCapacity()) @@ -841,13 +864,6 @@ inline void JSValue::put(ExecState* exec, const Identifier& propertyName, JSValu asCell()->methodTable()->put(asCell(), exec, propertyName, value, slot); } -inline void JSValue::putDirect(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) -{ - ASSERT(isCell() && isObject()); - if (!asObject(asCell())->putDirect(exec->globalData(), propertyName, value, slot) && slot.isStrictMode()) - throwTypeError(exec, StrictModeReadonlyPropertyWriteError); -} - inline void JSValue::put(ExecState* exec, unsigned propertyName, JSValue value) { if (UNLIKELY(!isCell())) { |