Commit 5e55df2c authored by barraclough@apple.com's avatar barraclough@apple.com

https://bugs.webkit.org/show_bug.cgi?id=119972

Add attributes field to PropertySlot

Reviewed by Geoff Garen.

For all JSC types, this makes getOwnPropertyDescriptor redundant.
There will be a bit more hacking required in WebCore to remove GOPD whilst maintaining current behaviour.
(Current behaviour is in many ways broken, particularly in that GOPD & GOPS are inconsistent, but we should fix incrementally).

Source/JavaScriptCore: 

No performance impact.

* runtime/PropertySlot.h:
(JSC::PropertySlot::setValue):
(JSC::PropertySlot::setCustom):
(JSC::PropertySlot::setCacheableCustom):
(JSC::PropertySlot::setCustomIndex):
(JSC::PropertySlot::setGetterSlot):
(JSC::PropertySlot::setCacheableGetterSlot):
    - These mathods now all require 'attributes'.
* runtime/JSObject.h:
(JSC::JSObject::getDirect):
(JSC::JSObject::getDirectOffset):
(JSC::JSObject::inlineGetOwnPropertySlot):
    - Added variants of getDirect, getDirectOffset that return the attributes.
* API/JSCallbackObjectFunctions.h:
(JSC::::getOwnPropertySlot):
* runtime/Arguments.cpp:
(JSC::Arguments::getOwnPropertySlotByIndex):
(JSC::Arguments::getOwnPropertySlot):
* runtime/JSActivation.cpp:
(JSC::JSActivation::symbolTableGet):
(JSC::JSActivation::getOwnPropertySlot):
* runtime/JSArray.cpp:
(JSC::JSArray::getOwnPropertySlot):
* runtime/JSArrayBuffer.cpp:
(JSC::JSArrayBuffer::getOwnPropertySlot):
* runtime/JSArrayBufferView.cpp:
(JSC::JSArrayBufferView::getOwnPropertySlot):
* runtime/JSDataView.cpp:
(JSC::JSDataView::getOwnPropertySlot):
* runtime/JSFunction.cpp:
(JSC::JSFunction::getOwnPropertySlot):
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::::getOwnPropertySlot):
(JSC::::getOwnPropertySlotByIndex):
* runtime/JSObject.cpp:
(JSC::JSObject::getOwnPropertySlotByIndex):
(JSC::JSObject::fillGetterPropertySlot):
* runtime/JSString.h:
(JSC::JSString::getStringPropertySlot):
* runtime/JSSymbolTableObject.h:
(JSC::symbolTableGet):
* runtime/Lookup.cpp:
(JSC::setUpStaticFunctionSlot):
* runtime/Lookup.h:
(JSC::getStaticPropertySlot):
(JSC::getStaticPropertyDescriptor):
(JSC::getStaticValueSlot):
(JSC::getStaticValueDescriptor):
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::getOwnPropertySlot):
* runtime/SparseArrayValueMap.cpp:
(JSC::SparseArrayEntry::get):
    - Pass attributes to PropertySlot::set* methods.

Source/WebCore: 

