summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/JSObject.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSObject.h')
-rw-r--r--Source/JavaScriptCore/runtime/JSObject.h140
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())) {