Changeset 48542 in webkit


Ignore:
Timestamp:
Sep 18, 2009 4:12:03 PM (15 years ago)
Author:
oliver@apple.com
Message:

Implement ES5 Object.defineProperty function
https://bugs.webkit.org/show_bug.cgi?id=29503

Reviewed by Geoff Garen

Implement Object.defineProperty. This requires adding the API to
ObjectConstructor, along with a helper function that implements the
ES5 internal ToPropertyDescriptor? function. It then adds
JSObject::defineOwnProperty that implements the appropriate ES5 semantics.
Currently defineOwnProperty uses a delete followed by a put to redefine
attributes of a property, clearly this is less efficient than it could be
but we can improve this if it needs to be possible in future.

Location:
trunk
Files:
6 added
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r48527 r48542  
     12009-09-18  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Geoff Garen.
     4
     5        Implement ES5 Object.defineProperty function
     6        https://bugs.webkit.org/show_bug.cgi?id=29503
     7
     8        Implement Object.defineProperty.  This requires adding the API to
     9        ObjectConstructor, along with a helper function that implements the
     10        ES5 internal [[ToPropertyDescriptor]] function.  It then adds
     11        JSObject::defineOwnProperty that implements the appropriate ES5 semantics.
     12        Currently defineOwnProperty uses a delete followed by a put to redefine
     13        attributes of a property, clearly this is less efficient than it could be
     14        but we can improve this if it needs to be possible in future.
     15
     16        * JavaScriptCore.exp:
     17        * debugger/DebuggerActivation.cpp:
     18        (JSC::DebuggerActivation::defineGetter):
     19        (JSC::DebuggerActivation::defineSetter):
     20        * debugger/DebuggerActivation.h:
     21        * interpreter/Interpreter.cpp:
     22        (JSC::Interpreter::privateExecute):
     23        * jit/JITStubs.cpp:
     24          Update defineGetter/Setter calls
     25        * runtime/CommonIdentifiers.h:
     26        * runtime/JSArray.cpp:
     27        (JSC::JSArray::getOwnPropertySlot):
     28        * runtime/JSGlobalObject.cpp:
     29        (JSC::JSGlobalObject::defineGetter):
     30        (JSC::JSGlobalObject::defineSetter):
     31        * runtime/JSGlobalObject.h:
     32        * runtime/JSObject.cpp:
     33        (JSC::JSObject::defineGetter):
     34        (JSC::JSObject::defineSetter):
     35        (JSC::putDescriptor):
     36        (JSC::JSObject::defineOwnProperty):
     37        * runtime/JSObject.h:
     38        * runtime/ObjectConstructor.cpp:
     39        (JSC::ObjectConstructor::ObjectConstructor):
     40        (JSC::objectConstructorGetOwnPropertyDescriptor):
     41        (JSC::toPropertyDescriptor):
     42        (JSC::objectConstructorDefineProperty):
     43        * runtime/ObjectPrototype.cpp:
     44        (JSC::objectProtoFuncDefineGetter):
     45        (JSC::objectProtoFuncDefineSetter):
     46        * runtime/PropertyDescriptor.cpp:
     47        (JSC::PropertyDescriptor::writable):
     48        (JSC::PropertyDescriptor::enumerable):
     49        (JSC::PropertyDescriptor::configurable):
     50        (JSC::PropertyDescriptor::isDataDescriptor):
     51        (JSC::PropertyDescriptor::isGenericDescriptor):
     52        (JSC::PropertyDescriptor::isAccessorDescriptor):
     53        (JSC::PropertyDescriptor::getter):
     54        (JSC::PropertyDescriptor::setter):
     55        (JSC::PropertyDescriptor::setDescriptor):
     56        (JSC::PropertyDescriptor::setAccessorDescriptor):
     57        (JSC::PropertyDescriptor::setWritable):
     58        (JSC::PropertyDescriptor::setEnumerable):
     59        (JSC::PropertyDescriptor::setConfigurable):
     60        (JSC::PropertyDescriptor::setSetter):
     61        (JSC::PropertyDescriptor::setGetter):
     62        (JSC::PropertyDescriptor::equalTo):
     63        (JSC::PropertyDescriptor::attributesEqual):
     64        (JSC::PropertyDescriptor::attributesWithOverride):
     65        * runtime/PropertyDescriptor.h:
     66        (JSC::PropertyDescriptor::PropertyDescriptor):
     67        (JSC::PropertyDescriptor::value):
     68        (JSC::PropertyDescriptor::setValue):
     69        (JSC::PropertyDescriptor::isEmpty):
     70        (JSC::PropertyDescriptor::writablePresent):
     71        (JSC::PropertyDescriptor::enumerablePresent):
     72        (JSC::PropertyDescriptor::configurablePresent):
     73        (JSC::PropertyDescriptor::setterPresent):
     74        (JSC::PropertyDescriptor::getterPresent):
     75        (JSC::PropertyDescriptor::operator==):
     76        (JSC::PropertyDescriptor::):
     77
    1782009-09-18  Gabor Loki  <loki@inf.u-szeged.hu>
    279
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r48403 r48542  
    129129__ZN3JSC13jsOwnedStringEPNS_12JSGlobalDataERKNS_7UStringE
    130130__ZN3JSC14JSGlobalObject10globalExecEv
    131 __ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
    132 __ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectE
     131__ZN3JSC14JSGlobalObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
     132__ZN3JSC14JSGlobalObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPNS_8JSObjectEj
    133133__ZN3JSC14JSGlobalObject12markChildrenERNS_9MarkStackE
    134134__ZN3JSC14JSGlobalObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
     
    156156__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
    157157__ZN3JSC18DebuggerActivationC1EPNS_8JSObjectE
     158__ZN3JSC18PropertyDescriptor11setWritableEb
    158159__ZN3JSC18PropertyDescriptor12setUndefinedEv
    159160__ZN3JSC18PropertyDescriptor13setDescriptorENS_7JSValueEj
     161__ZN3JSC18PropertyDescriptor13setEnumerableEb
     162__ZN3JSC18PropertyDescriptor15setConfigurableEb
     163__ZN3JSC18PropertyDescriptor17defaultAttributesE
    160164__ZN3JSC18PropertyDescriptor21setAccessorDescriptorENS_7JSValueES1_j
    161 __ZNK3JSC18PropertyDescriptor6setterEv
    162 __ZNK3JSC18PropertyDescriptor6getterEv
     165__ZN3JSC18PropertyDescriptor9setGetterENS_7JSValueE
     166__ZN3JSC18PropertyDescriptor9setSetterENS_7JSValueE
    163167__ZN3JSC19constructEmptyArrayEPNS_9ExecStateE
    164168__ZN3JSC19initializeThreadingEv
     
    235239__ZN3JSC8DebuggerD2Ev
    236240__ZN3JSC8JSObject11hasInstanceEPNS_9ExecStateENS_7JSValueES3_
    237 __ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
    238 __ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_
     241__ZN3JSC8JSObject12defineGetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
     242__ZN3JSC8JSObject12defineSetterEPNS_9ExecStateERKNS_10IdentifierEPS0_j
    239243__ZN3JSC8JSObject12lookupGetterEPNS_9ExecStateERKNS_10IdentifierE
    240244__ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE
     
    245249__ZN3JSC8JSObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
    246250__ZN3JSC8JSObject17createInheritorIDEv
     251__ZN3JSC8JSObject17defineOwnPropertyEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorEb
    247252__ZN3JSC8JSObject17putDirectFunctionEPNS_9ExecStateEPNS_16InternalFunctionEj
    248253__ZN3JSC8JSObject17putWithAttributesEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueEj
     
    347352__ZNK3JSC17DebuggerCallFrame4typeEv
    348353__ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_7JSValueE
    349 __ZNK3JSC18PropertyDescriptor12hasAccessorsEv
     354__ZNK3JSC18PropertyDescriptor10enumerableEv
     355__ZNK3JSC18PropertyDescriptor12configurableEv
     356__ZNK3JSC18PropertyDescriptor16isDataDescriptorEv
     357__ZNK3JSC18PropertyDescriptor20isAccessorDescriptorEv
     358__ZNK3JSC18PropertyDescriptor6setterEv
     359__ZNK3JSC18PropertyDescriptor6getterEv
     360__ZNK3JSC18PropertyDescriptor8writableEv
    350361__ZNK3JSC4Heap10statisticsEv
    351362__ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
  • trunk/JavaScriptCore/debugger/DebuggerActivation.cpp

    r48336 r48542  
    8282}
    8383
    84 void DebuggerActivation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
     84void DebuggerActivation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
    8585{
    86     m_activation->defineGetter(exec, propertyName, getterFunction);
     86    m_activation->defineGetter(exec, propertyName, getterFunction, attributes);
    8787}
    8888
    89 void DebuggerActivation::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
     89void DebuggerActivation::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
    9090{
    91     m_activation->defineSetter(exec, propertyName, setterFunction);
     91    m_activation->defineSetter(exec, propertyName, setterFunction, attributes);
    9292}
    9393
  • trunk/JavaScriptCore/debugger/DebuggerActivation.h

    r48336 r48542  
    4545        virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&);
    4646        virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
    47         virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction);
    48         virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction);
     47        virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes);
     48        virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes);
    4949        virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
    5050        virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r47738 r48542  
    37323732        Identifier& ident = callFrame->codeBlock()->identifier(property);
    37333733        ASSERT(callFrame->r(function).jsValue().isObject());
    3734         baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()));
     3734        baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()), 0);
    37353735
    37363736        ++vPC;
  • trunk/JavaScriptCore/runtime/CommonIdentifiers.h

    r48336 r48542  
    4040    macro(configurable) \
    4141    macro(constructor) \
     42    macro(defineProperty) \
    4243    macro(enumerable) \
    4344    macro(eval) \
  • trunk/JavaScriptCore/runtime/JSArray.cpp

    r48336 r48542  
    224224    }
    225225
    226     return false;
     226    return JSObject::getOwnPropertySlot(exec, Identifier::from(exec, i), slot);
    227227}
    228228
  • trunk/JavaScriptCore/runtime/JSGlobalObject.cpp

    r47404 r48542  
    176176}
    177177
    178 void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc)
     178void JSGlobalObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes)
    179179{
    180180    PropertySlot slot;
    181181    if (!symbolTableGet(propertyName, slot))
    182         JSVariableObject::defineGetter(exec, propertyName, getterFunc);
    183 }
    184 
    185 void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc)
     182        JSVariableObject::defineGetter(exec, propertyName, getterFunc, attributes);
     183}
     184
     185void JSGlobalObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes)
    186186{
    187187    PropertySlot slot;
    188188    if (!symbolTableGet(propertyName, slot))
    189         JSVariableObject::defineSetter(exec, propertyName, setterFunc);
     189        JSVariableObject::defineSetter(exec, propertyName, setterFunc, attributes);
    190190}
    191191
  • trunk/JavaScriptCore/runtime/JSGlobalObject.h

    r47780 r48542  
    176176        virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
    177177
    178         virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc);
    179         virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc);
     178        virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
     179        virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
    180180
    181181        // Linked list of all global objects that use the same JSGlobalData.
  • trunk/JavaScriptCore/runtime/JSObject.cpp

    r48336 r48542  
    276276}
    277277
    278 void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
     278void JSObject::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
    279279{
    280280    JSValue object = getDirect(propertyName);
     
    287287    PutPropertySlot slot;
    288288    GetterSetter* getterSetter = new (exec) GetterSetter(exec);
    289     putDirectInternal(exec->globalData(), propertyName, getterSetter, Getter, true, slot);
     289    putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Getter, true, slot);
    290290
    291291    // putDirect will change our Structure if we add a new property. For
     
    303303}
    304304
    305 void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
     305void JSObject::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
    306306{
    307307    JSValue object = getDirect(propertyName);
     
    314314    PutPropertySlot slot;
    315315    GetterSetter* getterSetter = new (exec) GetterSetter(exec);
    316     putDirectInternal(exec->globalData(), propertyName, getterSetter, Setter, true, slot);
     316    putDirectInternal(exec->globalData(), propertyName, getterSetter, attributes | Setter, true, slot);
    317317
    318318    // putDirect will change our Structure if we add a new property. For
     
    542542    }
    543543}
     544
     545static bool putDescriptor(ExecState* exec, JSObject* target, const Identifier& propertyName, PropertyDescriptor& descriptor, unsigned attributes, JSValue oldValue)
     546{
     547    if (descriptor.isGenericDescriptor() || descriptor.isDataDescriptor()) {
     548        target->putWithAttributes(exec, propertyName, descriptor.value() ? descriptor.value() : oldValue, attributes & ~(Getter | Setter));
     549        return true;
     550    }
     551    attributes &= ~ReadOnly;
     552    if (descriptor.getter() && descriptor.getter().isObject())
     553        target->defineGetter(exec, propertyName, asObject(descriptor.getter()), attributes);
     554    if (exec->hadException())
     555        return false;
     556    if (descriptor.setter() && descriptor.setter().isObject())
     557        target->defineSetter(exec, propertyName, asObject(descriptor.setter()), attributes);
     558    return !exec->hadException();
     559}
     560
     561bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException)
     562{
     563    // If we have a new property we can just put it on normally
     564    PropertyDescriptor current;
     565    if (!getOwnPropertyDescriptor(exec, propertyName, current))
     566        return putDescriptor(exec, this, propertyName, descriptor, descriptor.attributes(), jsUndefined());
     567
     568    if (descriptor.isEmpty())
     569        return true;
     570
     571    if (current.equalTo(descriptor))
     572        return true;
     573
     574    // Filter out invalid changes
     575    if (!current.configurable()) {
     576        if (descriptor.configurable()) {
     577            if (throwException)
     578                throwError(exec, TypeError, "Attempting to configurable attribute of unconfigurable property.");
     579            return false;
     580        }
     581        if (descriptor.enumerablePresent() && descriptor.enumerable() != current.enumerable()) {
     582            if (throwException)
     583                throwError(exec, TypeError, "Attempting to change enumerable attribute of unconfigurable property.");
     584            return false;
     585        }
     586    }
     587
     588    // A generic descriptor is simply changing the attributes of an existing property
     589    if (descriptor.isGenericDescriptor()) {
     590        if (!current.attributesEqual(descriptor)) {
     591            deleteProperty(exec, propertyName);
     592            putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
     593        }
     594        return true;
     595    }
     596
     597    // Changing between a normal property or an accessor property
     598    if (descriptor.isDataDescriptor() != current.isDataDescriptor()) {
     599        if (!current.configurable()) {
     600            if (throwException)
     601                throwError(exec, TypeError, "Attempting to change access mechanism for an unconfigurable property.");
     602            return false;
     603        }
     604        deleteProperty(exec, propertyName);
     605        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value() ? current.value() : jsUndefined());
     606    }
     607
     608    // Changing the value and attributes of an existing property
     609    if (descriptor.isDataDescriptor()) {
     610        if (!current.configurable()) {
     611            if (!current.writable() && descriptor.writable()) {
     612                if (throwException)
     613                    throwError(exec, TypeError, "Attempting to change writable attribute of unconfigurable property.");
     614                return false;
     615            }
     616            if (!current.writable()) {
     617                if (descriptor.value() || !JSValue::strictEqual(current.value(), descriptor.value())) {
     618                    if (throwException)
     619                        throwError(exec, TypeError, "Attempting to change value of a readonly property.");
     620                    return false;
     621                }
     622            }
     623        } else if (current.attributesEqual(descriptor)) {
     624            if (!descriptor.value())
     625                return true;
     626            PutPropertySlot slot;
     627            put(exec, propertyName, descriptor.value(), slot);
     628            if (exec->hadException())
     629                return false;
     630            return true;
     631        }
     632        deleteProperty(exec, propertyName);
     633        return putDescriptor(exec, this, propertyName, descriptor, current.attributesWithOverride(descriptor), current.value());
     634    }
     635
     636    // Changing the accessor functions of an existing accessor property
     637    ASSERT(descriptor.isAccessorDescriptor());
     638    if (!current.configurable()) {
     639        if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(current.setter(), descriptor.setter()))) {
     640            if (throwException)
     641                throwError(exec, TypeError, "Attempting to change the setter of an unconfigurable property.");
     642            return false;
     643        }
     644        if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(current.getter(), descriptor.getter()))) {
     645            if (throwException)
     646                throwError(exec, TypeError, "Attempting to change the getter of an unconfigurable property.");
     647            return false;
     648        }
     649    }
     650    JSValue accessor = getDirect(propertyName);
     651    if (!accessor)
     652        return false;
     653    GetterSetter* getterSetter = asGetterSetter(accessor);
     654    if (current.attributesEqual(descriptor)) {
     655        if (descriptor.setter())
     656            getterSetter->setSetter(asObject(descriptor.setter()));
     657        if (descriptor.getter())
     658            getterSetter->setGetter(asObject(descriptor.getter()));
     659        return true;
     660    }
     661    deleteProperty(exec, propertyName);
     662    unsigned attrs = current.attributesWithOverride(descriptor);
     663    if (descriptor.setter())
     664        attrs |= Setter;
     665    if (descriptor.getter())
     666        attrs |= Getter;
     667    putDirect(propertyName, getterSetter, attrs);
     668    return true;
     669}
     670
    544671} // namespace JSC
  • trunk/JavaScriptCore/runtime/JSObject.h

    r48403 r48542  
    187187        void fillGetterPropertySlot(PropertySlot&, JSValue* location);
    188188
    189         virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction);
    190         virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction);
     189        virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes = 0);
     190        virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes = 0);
    191191        virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName);
    192192        virtual JSValue lookupSetter(ExecState*, const Identifier& propertyName);
     193        virtual bool defineOwnProperty(ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow);
    193194
    194195        virtual bool isGlobalObject() const { return false; }
  • trunk/JavaScriptCore/runtime/ObjectConstructor.cpp

    r48338 r48542  
    3838static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*, JSObject*, JSValue, const ArgList&);
    3939static JSValue JSC_HOST_CALL objectConstructorKeys(ExecState*, JSObject*, JSValue, const ArgList&);
     40static JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*, JSObject*, JSValue, const ArgList&);
    4041
    4142ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure)
     
    5152    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum);
    5253    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().keys, objectConstructorKeys), DontEnum);
     54        putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 3, exec->propertyNames().defineProperty, objectConstructorDefineProperty), DontEnum);
    5355}
    5456
     
    104106    if (exec->hadException())
    105107        return jsUndefined();
    106     ASSERT(descriptor.isValid());
    107108
    108109    JSObject* description = constructEmptyObject(exec);
    109     if (!descriptor.hasAccessors()) {
    110         description->putDirect(exec->propertyNames().value, descriptor.value(), 0);
     110    if (!descriptor.isAccessorDescriptor()) {
     111        description->putDirect(exec->propertyNames().value, descriptor.value() ? descriptor.value() : jsUndefined(), 0);
    111112        description->putDirect(exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
    112113    } else {
    113         description->putDirect(exec->propertyNames().get, descriptor.getter(), 0);
    114         description->putDirect(exec->propertyNames().set, descriptor.setter(), 0);
     114        description->putDirect(exec->propertyNames().get, descriptor.getter() ? descriptor.getter() : jsUndefined(), 0);
     115        description->putDirect(exec->propertyNames().set, descriptor.setter() ? descriptor.setter() : jsUndefined(), 0);
    115116    }
    116117   
     
    134135}
    135136
     137// ES5 8.10.5 ToPropertyDescriptor
     138static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor& desc)
     139{
     140    if (!in.isObject()) {
     141        throwError(exec, TypeError, "Property description must be an object.");
     142        return false;
     143    }
     144    JSObject* description = asObject(in);
     145
     146    PropertySlot enumerableSlot;
     147    if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) {
     148        desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec));
     149        if (exec->hadException())
     150            return false;
     151    }
     152
     153    PropertySlot configurableSlot;
     154    if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) {
     155        desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec));
     156        if (exec->hadException())
     157            return false;
     158    }
     159
     160    JSValue value;
     161    PropertySlot valueSlot;
     162    if (description->getPropertySlot(exec, exec->propertyNames().value, valueSlot)) {
     163        desc.setValue(valueSlot.getValue(exec, exec->propertyNames().value));
     164        if (exec->hadException())
     165            return false;
     166    }
     167
     168    PropertySlot writableSlot;
     169    if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) {
     170        desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec));
     171        if (exec->hadException())
     172            return false;
     173    }
     174
     175    PropertySlot getSlot;
     176    if (description->getPropertySlot(exec, exec->propertyNames().get, getSlot)) {
     177        JSValue get = getSlot.getValue(exec, exec->propertyNames().get);
     178        if (exec->hadException())
     179            return false;
     180        if (!get.isUndefined()) {
     181            CallData callData;
     182            if (get.getCallData(callData) == CallTypeNone) {
     183                throwError(exec, TypeError, "Getter must be a function.");
     184                return false;
     185            }
     186        } else
     187            get = JSValue();
     188        desc.setGetter(get);
     189    }
     190
     191    PropertySlot setSlot;
     192    if (description->getPropertySlot(exec, exec->propertyNames().set, setSlot)) {
     193        JSValue set = setSlot.getValue(exec, exec->propertyNames().set);
     194        if (exec->hadException())
     195            return false;
     196        if (!set.isUndefined()) {
     197            CallData callData;
     198            if (set.getCallData(callData) == CallTypeNone) {
     199                throwError(exec, TypeError, "Setter must be a function.");
     200                return false;
     201            }
     202        } else
     203            set = JSValue();
     204
     205        desc.setSetter(set);
     206    }
     207
     208    if (!desc.isAccessorDescriptor())
     209        return true;
     210
     211    if (desc.value()) {
     212        throwError(exec, TypeError, "Invalid property.  'value' present on property with getter or setter.");
     213        return false;
     214    }
     215
     216    if (desc.writablePresent()) {
     217        throwError(exec, TypeError, "Invalid property.  'writable' present on property with getter or setter.");
     218        return false;
     219    }
     220    return true;
     221}
     222
     223JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState* exec, JSObject*, JSValue, const ArgList& args)
     224{
     225    if (!args.at(0).isObject())
     226        return throwError(exec, TypeError, "Properties can only be defined on Objects.");
     227    JSObject* O = asObject(args.at(0));
     228    UString propertyName = args.at(1).toString(exec);
     229    if (exec->hadException())
     230        return jsNull();
     231    PropertyDescriptor descriptor;
     232    if (!toPropertyDescriptor(exec, args.at(2), descriptor))
     233        return jsNull();
     234    ASSERT((descriptor.attributes() & (Getter | Setter)) || (!descriptor.isAccessorDescriptor()));
     235    ASSERT(!exec->hadException());
     236    O->defineOwnProperty(exec, Identifier(exec, propertyName), descriptor, true);
     237    return O;
     238}
     239
    136240} // namespace JSC
  • trunk/JavaScriptCore/runtime/PropertyDescriptor.cpp

    r47780 r48542  
    3131#include "GetterSetter.h"
    3232#include "JSObject.h"
     33#include "Operations.h"
    3334
    3435namespace JSC {
     36unsigned PropertyDescriptor::defaultAttributes = (DontDelete << 1) - 1;
     37
    3538bool PropertyDescriptor::writable() const
    3639{
    37     ASSERT(!hasAccessors());
     40    ASSERT(!isAccessorDescriptor());
    3841    return !(m_attributes & ReadOnly);
    3942}
     
    4144bool PropertyDescriptor::enumerable() const
    4245{
    43     ASSERT(isValid());
    4446    return !(m_attributes & DontEnum);
    4547}
     
    4749bool PropertyDescriptor::configurable() const
    4850{
    49     ASSERT(isValid());
    5051    return !(m_attributes & DontDelete);
    5152}
    5253
    53 bool PropertyDescriptor::hasAccessors() const
     54bool PropertyDescriptor::isDataDescriptor() const
    5455{
    55     return !!(m_attributes & (Getter | Setter));
     56    return m_value || (m_seenAttributes & WritablePresent);
     57}
     58
     59bool PropertyDescriptor::isGenericDescriptor() const
     60{
     61    return !isAccessorDescriptor() && !isDataDescriptor();
     62}
     63
     64bool PropertyDescriptor::isAccessorDescriptor() const
     65{
     66    return m_getter || m_setter;
    5667}
    5768
     
    6475JSValue PropertyDescriptor::getter() const
    6576{
    66     ASSERT(hasAccessors());
    67     if (!m_getter)
    68         return jsUndefined();
     77    ASSERT(isAccessorDescriptor());
    6978    return m_getter;
    7079}
     
    7281JSValue PropertyDescriptor::setter() const
    7382{
    74     ASSERT(hasAccessors());
    75     if (!m_setter)
    76         return jsUndefined();
     83    ASSERT(isAccessorDescriptor());
    7784    return m_setter;
    7885}
     
    8188{
    8289    ASSERT(value);
     90    m_attributes = attributes;
    8391    if (attributes & (Getter | Setter)) {
    8492        GetterSetter* accessor = asGetterSetter(value);
     
    8694        m_setter = accessor->setter();
    8795        ASSERT(m_getter || m_setter);
     96        m_seenAttributes = EnumerablePresent | ConfigurablePresent;
     97        m_attributes &= ~ReadOnly;
    8898    } else {
    8999        m_value = value;
     100        m_seenAttributes = EnumerablePresent | ConfigurablePresent | WritablePresent;
    90101    }
    91     m_attributes = attributes;
    92102}
    93103
     
    99109    m_getter = getter;
    100110    m_setter = setter;
     111    m_attributes &= ~ReadOnly;
     112    m_seenAttributes = EnumerablePresent | ConfigurablePresent;
     113}
     114
     115void PropertyDescriptor::setWritable(bool writable)
     116{
     117    if (writable)
     118        m_attributes &= ~ReadOnly;
     119    else
     120        m_attributes |= ReadOnly;
     121    m_seenAttributes |= WritablePresent;
     122}
     123
     124void PropertyDescriptor::setEnumerable(bool enumerable)
     125{
     126    if (enumerable)
     127        m_attributes &= ~DontEnum;
     128    else
     129        m_attributes |= DontEnum;
     130    m_seenAttributes |= EnumerablePresent;
     131}
     132
     133void PropertyDescriptor::setConfigurable(bool configurable)
     134{
     135    if (configurable)
     136        m_attributes &= ~DontDelete;
     137    else
     138        m_attributes |= DontDelete;
     139    m_seenAttributes |= ConfigurablePresent;
     140}
     141
     142void PropertyDescriptor::setSetter(JSValue setter)
     143{
     144    m_setter = setter;
     145    m_attributes |= Setter;
     146    m_attributes &= ~ReadOnly;
     147}
     148
     149void PropertyDescriptor::setGetter(JSValue getter)
     150{
     151    m_getter = getter;
     152    m_attributes |= Getter;
     153    m_attributes &= ~ReadOnly;
     154}
     155
     156bool PropertyDescriptor::equalTo(const PropertyDescriptor& other) const
     157{
     158    if (!other.m_value == m_value ||
     159        !other.m_getter == m_getter ||
     160        !other.m_setter == m_setter)
     161        return false;
     162    return (!m_value || JSValue::strictEqual(other.m_value, m_value)) &&
     163           (!m_getter || JSValue::strictEqual(other.m_getter, m_getter)) &&
     164           (!m_setter || JSValue::strictEqual(other.m_setter, m_setter)) &&
     165           attributesEqual(other);
     166}
     167
     168bool PropertyDescriptor::attributesEqual(const PropertyDescriptor& other) const
     169{
     170    unsigned mismatch = other.m_attributes ^ m_attributes;
     171    unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
     172    if (sharedSeen & WritablePresent && mismatch & ReadOnly)
     173        return false;
     174    if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
     175        return false;
     176    if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
     177        return false;
     178    return true;
     179}
     180
     181unsigned PropertyDescriptor::attributesWithOverride(const PropertyDescriptor& other) const
     182{
     183    unsigned mismatch = other.m_attributes ^ m_attributes;
     184    unsigned sharedSeen = other.m_seenAttributes & m_seenAttributes;
     185    unsigned newAttributes = m_attributes & defaultAttributes;
     186    if (sharedSeen & WritablePresent && mismatch & ReadOnly)
     187        newAttributes ^= ReadOnly;
     188    if (sharedSeen & ConfigurablePresent && mismatch & DontDelete)
     189        newAttributes ^= DontDelete;
     190    if (sharedSeen & EnumerablePresent && mismatch & DontEnum)
     191        newAttributes ^= DontEnum;
     192    return newAttributes;
    101193}
    102194
  • trunk/JavaScriptCore/runtime/PropertyDescriptor.h

    r47780 r48542  
    3333    public:
    3434        PropertyDescriptor()
    35             : m_attributes(0)
     35            : m_attributes(defaultAttributes)
     36            , m_seenAttributes(0)
    3637        {
    3738        }
     
    3940        bool enumerable() const;
    4041        bool configurable() const;
    41         bool hasAccessors() const;
     42        bool isDataDescriptor() const;
     43        bool isGenericDescriptor() const;
     44        bool isAccessorDescriptor() const;
    4245        unsigned attributes() const { return m_attributes; }
    43 #ifndef NDEBUG
    44         bool isValid() const { return m_value || ((m_getter || m_setter) && hasAccessors()); }
    45 #endif
    46         JSValue value() const { ASSERT(m_value); return m_value; }
     46        JSValue value() const { return m_value; }
    4747        JSValue getter() const;
    4848        JSValue setter() const;
     
    5050        void setDescriptor(JSValue value, unsigned attributes);
    5151        void setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes);
     52        void setWritable(bool);
     53        void setEnumerable(bool);
     54        void setConfigurable(bool);
     55        void setValue(JSValue value) { m_value = value; }
     56        void setSetter(JSValue);
     57        void setGetter(JSValue);
     58        bool isEmpty() const { return !(m_value || m_getter || m_setter || m_seenAttributes); }
     59        bool writablePresent() const { return m_seenAttributes & WritablePresent; }
     60        bool enumerablePresent() const { return m_seenAttributes & EnumerablePresent; }
     61        bool configurablePresent() const { return m_seenAttributes & ConfigurablePresent; }
     62        bool setterPresent() const { return m_setter; }
     63        bool getterPresent() const { return m_getter; }
     64        bool equalTo(const PropertyDescriptor& other) const;
     65        bool attributesEqual(const PropertyDescriptor& other) const;
     66        unsigned attributesWithOverride(const PropertyDescriptor& other) const;
    5267    private:
     68        static unsigned defaultAttributes;
     69        bool operator==(const PropertyDescriptor&){ return false; }
     70        enum { WritablePresent = 1, EnumerablePresent = 2, ConfigurablePresent = 4};
    5371        // May be a getter/setter
    5472        JSValue m_value;
     
    5674        JSValue m_setter;
    5775        unsigned m_attributes;
     76        unsigned m_seenAttributes;
    5877    };
    5978}
  • trunk/LayoutTests/ChangeLog

    r48541 r48542  
     12009-09-18  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Geoff Garen.
     4
     5        Implement ES5 Object.defineProperty function
     6        https://bugs.webkit.org/show_bug.cgi?id=29503
     7
     8        Add testcases for Object.defineProperty.
     9
     10        * fast/js/Object-defineProperty-expected.txt: Added.
     11        * fast/js/Object-defineProperty.html: Added.
     12        * fast/js/resources/Object-defineProperty.js: Added.
     13        * http/tests/security/resources/xss-DENIED-defineProperty-attacker.html: Added.
     14        * http/tests/security/xss-DENIED-defineProperty-expected.txt: Added.
     15        * http/tests/security/xss-DENIED-defineProperty.html: Added.
     16
    1172009-09-18  Brady Eidson  <beidson@apple.com>
    218
  • trunk/WebCore/ChangeLog

    r48540 r48542  
     12009-09-18  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Geoff Garen.
     4
     5        Implement ES5 Object.defineProperty function
     6        https://bugs.webkit.org/show_bug.cgi?id=29503
     7
     8        Override defineOwnProperty on JSDOMWindowShell to forward appropriately,
     9        and then override defineOwnProperty on JSDOMWindow to disallow cross origin
     10        defineOwnProperty usage.  We also override defineOwnProperty on QuarantinedObjectWrapper
     11        to ensure correct wrapping semantics of quarantined objects.
     12
     13        One major caveat in this patch is that it currently disallows the use
     14        of Object.defineProperty on DOMObjects other than the window due to
     15        the significant work involved in correctly propagating attributes and
     16        ensuring correct semantics on dom objects.
     17
     18        Tests: fast/js/Object-defineProperty.html
     19               http/tests/security/xss-DENIED-defineProperty.html
     20
     21        * bindings/js/JSDOMBinding.cpp:
     22        (WebCore::DOMObject::defineOwnProperty):
     23        * bindings/js/JSDOMBinding.h:
     24        * bindings/js/JSDOMWindowCustom.cpp:
     25        (WebCore::JSDOMWindow::defineGetter):
     26        (WebCore::JSDOMWindow::defineSetter):
     27        (WebCore::JSDOMWindow::defineOwnProperty):
     28        * bindings/js/JSDOMWindowShell.cpp:
     29        (WebCore::JSDOMWindowShell::defineOwnProperty):
     30        (WebCore::JSDOMWindowShell::defineGetter):
     31        (WebCore::JSDOMWindowShell::defineSetter):
     32        * bindings/js/JSDOMWindowShell.h:
     33        * bindings/js/JSLocationCustom.cpp:
     34        (WebCore::JSLocation::defineGetter):
     35        (WebCore::JSLocationPrototype::defineGetter):
     36        * bindings/js/JSQuarantinedObjectWrapper.cpp:
     37        (WebCore::JSQuarantinedObjectWrapper::getOwnPropertyDescriptor):
     38        (WebCore::JSQuarantinedObjectWrapper::defineOwnProperty):
     39        * bindings/js/JSQuarantinedObjectWrapper.h:
     40        * bindings/scripts/CodeGeneratorJS.pm:
     41
    1422009-09-18  Alexey Proskuryakov  <ap@apple.com>
    243
  • trunk/WebCore/bindings/js/JSDOMBinding.cpp

    r48025 r48542  
    649649}
    650650
     651bool DOMObject::defineOwnProperty(ExecState* exec, const Identifier&, PropertyDescriptor&, bool)
     652{
     653    throwError(exec, TypeError, "defineProperty is not supported on DOM Objects");
     654    return false;
     655}
     656
    651657} // namespace WebCore
  • trunk/WebCore/bindings/js/JSDOMBinding.h

    r48079 r48542  
    5656        }
    5757
     58        virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&, bool);
     59
    5860#ifndef NDEBUG
    5961        virtual ~DOMObject();
  • trunk/WebCore/bindings/js/JSDOMWindowCustom.cpp

    r48402 r48542  
    489489}
    490490
    491 void JSDOMWindow::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
     491void JSDOMWindow::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
    492492{
    493493    // Only allow defining getters by frames in the same origin.
     
    499499        return;
    500500
    501     Base::defineGetter(exec, propertyName, getterFunction);
    502 }
    503 
    504 void JSDOMWindow::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
     501    Base::defineGetter(exec, propertyName, getterFunction, attributes);
     502}
     503
     504void JSDOMWindow::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
    505505{
    506506    // Only allow defining setters by frames in the same origin.
    507507    if (!allowsAccessFrom(exec))
    508508        return;
    509     Base::defineSetter(exec, propertyName, setterFunction);
     509    Base::defineSetter(exec, propertyName, setterFunction, attributes);
     510}
     511
     512bool JSDOMWindow::defineOwnProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor, bool shouldThrow)
     513{
     514    // Only allow defining properties in this way by frames in the same origin, as it allows setters to be introduced.
     515    if (!allowsAccessFrom(exec))
     516        return false;
     517    return Base::defineOwnProperty(exec, propertyName, descriptor, shouldThrow);
    510518}
    511519
  • trunk/WebCore/bindings/js/JSDOMWindowShell.cpp

    r48336 r48542  
    104104}
    105105
     106bool JSDOMWindowShell::defineOwnProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor, bool shouldThrow)
     107{
     108    return m_window->defineOwnProperty(exec, propertyName, descriptor, shouldThrow);
     109}
     110
    106111bool JSDOMWindowShell::deleteProperty(ExecState* exec, const Identifier& propertyName)
    107112{
     
    124129}
    125130
    126 void JSDOMWindowShell::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
     131void JSDOMWindowShell::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
    127132{
    128     m_window->defineGetter(exec, propertyName, getterFunction);
     133    m_window->defineGetter(exec, propertyName, getterFunction, attributes);
    129134}
    130135
    131 void JSDOMWindowShell::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction)
     136void JSDOMWindowShell::defineSetter(ExecState* exec, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes)
    132137{
    133     m_window->defineSetter(exec, propertyName, setterFunction);
     138    m_window->defineSetter(exec, propertyName, setterFunction, attributes);
    134139}
    135140
  • trunk/WebCore/bindings/js/JSDOMWindowShell.h

    r48336 r48542  
    7575        virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);
    7676        virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier& propertyName, unsigned& attributes) const;
    77         virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction);
    78         virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction);
     77        virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);
     78        virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);
     79        virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);
    7980        virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName);
    8081        virtual JSC::JSValue lookupSetter(JSC::ExecState*, const JSC::Identifier& propertyName);
  • trunk/WebCore/bindings/js/JSLocationCustom.cpp

    r48336 r48542  
    183183}
    184184
    185 void JSLocation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
     185void JSLocation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
    186186{
    187187    if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)
    188188        return;
    189     Base::defineGetter(exec, propertyName, getterFunction);
     189    Base::defineGetter(exec, propertyName, getterFunction, attributes);
    190190}
    191191
     
    363363}
    364364
    365 void JSLocationPrototype::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction)
     365void JSLocationPrototype::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes)
    366366{
    367367    if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)
    368368        return;
    369     Base::defineGetter(exec, propertyName, getterFunction);
     369    Base::defineGetter(exec, propertyName, getterFunction, attributes);
    370370}
    371371
  • trunk/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp

    r48336 r48542  
    149149    bool result = m_unwrappedObject->getOwnPropertyDescriptor(unwrappedExecState(), identifier, unwrappedDescriptor);
    150150
    151     if (unwrappedDescriptor.hasAccessors()) {
     151    if (unwrappedDescriptor.isAccessorDescriptor()) {
    152152        descriptor.setAccessorDescriptor(wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.getter()),
    153153                                         wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.setter()),
     
    177177
    178178    transferExceptionToExecState(exec);
     179}
     180
     181bool JSQuarantinedObjectWrapper::defineOwnProperty(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow)
     182{
     183    if (!allowsSetProperty())
     184        return false;
     185
     186    PropertyDescriptor wrappedDescriptor;
     187    if (descriptor.isDataDescriptor()) {
     188        wrappedDescriptor.setValue(prepareIncomingValue(exec, descriptor.value()));
     189        if (wrappedDescriptor.writablePresent())
     190            wrappedDescriptor.setWritable(descriptor.writable());
     191    } else if (descriptor.isAccessorDescriptor()) {
     192        if (descriptor.getter())
     193            wrappedDescriptor.setGetter(prepareIncomingValue(exec, descriptor.getter()));
     194        if (descriptor.setter())
     195            wrappedDescriptor.setSetter(prepareIncomingValue(exec, descriptor.setter()));
     196    }
     197    if (wrappedDescriptor.enumerablePresent())
     198        wrappedDescriptor.setEnumerable(descriptor.enumerable());
     199    if (wrappedDescriptor.configurablePresent())
     200        wrappedDescriptor.setConfigurable(descriptor.configurable());
     201   
     202    bool result = m_unwrappedObject->defineOwnProperty(unwrappedExecState(), propertyName, wrappedDescriptor, shouldThrow);
     203   
     204    transferExceptionToExecState(exec);
     205    return result;
    179206}
    180207
  • trunk/WebCore/bindings/js/JSQuarantinedObjectWrapper.h

    r48336 r48542  
    6363        virtual void put(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);
    6464        virtual void put(JSC::ExecState*, unsigned, JSC::JSValue);
     65        virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);
    6566
    6667        virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier&);
  • trunk/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r48336 r48542  
    628628    # Custom getPropertyNames function exists on DOMWindow
    629629    push(@headerContent, "    virtual void getPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if $interfaceName eq "DOMWindow";
     630
     631    # Custom defineProperty function exists on DOMWindow
     632    push(@headerContent, "    virtual bool defineOwnProperty(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&, bool shouldThrow);\n") if $interfaceName eq "DOMWindow";
     633
    630634    # Custom getOwnPropertyNames function
    631635    push(@headerContent, "    virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&);\n") if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"} || $dataNode->extendedAttributes->{"HasNumericIndexGetter"});   
     
    635639
    636640    # Custom defineGetter function
    637     push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"};
     641    push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineGetter"};
    638642
    639643    # Custom defineSetter function
    640     push(@headerContent, "    virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"};
     644    push(@headerContent, "    virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomDefineSetter"};
    641645
    642646    # Custom lookupGetter function
     
    801805
    802806    # Custom defineGetter function
    803     push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"};
     807    push(@headerContent, "    virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes);\n") if $dataNode->extendedAttributes->{"CustomPrototypeDefineGetter"};
    804808
    805809    push(@headerContent, "    ${className}Prototype(PassRefPtr<JSC::Structure> structure) : JSC::JSObject(structure) { }\n");
Note: See TracChangeset for help on using the changeset viewer.