* bindings/js/JSCSSStyleDeclarationCustom.cpp:
(WebCore::JSCSSStyleDeclaration::getOwnPropertySlotDelegate):
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::getOwnPropertySlot):
(WebCore::JSDOMWindow::getOwnPropertySlotByIndex):
(WebCore::JSDOMWindow::getOwnPropertyDescriptor):
* bindings/js/JSHistoryCustom.cpp:
(WebCore::JSHistory::getOwnPropertySlotDelegate):
(WebCore::JSHistory::getOwnPropertyDescriptorDelegate):
* bindings/js/JSLocationCustom.cpp:
(WebCore::JSLocation::getOwnPropertySlotDelegate):
(WebCore::JSLocation::getOwnPropertyDescriptorDelegate):
* bindings/js/JSPluginElementFunctions.cpp:
(WebCore::runtimeObjectCustomGetOwnPropertySlot):
(WebCore::runtimeObjectCustomGetOwnPropertyDescriptor):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateGetOwnPropertySlotBody):
(GenerateGetOwnPropertyDescriptorBody):
(GenerateImplementation):
* bridge/runtime_array.cpp:
(JSC::RuntimeArray::getOwnPropertySlot):
(JSC::RuntimeArray::getOwnPropertyDescriptor):
(JSC::RuntimeArray::getOwnPropertySlotByIndex):
* bridge/runtime_method.cpp:
(JSC::RuntimeMethod::getOwnPropertySlot):
(JSC::RuntimeMethod::getOwnPropertyDescriptor):
* bridge/runtime_object.cpp:
(JSC::Bindings::RuntimeObject::getOwnPropertySlot):
(JSC::Bindings::RuntimeObject::getOwnPropertyDescriptor):
    - Pass attributes to PropertySlot::set* methods.

Source/WebKit2: 

* WebProcess/Plugins/Netscape/JSNPObject.cpp:
(WebKit::JSNPObject::getOwnPropertySlot):
(WebKit::JSNPObject::getOwnPropertyDescriptor):
    - Pass attributes to PropertySlot::set* methods.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@154253 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent f3971948
......@@ -137,7 +137,7 @@ bool JSCallbackObject<Parent>::getOwnPropertySlot(JSObject* object, ExecState* e
propertyNameRef = OpaqueJSString::create(name);
APICallbackShim callbackShim(exec);
if (hasProperty(ctx, thisRef, propertyNameRef.get())) {
slot.setCustom(thisObject, callbackGetter);
slot.setCustom(thisObject, ReadOnly | DontEnum, callbackGetter);
return true;
}
} else if (JSObjectGetPropertyCallback getProperty = jsClass->getProperty) {
......@@ -151,11 +151,11 @@ bool JSCallbackObject<Parent>::getOwnPropertySlot(JSObject* object, ExecState* e
}
if (exception) {
throwError(exec, toJS(exec, exception));
slot.setValue(thisObject, jsUndefined());
slot.setValue(thisObject, ReadOnly | DontEnum, jsUndefined());
return true;
}
if (value) {
slot.setValue(thisObject, toJS(exec, value));
slot.setValue(thisObject, ReadOnly | DontEnum, toJS(exec, value));
return true;
}
}
......@@ -164,7 +164,7 @@ bool JSCallbackObject<Parent>::getOwnPropertySlot(JSObject* object, ExecState* e
if (staticValues->contains(name)) {
JSValue value = thisObject->getStaticValue(exec, propertyName);
if (value) {
slot.setValue(thisObject, value);
slot.setValue(thisObject, ReadOnly | DontEnum, value);
return true;
}
}
......@@ -172,7 +172,7 @@ bool JSCallbackObject<Parent>::getOwnPropertySlot(JSObject* object, ExecState* e
if (OpaqueJSClassStaticFunctionsTable* staticFunctions = jsClass->staticFunctions(exec)) {
if (staticFunctions->contains(name)) {
slot.setCustom(thisObject, staticFunctionGetter);
slot.setCustom(thisObject, ReadOnly | DontEnum, staticFunctionGetter);
return true;
}
}
......
2013-08-18 Gavin Barraclough <barraclough@apple.com>
https://bugs.webkit.org/show_bug.cgi?id=119972
Add attributes field to PropertySlot
Reviewed by Geoff Garen.
For all JSC types, this makes getOwnPropertyDescriptor redundant.
There will be a bit more hacking required in WebCore to remove GOPD whilst maintaining current behaviour.
(Current behaviour is in many ways broken, particularly in that GOPD & GOPS are inconsistent, but we should fix incrementally).
No performance impact.
* runtime/PropertySlot.h:
(JSC::PropertySlot::setValue):
(JSC::PropertySlot::setCustom):
(JSC::PropertySlot::setCacheableCustom):
(JSC::PropertySlot::setCustomIndex):
(JSC::PropertySlot::setGetterSlot):
(JSC::PropertySlot::setCacheableGetterSlot):
- These mathods now all require 'attributes'.
* runtime/JSObject.h:
(JSC::JSObject::getDirect):
(JSC::JSObject::getDirectOffset):
(JSC::JSObject::inlineGetOwnPropertySlot):
- Added variants of getDirect, getDirectOffset that return the attributes.
* API/JSCallbackObjectFunctions.h:
(JSC::::getOwnPropertySlot):
* runtime/Arguments.cpp:
(JSC::Arguments::getOwnPropertySlotByIndex):
(JSC::Arguments::getOwnPropertySlot):
* runtime/JSActivation.cpp:
(JSC::JSActivation::symbolTableGet):
(JSC::JSActivation::getOwnPropertySlot):
* runtime/JSArray.cpp:
(JSC::JSArray::getOwnPropertySlot):
* runtime/JSArrayBuffer.cpp:
(JSC::JSArrayBuffer::getOwnPropertySlot):
* runtime/JSArrayBufferView.cpp:
(JSC::JSArrayBufferView::getOwnPropertySlot):
* runtime/JSDataView.cpp:
(JSC::JSDataView::getOwnPropertySlot):
* runtime/JSFunction.cpp:
(JSC::JSFunction::getOwnPropertySlot):
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::::getOwnPropertySlot):
(JSC::::getOwnPropertySlotByIndex):
* runtime/JSObject.cpp:
(JSC::JSObject::getOwnPropertySlotByIndex):
(JSC::JSObject::fillGetterPropertySlot):
* runtime/JSString.h:
(JSC::JSString::getStringPropertySlot):
* runtime/JSSymbolTableObject.h:
(JSC::symbolTableGet):
* runtime/Lookup.cpp:
(JSC::setUpStaticFunctionSlot):
* runtime/Lookup.h:
(JSC::getStaticPropertySlot):
(JSC::getStaticPropertyDescriptor):
(JSC::getStaticValueSlot):
(JSC::getStaticValueDescriptor):
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::getOwnPropertySlot):
* runtime/SparseArrayValueMap.cpp:
(JSC::SparseArrayEntry::get):
- Pass attributes to PropertySlot::set* methods.
2013-08-17 Mark Hahnenberg <mhahnenberg@apple.com>
<https://webkit.org/b/119919> Concurrent JIT crashes in various fast/js/dfg-* tests while the main thread is setting innerHTML
......
......@@ -94,7 +94,7 @@ bool Arguments::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, uns
{
Arguments* thisObject = jsCast<Arguments*>(object);
if (JSValue value = thisObject->tryGetArgument(i)) {
slot.setValue(thisObject, value);
slot.setValue(thisObject, None, value);
return true;
}
......@@ -129,18 +129,18 @@ bool Arguments::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyNa
unsigned i = propertyName.asIndex();
if (JSValue value = thisObject->tryGetArgument(i)) {
RELEASE_ASSERT(i < PropertyName::NotAnIndex);
slot.setValue(thisObject, value);
slot.setValue(thisObject, None, value);
return true;
}
if (propertyName == exec->propertyNames().length && LIKELY(!thisObject->m_overrodeLength)) {
slot.setValue(thisObject, jsNumber(thisObject->m_numArguments));
slot.setValue(thisObject, DontEnum, jsNumber(thisObject->m_numArguments));
return true;
}
if (propertyName == exec->propertyNames().callee && LIKELY(!thisObject->m_overrodeCallee)) {
if (!thisObject->m_isStrictMode) {
slot.setValue(thisObject, thisObject->m_callee.get());
slot.setValue(thisObject, DontEnum, thisObject->m_callee.get());
return true;
}
thisObject->createStrictModeCalleeIfNecessary(exec);
......
......@@ -66,7 +66,7 @@ inline bool JSActivation::symbolTableGet(PropertyName propertyName, PropertySlot
if (isTornOff() && !isValid(entry))
return false;
slot.setValue(this, registerAt(entry.getIndex()).get());
slot.setValue(this, DontEnum, registerAt(entry.getIndex()).get());
return true;
}
......@@ -157,7 +157,7 @@ bool JSActivation::getOwnPropertySlot(JSObject* object, ExecState* exec, Propert
if (propertyName == exec->propertyNames().arguments) {
// Defend against the inspector asking for the arguments object after it has been optimized out.
if (!thisObject->isTornOff()) {
slot.setCustom(thisObject, thisObject->getArgumentsGetter());
slot.setCustom(thisObject, DontEnum, thisObject->getArgumentsGetter());
return true;
}
}
......@@ -165,8 +165,9 @@ bool JSActivation::getOwnPropertySlot(JSObject* object, ExecState* exec, Propert
if (thisObject->symbolTableGet(propertyName, slot))
return true;
if (JSValue value = thisObject->getDirect(exec->vm(), propertyName)) {
slot.setValue(thisObject, value);
unsigned attributes;
if (JSValue value = thisObject->getDirect(exec->vm(), propertyName, attributes)) {
slot.setValue(thisObject, attributes, value);
return true;
}
......
......@@ -181,7 +181,8 @@ bool JSArray::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName
{
JSArray* thisObject = jsCast<JSArray*>(object);
if (propertyName == exec->propertyNames().length) {
slot.setValue(thisObject, jsNumber(thisObject->length()));
unsigned attributes = thisObject->isLengthWritable() ? DontDelete | DontEnum : DontDelete | DontEnum | ReadOnly;
slot.setValue(thisObject, attributes, jsNumber(thisObject->length()));
return true;
}
......
......@@ -71,7 +71,7 @@ bool JSArrayBuffer::getOwnPropertySlot(
JSArrayBuffer* thisObject = jsCast<JSArrayBuffer*>(object);
if (propertyName == exec->propertyNames().byteLength) {
slot.setValue(thisObject, jsNumber(thisObject->impl()->byteLength()));
slot.setValue(thisObject, DontDelete | ReadOnly, jsNumber(thisObject->impl()->byteLength()));
return true;
}
......
......@@ -125,13 +125,13 @@ bool JSArrayBufferView::getOwnPropertySlot(
{
JSArrayBufferView* thisObject = jsCast<JSArrayBufferView*>(object);
if (propertyName == exec->propertyNames().byteOffset) {
slot.setValue(thisObject, jsNumber(thisObject->byteOffset()));
slot.setValue(thisObject, DontDelete | ReadOnly, jsNumber(thisObject->byteOffset()));
return true;
}
if (propertyName == exec->propertyNames().buffer) {
slot.setValue(
thisObject, exec->vm().m_typedArrayController->toJS(
thisObject, DontDelete | ReadOnly, exec->vm().m_typedArrayController->toJS(
exec, thisObject->globalObject(), thisObject->buffer()));
return true;
}
......
......@@ -88,7 +88,7 @@ bool JSDataView::getOwnPropertySlot(
{
JSDataView* thisObject = jsCast<JSDataView*>(object);
if (propertyName == exec->propertyNames().byteLength) {
slot.setValue(thisObject, jsNumber(thisObject->m_length));
slot.setValue(thisObject, DontEnum | ReadOnly, jsNumber(thisObject->m_length));
return true;
}
......
......@@ -248,16 +248,17 @@ bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyN
if (propertyName == exec->propertyNames().prototype) {
VM& vm = exec->vm();
PropertyOffset offset = thisObject->getDirectOffset(vm, propertyName);
unsigned attributes;
PropertyOffset offset = thisObject->getDirectOffset(vm, propertyName, attributes);
if (!isValidOffset(offset)) {
JSObject* prototype = constructEmptyObject(exec);
prototype->putDirect(vm, exec->propertyNames().constructor, thisObject, DontEnum);
thisObject->putDirect(vm, exec->propertyNames().prototype, prototype, DontDelete | DontEnum);
offset = thisObject->getDirectOffset(vm, exec->propertyNames().prototype);
offset = thisObject->getDirectOffset(vm, exec->propertyNames().prototype, attributes);
ASSERT(isValidOffset(offset));
}
slot.setValue(thisObject, thisObject->getDirect(offset), offset);
slot.setValue(thisObject, attributes, thisObject->getDirect(offset), offset);
}
if (propertyName == exec->propertyNames().arguments) {
......@@ -270,17 +271,17 @@ bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyN
}
return result;
}
slot.setCacheableCustom(thisObject, argumentsGetter);
slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, argumentsGetter);
return true;
}
if (propertyName == exec->propertyNames().length) {
slot.setCacheableCustom(thisObject, lengthGetter);
slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, lengthGetter);
return true;
}
if (propertyName == exec->propertyNames().name) {
slot.setCacheableCustom(thisObject, nameGetter);
slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, nameGetter);
return true;
}
......@@ -294,7 +295,7 @@ bool JSFunction::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyN
}
return result;
}
slot.setCacheableCustom(thisObject, callerGetter);
slot.setCacheableCustom(thisObject, ReadOnly | DontEnum | DontDelete, callerGetter);
return true;
}
......
......@@ -215,18 +215,18 @@ bool JSGenericTypedArrayView<Adaptor>::getOwnPropertySlot(
{
JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
if (propertyName == exec->propertyNames().length) {
slot.setValue(thisObject, jsNumber(thisObject->length()));
slot.setValue(thisObject, DontDelete | ReadOnly, jsNumber(thisObject->length()));
return true;
}
if (propertyName == exec->propertyNames().byteLength) {
slot.setValue(thisObject, jsNumber(thisObject->byteLength()));
slot.setValue(thisObject, DontDelete | ReadOnly, jsNumber(thisObject->byteLength()));
return true;
}
unsigned index = propertyName.asIndex();
if (index != PropertyName::NotAnIndex && thisObject->canGetIndexQuickly(index)) {
slot.setValue(thisObject, thisObject->getIndexQuickly(index));
slot.setValue(thisObject, DontDelete | ReadOnly, thisObject->getIndexQuickly(index));
return true;
}
......@@ -324,7 +324,7 @@ bool JSGenericTypedArrayView<Adaptor>::getOwnPropertySlotByIndex(
if (!thisObject->canGetIndexQuickly(propertyName))
return false;
slot.setValue(thisObject, thisObject->getIndexQuickly(propertyName));
slot.setValue(thisObject, None, thisObject->getIndexQuickly(propertyName));
return true;
}
......
......@@ -289,7 +289,7 @@ bool JSObject::getOwnPropertySlotByIndex(JSObject* thisObject, ExecState* exec,
JSValue value = butterfly->contiguous()[i].get();
if (value) {
slot.setValue(thisObject, value);
slot.setValue(thisObject, None, value);
return true;
}
......@@ -303,7 +303,7 @@ bool JSObject::getOwnPropertySlotByIndex(JSObject* thisObject, ExecState* exec,
double value = butterfly->contiguousDouble()[i];
if (value == value) {
slot.setValue(thisObject, JSValue(JSValue::EncodeAsDouble, value));
slot.setValue(thisObject, None, JSValue(JSValue::EncodeAsDouble, value));
return true;
}
......@@ -318,7 +318,7 @@ bool JSObject::getOwnPropertySlotByIndex(JSObject* thisObject, ExecState* exec,
if (i < storage->vectorLength()) {
JSValue value = storage->m_vector[i].get();
if (value) {
slot.setValue(thisObject, value);
slot.setValue(thisObject, None, value);
return true;
}
} else if (SparseArrayValueMap* map = storage->m_sparseMap.get()) {
......@@ -1625,14 +1625,14 @@ bool JSObject::removeDirect(VM& vm, PropertyName propertyName)
return true;
}
NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue getterSetter, PropertyOffset offset)
NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue getterSetter, unsigned attributes, PropertyOffset offset)
{
if (structure()->isDictionary()) {
slot.setGetterSlot(this, jsCast<GetterSetter*>(getterSetter));
slot.setGetterSlot(this, attributes, jsCast<GetterSetter*>(getterSetter));
return;
}
slot.setCacheableGetterSlot(this, jsCast<GetterSetter*>(getterSetter), offset);
slot.setCacheableGetterSlot(this, attributes, jsCast<GetterSetter*>(getterSetter), offset);
}
void JSObject::putIndexedDescriptor(ExecState* exec, SparseArrayEntry* entryInMap, PropertyDescriptor& descriptor, PropertyDescriptor& oldDescriptor)
......
......@@ -73,17 +73,6 @@ struct HashTable;
JS_EXPORT_PRIVATE JSObject* throwTypeError(ExecState*, const String&);
extern JS_EXPORTDATA const char* StrictModeReadonlyPropertyWriteError;
// ECMA 262-3 8.6.1
// Property attributes
enum Attribute {
None = 0,
ReadOnly = 1 << 1, // property can be only read, not written
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
Accessor = 1 << 5, // property is a getter/setter
};
COMPILE_ASSERT(None < FirstInternalAttribute, None_is_below_FirstInternalAttribute);
COMPILE_ASSERT(ReadOnly < FirstInternalAttribute, ReadOnly_is_below_FirstInternalAttribute);
COMPILE_ASSERT(DontEnum < FirstInternalAttribute, DontEnum_is_below_FirstInternalAttribute);
......@@ -510,6 +499,14 @@ public:
return offset != invalidOffset ? getDirect(offset) : JSValue();
}
JSValue getDirect(VM& vm, PropertyName propertyName, unsigned& attributes) const
{
JSCell* specific;
PropertyOffset offset = structure()->get(vm, propertyName, attributes, specific);
checkOffset(offset, structure()->inlineCapacity());
return offset != invalidOffset ? getDirect(offset) : JSValue();
}
PropertyOffset getDirectOffset(VM& vm, PropertyName propertyName)
{
PropertyOffset offset = structure()->get(vm, propertyName);
......@@ -517,6 +514,14 @@ public:
return offset;
}
PropertyOffset getDirectOffset(VM& vm, PropertyName propertyName, unsigned& attributes)
{
JSCell* specific;
PropertyOffset offset = structure()->get(vm, propertyName, attributes, specific);
checkOffset(offset, structure()->inlineCapacity());
return offset;
}
bool hasInlineStorage() const { return structure()->hasInlineStorage(); }
ConstPropertyStorage inlineStorageUnsafe() const
{
......@@ -936,7 +941,7 @@ private:
bool putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*);
bool inlineGetOwnPropertySlot(ExecState*, PropertyName, PropertySlot&);
JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, JSValue, PropertyOffset);
JS_EXPORT_PRIVATE void fillGetterPropertySlot(PropertySlot&, JSValue, unsigned, PropertyOffset);
const HashEntry* findPropertyHashEntry(ExecState*, PropertyName) const;
......@@ -1168,13 +1173,15 @@ inline JSValue JSObject::prototype() const
ALWAYS_INLINE bool JSObject::inlineGetOwnPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
PropertyOffset offset = structure()->get(exec->vm(), propertyName);
unsigned attributes;
JSCell* specific;
PropertyOffset offset = structure()->get(exec->vm(), propertyName, attributes, specific);
if (LIKELY(isValidOffset(offset))) {
JSValue value = getDirect(offset);
if (structure()->hasGetterSetterProperties() && value.isGetterSetter())
fillGetterPropertySlot(slot, value, offset);
fillGetterPropertySlot(slot, value, attributes, offset);
else
slot.setValue(this, value, offset);
slot.setValue(this, attributes, value, offset);
return true;
}
......
......@@ -473,14 +473,14 @@ namespace JSC {
ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
{
if (propertyName == exec->propertyNames().length) {
slot.setValue(this, jsNumber(m_length));
slot.setValue(this, DontEnum | DontDelete | ReadOnly, jsNumber(m_length));
return true;
}
unsigned i = propertyName.asIndex();
if (i < m_length) {
ASSERT(i != PropertyName::NotAnIndex); // No need for an explicit check, the above test would always fail!
slot.setValue(this, getIndex(exec, i));
slot.setValue(this, DontDelete | ReadOnly, getIndex(exec, i));
return true;
}
......@@ -490,7 +490,7 @@ namespace JSC {
ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
{
if (propertyName < m_length) {
slot.setValue(this, getIndex(exec, propertyName));
slot.setValue(this, DontDelete | ReadOnly, getIndex(exec, propertyName));
return true;
}
......
......@@ -79,7 +79,7 @@ inline bool symbolTableGet(
return false;
SymbolTableEntry::Fast entry = iter->value;
ASSERT(!entry.isNull());
slot.setValue(object, object->registerAt(entry.getIndex()).get());
slot.setValue(object, entry.getAttributes(), object->registerAt(entry.getIndex()).get());
return true;
}
......@@ -111,7 +111,7 @@ inline bool symbolTableGet(
return false;
SymbolTableEntry::Fast entry = iter->value;
ASSERT(!entry.isNull());
slot.setValue(object, object->registerAt(entry.getIndex()).get());
slot.setValue(object, entry.getAttributes(), object->registerAt(entry.getIndex()).get());
slotIsWriteable = !entry.isReadOnly();
return true;
}
......
......@@ -69,7 +69,8 @@ bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject*
{
ASSERT(thisObj->globalObject());
ASSERT(entry->attributes() & Function);
PropertyOffset offset = thisObj->getDirectOffset(exec->vm(), propertyName);
unsigned attributes;
PropertyOffset offset = thisObj->getDirectOffset(exec->vm(), propertyName, attributes);
if (!isValidOffset(offset)) {
// If a property is ever deleted from an object with a static table, then we reify
......@@ -80,11 +81,11 @@ bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject*
thisObj->putDirectNativeFunction(
exec, thisObj->globalObject(), propertyName, entry->functionLength(),
entry->function(), entry->intrinsic(), entry->attributes());
offset = thisObj->getDirectOffset(exec->vm(), propertyName);
offset = thisObj->getDirectOffset(exec->vm(), propertyName, attributes);
ASSERT(isValidOffset(offset));
}
slot.setValue(thisObj, thisObj->getDirect(offset), offset);
slot.setValue(thisObj, attributes, thisObj->getDirect(offset), offset);
return true;
}
......
......@@ -251,7 +251,7 @@ namespace JSC {
if (entry->attributes() & Function)
return setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
slot.setCacheableCustom(thisObj, entry->propertyGetter());
slot.setCacheableCustom(thisObj, entry->attributes(), entry->propertyGetter());
return true;
}
......@@ -271,7 +271,7 @@ namespace JSC {
return present;
}
slot.setCustom(thisObj, entry->propertyGetter());
slot.setCustom(thisObj, entry->attributes(), entry->propertyGetter());
descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
return true;
}
......@@ -330,7 +330,7 @@ namespace JSC {
ASSERT(!(entry->attributes() & Function));
slot.setCacheableCustom(thisObj, entry->propertyGetter());
slot.setCacheableCustom(thisObj, entry->attributes(), entry->propertyGetter());
return true;
}
......@@ -348,7 +348,7 @@ namespace JSC {
ASSERT(!(entry->attributes() & Function));
PropertySlot slot(thisObj);
slot.setCustom(thisObj, entry->propertyGetter());
slot.setCustom(thisObj, entry->attributes(), entry->propertyGetter());
descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
return true;
}
......
......@@ -33,6 +33,17 @@ namespace JSC {
class ExecState;
class GetterSetter;
// ECMA 262-3 8.6.1
// Property attributes
enum Attribute {
None = 0,
ReadOnly = 1 << 1, // property can be only read, not written
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
Accessor = 1 << 5, // property is a getter/setter
};
class PropertySlot {
enum PropertyType {
TypeUnset,
......@@ -79,10 +90,11 @@ public:
return m_slotBase;
}
void setValue(JSObject* slotBase, JSValue value)
void setValue(JSObject* slotBase, unsigned attributes, JSValue value)
{
ASSERT(value);
m_data.value = JSValue::encode(value);
m_attributes = attributes;
ASSERT(slotBase);
m_slotBase = slotBase;
......@@ -90,10 +102,11 @@ public:
m_offset = invalidOffset;
}
void setValue(JSObject* slotBase, JSValue value, PropertyOffset offset)
void setValue(JSObject* slotBase, unsigned attributes, JSValue value, PropertyOffset offset)
{
ASSERT(value);
m_data.value = JSValue::encode(value);
m_attributes = attributes;
ASSERT(slotBase);
m_slotBase = slotBase;
......@@ -101,20 +114,22 @@ public:
m_offset = offset;
}
void setValue(JSString*, JSValue value)
void setValue(JSString*, unsigned attributes, JSValue value)
{
ASSERT(value);
m_data.value = JSValue::encode(value);
m_attributes = attributes;
m_slotBase = 0;
m_propertyType = TypeValue;
m_offset = invalidOffset;
}
void setCustom(JSObject* slotBase, GetValueFunc getValue)
void setCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
{
ASSERT(getValue);
m_data.custom.getValue = getValue;
m_attributes = attributes;
ASSERT(slotBase);
m_slotBase = slotBase;
......@@ -122,10 +137,11 @@ public:
m_offset = invalidOffset;
}
void setCacheableCustom(JSObject* slotBase, GetValueFunc getValue)
void setCacheableCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
{
ASSERT(getValue);
m_data.custom.getValue = getValue;
m_attributes = attributes;
ASSERT(slotBase);
m_slotBase = slotBase;
......@@ -133,11 +149,12 @@ public:
m_offset = !invalidOffset;
}
void setCustomIndex(JSObject* slotBase, unsigned index, GetIndexValueFunc getIndexValue)
void setCustomIndex(JSObject* slotBase, unsigned attributes, unsigned index, GetIndexValueFunc getIndexValue)
{
ASSERT(getIndexValue);
m_data.customIndex.getIndexValue = getIndexValue;
m_data.customIndex.index = index;
m_attributes = attributes;
ASSERT(slotBase);
m_slotBase = slotBase;
......@@ -145,10 +162,11 @@ public:
m_offset = invalidOffset;
}
void setGetterSlot(JSObject* slotBase, GetterSetter* getterSetter)
void setGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter)
{
ASSERT(getterSetter);
m_data.getter.getterSetter = getterSetter;
m_attributes = attributes;
ASSERT(slotBase);
m_slotBase = slotBase;
......@@ -156,10 +174,11 @@ public:
m_offset = invalidOffset;
}
void setCacheableGetterSlot(JSObject* slotBase, GetterSetter* getterSetter, PropertyOffset offset)
void setCacheableGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter, PropertyOffset offset)
{
ASSERT(getterSetter);
m_data.getter.getterSetter = getterSetter;
m_attributes = attributes;
ASSERT(slotBase);
m_slotBase = slotBase;
......@@ -179,6 +198,7 @@ public: