Changeset 47780 in webkit


Ignore:
Timestamp:
Aug 26, 2009 9:52:15 AM (15 years ago)
Author:
oliver@apple.com
Message:

[ES5] Implement getOwnPropertyDescriptor
https://bugs.webkit.org/show_bug.cgi?id=28724

Reviewed by Gavin Barraclough.

JavaScriptCore:
Implement the core runtime support for getOwnPropertyDescriptor.
This adds a virtual getOwnPropertyDescriptor method to every class
that implements getOwnPropertySlot that shadows the behaviour of
getOwnPropertySlot. The alternative would be to make getOwnPropertySlot
(or PropertySlots in general) provide property attribute information,
but quick testing showed this to be a regression.

WebCore:
Implement the WebCore side of getOwnPropertyDescriptor. This
requires a custom implementation of getOwnPropertyDescriptor
for every class with a custom implementation of getOwnPropertySlot.

The bindings generator has been updated to generate appropriate
versions of getOwnPropertyDescriptor for the general case where
a custom getOwnPropertyDescriptor is not needed. ES5 is vague
about how getOwnPropertyDescriptor should work in the context of
"host" functions with polymorphic GetOwnProperty?, so it seems
okay that occasionally we "guess" what attributes -- eg. determining
whether a property is writable.

Test: fast/js/getOwnPropertyDescriptor.html

Location:
trunk
Files:
4 added
69 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r47775 r47780  
     12009-08-25  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        [ES5] Implement getOwnPropertyDescriptor
     6        https://bugs.webkit.org/show_bug.cgi?id=28724
     7
     8        Implement the core runtime support for getOwnPropertyDescriptor.
     9        This adds a virtual getOwnPropertyDescriptor method to every class
     10        that implements getOwnPropertySlot that shadows the behaviour of
     11        getOwnPropertySlot.  The alternative would be to make getOwnPropertySlot
     12        (or PropertySlots in general) provide property attribute information,
     13        but quick testing showed this to be a regression.
     14
     15        * JavaScriptCore.exp:
     16        * JavaScriptCore.xcodeproj/project.pbxproj:
     17        * runtime/Arguments.cpp:
     18        (JSC::Arguments::getOwnPropertyDescriptor):
     19        * runtime/Arguments.h:
     20        * runtime/ArrayPrototype.cpp:
     21        (JSC::ArrayPrototype::getOwnPropertyDescriptor):
     22        * runtime/ArrayPrototype.h:
     23        * runtime/CommonIdentifiers.h:
     24        * runtime/DatePrototype.cpp:
     25        (JSC::DatePrototype::getOwnPropertyDescriptor):
     26        * runtime/DatePrototype.h:
     27        * runtime/JSArray.cpp:
     28        (JSC::JSArray::getOwnPropertyDescriptor):
     29        * runtime/JSArray.h:
     30        * runtime/JSByteArray.cpp:
     31        (JSC::JSByteArray::getOwnPropertyDescriptor):
     32        * runtime/JSByteArray.h:
     33        * runtime/JSFunction.cpp:
     34        (JSC::JSFunction::getOwnPropertyDescriptor):
     35        * runtime/JSFunction.h:
     36        * runtime/JSGlobalObject.h:
     37        (JSC::JSGlobalObject::getOwnPropertyDescriptor):
     38        * runtime/JSNotAnObject.cpp:
     39        (JSC::JSNotAnObject::getOwnPropertyDescriptor):
     40        * runtime/JSNotAnObject.h:
     41        * runtime/JSONObject.cpp:
     42        (JSC::JSONObject::getOwnPropertySlot):
     43        (JSC::JSONObject::getOwnPropertyDescriptor):
     44        * runtime/JSONObject.h:
     45        * runtime/JSObject.cpp:
     46        (JSC::JSObject::getOwnPropertyDescriptor):
     47        (JSC::JSObject::getPropertyDescriptor):
     48        * runtime/JSObject.h:
     49        * runtime/JSString.cpp:
     50        (JSC::JSString::getStringPropertyDescriptor):
     51        (JSC::JSString::getOwnPropertyDescriptor):
     52        * runtime/JSString.h:
     53        * runtime/JSVariableObject.cpp:
     54        (JSC::JSVariableObject::symbolTableGet):
     55        * runtime/JSVariableObject.h:
     56        * runtime/Lookup.h:
     57        (JSC::getStaticPropertyDescriptor):
     58        (JSC::getStaticFunctionDescriptor):
     59        (JSC::getStaticValueDescriptor):
     60          Add property descriptor equivalents of the lookup
     61          table access functions
     62
     63        * runtime/MathObject.cpp:
     64        (JSC::MathObject::getOwnPropertySlot):
     65        (JSC::MathObject::getOwnPropertyDescriptor):
     66        * runtime/MathObject.h:
     67        * runtime/NumberConstructor.cpp:
     68        (JSC::NumberConstructor::getOwnPropertyDescriptor):
     69        * runtime/NumberConstructor.h:
     70        * runtime/ObjectConstructor.cpp:
     71        (JSC::ObjectConstructor::ObjectConstructor):
     72        (JSC::objectConstructorGetOwnPropertyDescriptor):
     73        * runtime/PropertyDescriptor.cpp: Added.
     74        (JSC::PropertyDescriptor::writable):
     75        (JSC::PropertyDescriptor::enumerable):
     76        (JSC::PropertyDescriptor::configurable):
     77        (JSC::PropertyDescriptor::hasAccessors):
     78        (JSC::PropertyDescriptor::setUndefined):
     79        (JSC::PropertyDescriptor::getter):
     80        (JSC::PropertyDescriptor::setter):
     81        (JSC::PropertyDescriptor::setDescriptor):
     82        (JSC::PropertyDescriptor::setAccessorDescriptor):
     83        * runtime/PropertyDescriptor.h: Added.
     84        (JSC::PropertyDescriptor::PropertyDescriptor):
     85        (JSC::PropertyDescriptor::attributes):
     86        (JSC::PropertyDescriptor::isValid):
     87        (JSC::PropertyDescriptor::value):
     88        * runtime/RegExpConstructor.cpp:
     89        (JSC::RegExpConstructor::getOwnPropertyDescriptor):
     90        * runtime/RegExpConstructor.h:
     91        * runtime/RegExpMatchesArray.h:
     92        (JSC::RegExpMatchesArray::getOwnPropertyDescriptor):
     93        * runtime/RegExpObject.cpp:
     94        (JSC::RegExpObject::getOwnPropertyDescriptor):
     95        * runtime/RegExpObject.h:
     96        * runtime/StringObject.cpp:
     97        (JSC::StringObject::getOwnPropertyDescriptor):
     98        * runtime/StringObject.h:
     99        * runtime/StringPrototype.cpp:
     100        (JSC::StringPrototype::getOwnPropertyDescriptor):
     101        * runtime/StringPrototype.h:
     102
    11032009-08-24  Gavin Barraclough  <barraclough@apple.com>
    2104
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r47752 r47780  
    118118__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE
    119119__ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
     120__ZN3JSC12StringObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
    120121__ZN3JSC12StringObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
    121122__ZN3JSC12StringObject4infoE
     
    147148__ZN3JSC16InternalFunctionC2EPNS_12JSGlobalDataEN3WTF10PassRefPtrINS_9StructureEEERKNS_10IdentifierE
    148149__ZN3JSC16JSVariableObject14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE
     150__ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescriptorE
    149151__ZN3JSC16JSVariableObject16getPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayE
    150152__ZN3JSC16toUInt32SlowCaseEdRb
     
    155157__ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi
    156158__ZN3JSC18DebuggerActivationC1EPNS_8JSObjectE
     159__ZN3JSC18PropertyDescriptor12setUndefinedEv
     160__ZN3JSC18PropertyDescriptor13setDescriptorENS_7JSValueEj
     161__ZN3JSC18PropertyDescriptor21setAccessorDescriptorENS_7JSValueES1_j
     162__ZNK3JSC18PropertyDescriptor6setterEv
     163__ZNK3JSC18PropertyDescriptor6getterEv
    157164__ZN3JSC19constructEmptyArrayEPNS_9ExecStateE
    158165__ZN3JSC19initializeThreadingEv
     
    245252__ZN3JSC8JSObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE
    246253__ZN3JSC8JSObject18getPrimitiveNumberEPNS_9ExecStateERdRNS_7JSValueE
     254__ZN3JSC8JSObject21getPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
    247255__ZN3JSC8JSObject22fillGetterPropertySlotERNS_12PropertySlotEPNS_7JSValueE 
    248256__ZN3JSC8JSObject23allocatePropertyStorageEmm
     257__ZN3JSC8JSObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE
    249258__ZN3JSC8JSObject3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE
    250259__ZN3JSC8JSObject3putEPNS_9ExecStateEjNS_7JSValueE 
     
    338347__ZNK3JSC17DebuggerCallFrame4typeEv
    339348__ZNK3JSC17DebuggerCallFrame8evaluateERKNS_7UStringERNS_7JSValueE
     349__ZNK3JSC18PropertyDescriptor12hasAccessorsEv
    340350__ZNK3JSC4Heap10statisticsEv
    341351__ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE
  • trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r47665 r47780  
    216216                A7F9935F0FD7325100A0B2D0 /* JSONObject.h in Headers */ = {isa = PBXBuildFile; fileRef = A7F9935D0FD7325100A0B2D0 /* JSONObject.h */; };
    217217                A7F993600FD7325100A0B2D0 /* JSONObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7F9935E0FD7325100A0B2D0 /* JSONObject.cpp */; };
     218                A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7FB60A3103F7DC20017A286 /* PropertyDescriptor.cpp */; };
     219                A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */; settings = {ATTRIBUTES = (Private, ); }; };
    218220                BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9050E1839DB000F9297 /* ErrorConstructor.h */; };
    219221                BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9070E1839DB000F9297 /* ErrorPrototype.h */; };
     
    769771                A7F9935E0FD7325100A0B2D0 /* JSONObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSONObject.cpp; sourceTree = "<group>"; };
    770772                A7F9949A0FD746A300A0B2D0 /* JSONObject.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSONObject.lut.h; path = /Users/oliver/builds/Debug/DerivedSources/JavaScriptCore/JSONObject.lut.h; sourceTree = "<absolute>"; };
     773                A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyDescriptor.h; sourceTree = "<group>"; };
     774                A7FB60A3103F7DC20017A286 /* PropertyDescriptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyDescriptor.cpp; sourceTree = "<group>"; };
    771775                A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; };
    772776                A8E894330CD0603F00367179 /* JSGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObject.h; sourceTree = "<group>"; };
     
    13391343                        isa = PBXGroup;
    13401344                        children = (
     1345                                A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */,
    13411346                                BCF605110E203EF800B9A64D /* ArgList.cpp */,
    13421347                                BCF605120E203EF800B9A64D /* ArgList.h */,
     
    15111516                                A7C530E3102A3813005BC741 /* MarkStackPosix.cpp */,
    15121517                                A74B3498102A5F8E0032AB98 /* MarkStack.cpp */,
     1518                                A7FB60A3103F7DC20017A286 /* PropertyDescriptor.cpp */,
    15131519                        );
    15141520                        path = runtime;
     
    19161922                                86CAFEE31035DDE60028A609 /* Executable.h in Headers */,
    19171923                                142D3939103E4560007DCB52 /* NumericStrings.h in Headers */,
     1924                                A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */,
    19181925                        );
    19191926                        runOnlyForDeploymentPostprocessing = 0;
     
    22852292                                A74B3499102A5F8E0032AB98 /* MarkStack.cpp in Sources */,
    22862293                                86CA032E1038E8440028A609 /* Executable.cpp in Sources */,
     2294                                A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */,
    22872295                        );
    22882296                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/JavaScriptCore/runtime/Arguments.cpp

    r47022 r47780  
    180180}
    181181
     182bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     183{
     184    bool isArrayIndex;
     185    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
     186    if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
     187        if (i < d->numParameters) {
     188            descriptor.setDescriptor(d->registers[d->firstParameterIndex + i].jsValue(), DontEnum);
     189        } else
     190            descriptor.setDescriptor(d->extraArguments[i - d->numParameters].jsValue(), DontEnum);
     191        return true;
     192    }
     193   
     194    if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
     195        descriptor.setDescriptor(jsNumber(exec, d->numArguments), DontEnum);
     196        return true;
     197    }
     198   
     199    if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
     200        descriptor.setDescriptor(d->callee, DontEnum);
     201        return true;
     202    }
     203   
     204    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     205}
     206
    182207void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot)
    183208{
  • trunk/JavaScriptCore/runtime/Arguments.h

    r47641 r47780  
    9393        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    9494        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
     95        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    9596        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    9697        virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&);
  • trunk/JavaScriptCore/runtime/ArrayPrototype.cpp

    r47738 r47780  
    126126}
    127127
     128bool ArrayPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     129{
     130    return getStaticFunctionDescriptor<JSArray>(exec, ExecState::arrayTable(exec), this, propertyName, descriptor);
     131}
     132
    128133// ------------------------------ Array Functions ----------------------------
    129134
  • trunk/JavaScriptCore/runtime/ArrayPrototype.h

    r38440 r47780  
    3232
    3333        bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     34        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    3435
    3536        virtual const ClassInfo* classInfo() const { return &info; }
  • trunk/JavaScriptCore/runtime/CommonIdentifiers.h

    r47271 r47780  
    3838    macro(caller) \
    3939    macro(compile) \
     40    macro(configurable) \
    4041    macro(constructor) \
     42    macro(enumerable) \
    4143    macro(eval) \
    4244    macro(exec) \
    4345    macro(fromCharCode) \
    4446    macro(global) \
     47    macro(get) \
    4548    macro(getPrototypeOf) \
     49    macro(getOwnPropertyDescriptor) \
    4650    macro(hasOwnProperty) \
    4751    macro(ignoreCase) \
     
    5862    macro(propertyIsEnumerable) \
    5963    macro(prototype) \
     64    macro(set) \
    6065    macro(source) \
    6166    macro(test) \
     
    6873    macro(toString) \
    6974    macro(UTC) \
     75    macro(value) \
    7076    macro(valueOf) \
     77    macro(writable) \
    7178    macro(displayName)
    7279
  • trunk/JavaScriptCore/runtime/DatePrototype.cpp

    r47288 r47780  
    408408}
    409409
     410
     411bool DatePrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     412{
     413    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::dateTable(exec), this, propertyName, descriptor);
     414}
     415
    410416// Functions
    411417
  • trunk/JavaScriptCore/runtime/DatePrototype.h

    r43122 r47780  
    3333
    3434        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     35        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    3536
    3637        virtual const ClassInfo* classInfo() const { return &info; }
  • trunk/JavaScriptCore/runtime/JSArray.cpp

    r47653 r47780  
    240240
    241241    return JSObject::getOwnPropertySlot(exec, propertyName, slot);
     242}
     243
     244bool JSArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     245{
     246    if (propertyName == exec->propertyNames().length) {
     247        descriptor.setDescriptor(jsNumber(exec, length()), DontDelete | DontEnum);
     248        return true;
     249    }
     250   
     251    bool isArrayIndex;
     252    unsigned i = propertyName.toArrayIndex(&isArrayIndex);
     253    if (isArrayIndex) {
     254        if (i >= m_storage->m_length)
     255            return false;
     256        if (i < m_storage->m_vectorLength) {
     257            JSValue value = m_storage->m_vector[i];
     258            if (value) {
     259                descriptor.setDescriptor(value, 0);
     260                return true;
     261            }
     262        } else if (SparseArrayValueMap* map = m_storage->m_sparseValueMap) {
     263            if (i >= MIN_SPARSE_ARRAY_INDEX) {
     264                SparseArrayValueMap::iterator it = map->find(i);
     265                if (it != map->end()) {
     266                    descriptor.setDescriptor(it->second, 0);
     267                    return true;
     268                }
     269            }
     270        }
     271    }
     272    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
    242273}
    243274
  • trunk/JavaScriptCore/runtime/JSArray.h

    r47269 r47780  
    4848        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    4949        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
     50        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    5051        virtual void put(ExecState*, unsigned propertyName, JSValue); // FIXME: Make protected and add setItem.
    5152
  • trunk/JavaScriptCore/runtime/JSByteArray.cpp

    r47267 r47780  
    6060    return JSObject::getOwnPropertySlot(exec, propertyName, slot);
    6161}
    62    
     62
     63bool JSByteArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     64{
     65    bool ok;
     66    unsigned index = propertyName.toUInt32(&ok, false);
     67    if (ok && canAccessIndex(index)) {
     68        descriptor.setDescriptor(getIndex(exec, index), DontDelete);
     69        return true;
     70    }
     71    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     72}
     73
    6374bool JSByteArray::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
    6475{
  • trunk/JavaScriptCore/runtime/JSByteArray.h

    r46528 r47780  
    7979        virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
    8080        virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
     81        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    8182        virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
    8283        virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue);
  • trunk/JavaScriptCore/runtime/JSFunction.cpp

    r47686 r47780  
    178178}
    179179
     180    bool JSFunction::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     181    {
     182        if (isHostFunction())
     183            return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     184       
     185        if (propertyName == exec->propertyNames().prototype) {
     186            PropertySlot slot;
     187            getOwnPropertySlot(exec, propertyName, slot);
     188            return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     189        }
     190       
     191        if (propertyName == exec->propertyNames().arguments) {
     192            descriptor.setDescriptor(exec->interpreter()->retrieveArguments(exec, this), ReadOnly | DontEnum | DontDelete);
     193            return true;
     194        }
     195       
     196        if (propertyName == exec->propertyNames().length) {
     197            descriptor.setDescriptor(jsNumber(exec, jsExecutable()->parameterCount()), ReadOnly | DontEnum | DontDelete);
     198            return true;
     199        }
     200       
     201        if (propertyName == exec->propertyNames().caller) {
     202            descriptor.setDescriptor(exec->interpreter()->retrieveCaller(exec, this), ReadOnly | DontEnum | DontDelete);
     203            return true;
     204        }
     205       
     206        return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     207    }
     208   
    180209void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    181210{
  • trunk/JavaScriptCore/runtime/JSFunction.h

    r47664 r47780  
    7979
    8080        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     81        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    8182        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    8283        virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
  • trunk/JavaScriptCore/runtime/JSGlobalObject.h

    r47404 r47780  
    171171
    172172        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     173        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    173174        virtual bool hasOwnPropertyForWrite(ExecState*, const Identifier&);
    174175        virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
     
    327328    }
    328329
     330    inline bool JSGlobalObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     331    {
     332        if (symbolTableGet(propertyName, descriptor))
     333            return true;
     334        return JSVariableObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     335    }
     336
    329337    inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
    330338    {
  • trunk/JavaScriptCore/runtime/JSNotAnObject.cpp

    r47022 r47780  
    9494}
    9595
     96bool JSNotAnObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier&, PropertyDescriptor&)
     97{
     98    ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception);
     99    return false;
     100}
     101
    96102void JSNotAnObject::put(ExecState* exec, const Identifier& , JSValue, PutPropertySlot&)
    97103{
  • trunk/JavaScriptCore/runtime/JSNotAnObject.h

    r47022 r47780  
    8181        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    8282        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
     83        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    8384
    8485        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
  • trunk/JavaScriptCore/runtime/JSONObject.cpp

    r47086 r47780  
    582582bool JSONObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
    583583{
    584     const HashEntry* entry = ExecState::jsonTable(exec)->entry(exec, propertyName);
    585     if (!entry)
    586         return JSObject::getOwnPropertySlot(exec, propertyName, slot);
    587 
    588     ASSERT(entry->attributes() & Function);
    589     setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
    590     return true;
     584    return getStaticFunctionSlot<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, slot);
     585}
     586
     587bool JSONObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     588{
     589    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::jsonTable(exec), this, propertyName, descriptor);
    591590}
    592591
  • trunk/JavaScriptCore/runtime/JSONObject.h

    r47267 r47780  
    4949    private:
    5050        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     51        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    5152
    5253        virtual const ClassInfo* classInfo() const { return &info; }
  • trunk/JavaScriptCore/runtime/JSObject.cpp

    r47267 r47780  
    3131#include "NativeErrorConstructor.h"
    3232#include "ObjectPrototype.h"
     33#include "PropertyDescriptor.h"
    3334#include "PropertyNameArray.h"
    3435#include "Lookup.h"
     
    505506}
    506507
     508bool JSObject::getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor& descriptor)
     509{
     510    unsigned attributes = 0;
     511    JSCell* cell = 0;
     512    size_t offset = m_structure->get(propertyName, attributes, cell);
     513    if (offset == WTF::notFound)
     514        return false;
     515    descriptor.setDescriptor(getDirectOffset(offset), attributes);
     516    return true;
     517}
     518
     519bool JSObject::getPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     520{
     521    JSObject* object = this;
     522    while (true) {
     523        if (object->getOwnPropertyDescriptor(exec, propertyName, descriptor))
     524            return true;
     525        JSValue prototype = object->prototype();
     526        if (!prototype.isObject())
     527            return false;
     528        object = asObject(prototype);
     529    }
     530}
    507531} // namespace JSC
  • trunk/JavaScriptCore/runtime/JSObject.h

    r47601 r47780  
    4949    class HashEntry;
    5050    class InternalFunction;
     51    class PropertyDescriptor;
    5152    class PropertyNameArray;
    5253    class Structure;
     
    9697        bool getPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    9798        bool getPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
     99        bool getPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
    98100
    99101        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    100102        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
     103        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    101104
    102105        virtual void put(ExecState*, const Identifier& propertyName, JSValue value, PutPropertySlot&);
  • trunk/JavaScriptCore/runtime/JSString.cpp

    r43506 r47780  
    104104}
    105105
     106bool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     107{
     108    if (propertyName == exec->propertyNames().length) {
     109        descriptor.setDescriptor(jsNumber(exec, m_value.size()), DontEnum | DontDelete | ReadOnly);
     110        return true;
     111    }
     112   
     113    bool isStrictUInt32;
     114    unsigned i = propertyName.toStrictUInt32(&isStrictUInt32);
     115    if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) {
     116        descriptor.setDescriptor(jsSingleCharacterSubstring(exec, m_value, i), DontDelete | ReadOnly);
     117        return true;
     118    }
     119   
     120    return false;
     121}
     122
     123bool JSString::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     124{
     125    if (getStringPropertyDescriptor(exec, propertyName, descriptor))
     126        return true;
     127    if (propertyName != exec->propertyNames().underscoreProto)
     128        return false;
     129    descriptor.setDescriptor(exec->lexicalGlobalObject()->stringPrototype(), DontEnum);
     130    return true;
     131}
     132
    106133bool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot)
    107134{
  • trunk/JavaScriptCore/runtime/JSString.h

    r47622 r47780  
    2828#include "Identifier.h"
    2929#include "JSNumberCell.h"
     30#include "PropertyDescriptor.h"
    3031#include "PropertySlot.h"
    3132
     
    8788        bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    8889        bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
     90        bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
    8991
    9092        bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); }
     
    114116        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    115117        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
     118        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    116119
    117120        UString m_value;
  • trunk/JavaScriptCore/runtime/JSVariableObject.cpp

    r37989 r47780  
    3131
    3232#include "PropertyNameArray.h"
     33#include "PropertyDescriptor.h"
    3334
    3435namespace JSC {
     
    6869}
    6970
     71bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertyDescriptor& descriptor)
     72{
     73    SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
     74    if (!entry.isNull()) {
     75        descriptor.setDescriptor(registerAt(entry.getIndex()).jsValue(), entry.getAttributes() | DontDelete);
     76        return true;
     77    }
     78    return false;
     79}
     80
    7081} // namespace JSC
  • trunk/JavaScriptCore/runtime/JSVariableObject.h

    r43122 r47780  
    9090
    9191        bool symbolTableGet(const Identifier&, PropertySlot&);
     92        bool symbolTableGet(const Identifier&, PropertyDescriptor&);
    9293        bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
    9394        bool symbolTablePut(const Identifier&, JSValue);
  • trunk/JavaScriptCore/runtime/Lookup.h

    r45553 r47780  
    187187    }
    188188
     189    template <class ThisImp, class ParentImp>
     190    inline bool getStaticPropertyDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor)
     191    {
     192        const HashEntry* entry = table->entry(exec, propertyName);
     193       
     194        if (!entry) // not found, forward to parent
     195            return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     196 
     197        PropertySlot slot;
     198        if (entry->attributes() & Function)
     199            setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
     200        else
     201            slot.setCustom(thisObj, entry->propertyGetter());
     202
     203        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     204        return true;
     205    }
     206
    189207    /**
    190208     * Simplified version of getStaticPropertySlot in case there are only functions.
     
    205223        return true;
    206224    }
     225   
     226    /**
     227     * Simplified version of getStaticPropertyDescriptor in case there are only functions.
     228     * Using this instead of getStaticPropertyDescriptor allows 'this' to avoid implementing
     229     * a dummy getValueProperty.
     230     */
     231    template <class ParentImp>
     232    inline bool getStaticFunctionDescriptor(ExecState* exec, const HashTable* table, JSObject* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor)
     233    {
     234        if (static_cast<ParentImp*>(thisObj)->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor))
     235            return true;
     236       
     237        const HashEntry* entry = table->entry(exec, propertyName);
     238        if (!entry)
     239            return false;
     240       
     241        PropertySlot slot;
     242        setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
     243        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     244        return true;
     245    }
    207246
    208247    /**
     
    221260
    222261        slot.setCustom(thisObj, entry->propertyGetter());
     262        return true;
     263    }
     264
     265    /**
     266     * Simplified version of getStaticPropertyDescriptor in case there are no functions, only "values".
     267     * Using this instead of getStaticPropertyDescriptor removes the need for a FuncImp class.
     268     */
     269    template <class ThisImp, class ParentImp>
     270    inline bool getStaticValueDescriptor(ExecState* exec, const HashTable* table, ThisImp* thisObj, const Identifier& propertyName, PropertyDescriptor& descriptor)
     271    {
     272        const HashEntry* entry = table->entry(exec, propertyName);
     273       
     274        if (!entry) // not found, forward to parent
     275            return thisObj->ParentImp::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     276       
     277        ASSERT(!(entry->attributes() & Function));
     278        PropertySlot slot;
     279        slot.setCustom(thisObj, entry->propertyGetter());
     280        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
    223281        return true;
    224282    }
  • trunk/JavaScriptCore/runtime/MathObject.cpp

    r43372 r47780  
    104104bool MathObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot &slot)
    105105{
    106     const HashEntry* entry = ExecState::mathTable(exec)->entry(exec, propertyName);
    107 
    108     if (!entry)
    109         return JSObject::getOwnPropertySlot(exec, propertyName, slot);
    110 
    111     ASSERT(entry->attributes() & Function);
    112     setUpStaticFunctionSlot(exec, entry, this, propertyName, slot);
    113     return true;
     106    return getStaticFunctionSlot<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, slot);
     107}
     108
     109bool MathObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     110{
     111    return getStaticFunctionDescriptor<JSObject>(exec, ExecState::mathTable(exec), this, propertyName, descriptor);
    114112}
    115113
  • trunk/JavaScriptCore/runtime/MathObject.h

    r47267 r47780  
    3131
    3232        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     33        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    3334
    3435        virtual const ClassInfo* classInfo() const { return &info; }
  • trunk/JavaScriptCore/runtime/NumberConstructor.cpp

    r43372 r47780  
    6969}
    7070
     71bool NumberConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     72{
     73    return getStaticValueDescriptor<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, descriptor);
     74}
     75
    7176static JSValue numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&)
    7277{
  • trunk/JavaScriptCore/runtime/NumberConstructor.h

    r47267 r47780  
    3333
    3434        virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     35        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    3536        JSValue getValueProperty(ExecState*, int token) const;
    3637
  • trunk/JavaScriptCore/runtime/ObjectConstructor.cpp

    r47239 r47780  
    2626#include "JSGlobalObject.h"
    2727#include "ObjectPrototype.h"
     28#include "PropertyDescriptor.h"
    2829#include "PrototypeFunction.h"
    2930
     
    3334
    3435static JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&);
     36static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*, JSObject*, JSValue, const ArgList&);
    3537
    3638ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure)
    37     : InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
     39: InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object"))
    3840{
    3941    // ECMA 15.2.3.1
    4042    putDirectWithoutTransition(exec->propertyNames().prototype, objectPrototype, DontEnum | DontDelete | ReadOnly);
    41 
     43   
    4244    // no. of arguments for constructor
    4345    putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete);
    44 
     46   
    4547    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getPrototypeOf, objectConstructorGetPrototypeOf), DontEnum);
     48    putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum);
    4649}
    4750
     
    8487}
    8588
     89JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec, JSObject*, JSValue, const ArgList& args)
     90{
     91    if (!args.at(0).isObject())
     92        return throwError(exec, TypeError, "Requested property descriptor of a value that is not an object.");
     93    UString propertyName = args.at(1).toString(exec);
     94    if (exec->hadException())
     95        return jsNull();
     96    JSObject* object = asObject(args.at(0));
     97    PropertyDescriptor descriptor;
     98    if (!object->getOwnPropertyDescriptor(exec, Identifier(exec, propertyName), descriptor))
     99        return jsUndefined();
     100    if (exec->hadException())
     101        return jsUndefined();
     102    ASSERT(descriptor.isValid());
     103
     104    JSObject* description = constructEmptyObject(exec);
     105    if (!descriptor.hasAccessors()) {
     106        description->putDirect(exec->propertyNames().value, descriptor.value(), 0);
     107        description->putDirect(exec->propertyNames().writable, jsBoolean(descriptor.writable()), 0);
     108    } else {
     109        description->putDirect(exec->propertyNames().get, descriptor.getter(), 0);
     110        description->putDirect(exec->propertyNames().set, descriptor.setter(), 0);
     111    }
     112   
     113    description->putDirect(exec->propertyNames().enumerable, jsBoolean(descriptor.enumerable()), 0);
     114    description->putDirect(exec->propertyNames().configurable, jsBoolean(descriptor.configurable()), 0);
     115
     116    return description;
     117}
     118
    86119} // namespace JSC
  • trunk/JavaScriptCore/runtime/PropertyDescriptor.h

    r47779 r47780  
    2424 */
    2525
    26 #ifndef JSONObject_h
    27 #define JSONObject_h
     26#ifndef PropertyDescriptor_h
     27#define PropertyDescriptor_h
    2828
    29 #include "JSObject.h"
     29#include "JSValue.h"
    3030
    3131namespace JSC {
    32 
    33     class Stringifier;
    34 
    35     class JSONObject : public JSObject {
     32    class PropertyDescriptor {
    3633    public:
    37         JSONObject(PassRefPtr<Structure> structure)
    38             : JSObject(structure)
     34        PropertyDescriptor()
     35            : m_attributes(0)
    3936        {
    4037        }
     38        bool writable() const;
     39        bool enumerable() const;
     40        bool configurable() const;
     41        bool hasAccessors() const;
     42        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; }
     47        JSValue getter() const;
     48        JSValue setter() const;
     49        void setUndefined();
     50        void setDescriptor(JSValue value, unsigned attributes);
     51        void setAccessorDescriptor(JSValue getter, JSValue setter, unsigned attributes);
     52    private:
     53        // May be a getter/setter
     54        JSValue m_value;
     55        JSValue m_getter;
     56        JSValue m_setter;
     57        unsigned m_attributes;
     58    };
     59}
    4160
    42         static PassRefPtr<Structure> createStructure(JSValue prototype)
    43         {
    44             return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark));
    45         }
    46 
    47         static void markStringifiers(MarkStack&, Stringifier*);
    48 
    49     private:
    50         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
    51 
    52         virtual const ClassInfo* classInfo() const { return &info; }
    53         static const ClassInfo info;
    54     };
    55 
    56 } // namespace JSC
    57 
    58 #endif // JSONObject_h
     61#endif
  • trunk/JavaScriptCore/runtime/RegExpConstructor.cpp

    r47288 r47780  
    235235}
    236236
     237bool RegExpConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     238{
     239    return getStaticValueDescriptor<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, descriptor);
     240}
     241
    237242JSValue regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot)
    238243{
  • trunk/JavaScriptCore/runtime/RegExpConstructor.h

    r47267 r47780  
    4242        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    4343        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
     44        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    4445
    4546        static const ClassInfo info;
  • trunk/JavaScriptCore/runtime/RegExpMatchesArray.h

    r44224 r47780  
    4545        }
    4646
     47        virtual bool getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     48        {
     49            if (lazyCreationData())
     50                fillArrayInstance(exec);
     51            return JSArray::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     52        }
     53
    4754        virtual void put(ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot)
    4855        {
  • trunk/JavaScriptCore/runtime/RegExpObject.cpp

    r44224 r47780  
    7171{
    7272    return getStaticValueSlot<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, slot);
     73}
     74
     75bool RegExpObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     76{
     77    return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, descriptor);
    7378}
    7479
  • trunk/JavaScriptCore/runtime/RegExpObject.h

    r47267 r47780  
    4242
    4343        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
     44        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    4445        virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    4546
  • trunk/JavaScriptCore/runtime/StringObject.cpp

    r43122 r47780  
    6262}
    6363
     64bool StringObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     65{
     66    if (internalValue()->getStringPropertyDescriptor(exec, propertyName, descriptor))
     67        return true;   
     68    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     69}
     70
    6471void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    6572{
  • trunk/JavaScriptCore/runtime/StringObject.h

    r43122 r47780  
    3636        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
    3737        virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
     38        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    3839
    3940        virtual void put(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&);
  • trunk/JavaScriptCore/runtime/StringPrototype.cpp

    r47646 r47780  
    132132{
    133133    return getStaticFunctionSlot<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, slot);
     134}
     135
     136bool StringPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     137{
     138    return getStaticFunctionDescriptor<StringObject>(exec, ExecState::stringTable(exec), this, propertyName, descriptor);
    134139}
    135140
  • trunk/JavaScriptCore/runtime/StringPrototype.h

    r38440 r47780  
    3333
    3434        virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
     35        virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    3536
    3637        virtual const ClassInfo* classInfo() const { return &info; }
  • trunk/LayoutTests/ChangeLog

    r47773 r47780  
     12009-08-25  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        [ES5] Implement getOwnPropertyDescriptor
     6        https://bugs.webkit.org/show_bug.cgi?id=28724
     7
     8        Add tests for getOwnProeprtyDescriptor
     9
     10        * fast/js/getOwnPropertyDescriptor-expected.txt: Added.
     11        * fast/js/getOwnPropertyDescriptor.html: Added.
     12        * fast/js/resources/getOwnPropertyDescriptor.js: Added.
     13        ():
     14
    1152009-08-25  Dmitry Titov  <dimich@chromium.org>
    216
  • trunk/WebCore/ChangeLog

    r47779 r47780  
     12009-08-25  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        [ES5] Implement getOwnPropertyDescriptor
     6        https://bugs.webkit.org/show_bug.cgi?id=28724
     7
     8        Implement the WebCore side of getOwnPropertyDescriptor.  This
     9        requires a custom implementation of getOwnPropertyDescriptor
     10        for every class with a custom implementation of getOwnPropertySlot.
     11
     12        The bindings generator has been updated to generate appropriate
     13        versions of getOwnPropertyDescriptor for the general case where
     14        a custom getOwnPropertyDescriptor is not needed.  ES5 is vague
     15        about how getOwnPropertyDescriptor should work in the context of
     16        "host" functions with polymorphic [[GetOwnProperty]], so it seems
     17        okay that occasionally we "guess" what attributes -- eg. determining
     18        whether a property is writable.
     19
     20        Test: fast/js/getOwnPropertyDescriptor.html
     21
     22        * bindings/js/JSDOMWindowCustom.cpp:
     23        (WebCore::JSDOMWindow::getOwnPropertyDescriptor):
     24        * bindings/js/JSDOMWindowShell.cpp:
     25        (WebCore::JSDOMWindowShell::getOwnPropertyDescriptor):
     26        * bindings/js/JSDOMWindowShell.h:
     27        * bindings/js/JSHTMLAppletElementCustom.cpp:
     28        (WebCore::JSHTMLAppletElement::getOwnPropertyDescriptorDelegate):
     29        * bindings/js/JSHTMLEmbedElementCustom.cpp:
     30        (WebCore::JSHTMLEmbedElement::getOwnPropertyDescriptorDelegate):
     31        * bindings/js/JSHTMLObjectElementCustom.cpp:
     32        (WebCore::JSHTMLObjectElement::getOwnPropertyDescriptorDelegate):
     33        * bindings/js/JSHistoryCustom.cpp:
     34        (WebCore::JSHistory::getOwnPropertyDescriptorDelegate):
     35        * bindings/js/JSLocationCustom.cpp:
     36        (WebCore::JSLocation::getOwnPropertyDescriptorDelegate):
     37        * bindings/js/JSNamedNodesCollection.cpp:
     38        (WebCore::JSNamedNodesCollection::getOwnPropertyDescriptor):
     39        * bindings/js/JSNamedNodesCollection.h:
     40        * bindings/js/JSPluginElementFunctions.cpp:
     41        (WebCore::runtimeObjectCustomGetOwnPropertyDescriptor):
     42        * bindings/js/JSPluginElementFunctions.h:
     43        * bindings/js/JSQuarantinedObjectWrapper.cpp:
     44        (WebCore::JSQuarantinedObjectWrapper::getOwnPropertyDescriptor):
     45        * bindings/js/JSQuarantinedObjectWrapper.h:
     46        * bindings/js/JSWorkerContextCustom.cpp:
     47        (WebCore::JSWorkerContext::getOwnPropertyDescriptorDelegate):
     48        * bindings/scripts/CodeGeneratorJS.pm:
     49        * bridge/objc/objc_runtime.h:
     50        * bridge/objc/objc_runtime.mm:
     51        (JSC::Bindings::ObjcFallbackObjectImp::getOwnPropertyDescriptor):
     52        * bridge/runtime.h:
     53        (JSC::Bindings::Instance::getOwnPropertyDescriptor):
     54        * bridge/runtime_array.cpp:
     55        (JSC::RuntimeArray::getOwnPropertyDescriptor):
     56        * bridge/runtime_array.h:
     57        * bridge/runtime_method.cpp:
     58        (JSC::RuntimeMethod::getOwnPropertyDescriptor):
     59        * bridge/runtime_method.h:
     60        * bridge/runtime_object.cpp:
     61        (JSC::RuntimeObjectImp::getOwnPropertyDescriptor):
     62        * bridge/runtime_object.h:
     63
    1642009-08-26  Vincent Untz <vuntz@gnome.org>
    265
  • trunk/WebCore/bindings/js/JSDOMWindowCustom.cpp

    r47697 r47780  
    280280}
    281281
     282bool JSDOMWindow::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     283{
     284    // When accessing a Window cross-domain, functions are always the native built-in ones, and they
     285    // are not affected by properties changed on the Window or anything in its prototype chain.
     286    // This is consistent with the behavior of Firefox.
     287   
     288    const HashEntry* entry;
     289   
     290    // We don't want any properties other than "close" and "closed" on a closed window.
     291    if (!impl()->frame()) {
     292        // The following code is safe for cross-domain and same domain use.
     293        // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
     294        entry = s_info.propHashTable(exec)->entry(exec, propertyName);
     295        if (entry && !(entry->attributes() & Function) && entry->propertyGetter() == jsDOMWindowClosed) {
     296            descriptor.setDescriptor(jsBoolean(true), ReadOnly | DontDelete | DontEnum);
     297            return true;
     298        }
     299        entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
     300        if (entry && (entry->attributes() & Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) {
     301            PropertySlot slot;
     302            slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
     303            descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
     304            return true;
     305        }
     306        descriptor.setUndefined();
     307        return true;
     308    }
     309
     310    String errorMessage;
     311    bool allowsAccess = allowsAccessFrom(exec, errorMessage);
     312    if (allowsAccess && JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor))
     313        return true;
     314
     315    // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the
     316    // prototype due to the blanket same origin (allowsAccessFrom) check at the end of getOwnPropertySlot.
     317    // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of
     318    // what prototype is actually set on this object.
     319    entry = JSDOMWindowPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
     320    if (entry) {
     321        if (entry->attributes() & Function) {
     322            if (entry->function() == jsDOMWindowPrototypeFunctionBlur) {
     323                if (!allowsAccess) {
     324                    PropertySlot slot;
     325                    slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>);
     326                    descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
     327                    return true;
     328                }
     329            } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) {
     330                if (!allowsAccess) {
     331                    PropertySlot slot;
     332                    slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
     333                    descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
     334                    return true;
     335                }
     336            } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) {
     337                if (!allowsAccess) {
     338                    PropertySlot slot;
     339                    slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>);
     340                    descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
     341                    return true;
     342                }
     343            } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) {
     344                if (!allowsAccess) {
     345                    PropertySlot slot;
     346                    slot.setCustom(this, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>);
     347                    descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
     348                    return true;
     349                }
     350            } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) {
     351                if (!DOMWindow::canShowModalDialog(impl()->frame())) {
     352                    descriptor.setUndefined();
     353                    return true;
     354                }
     355            }
     356        }
     357    } else {
     358        // Allow access to toString() cross-domain, but always Object.prototype.toString.
     359        if (propertyName == exec->propertyNames().toString) {
     360            if (!allowsAccess) {
     361                PropertySlot slot;
     362                slot.setCustom(this, objectToStringFunctionGetter);
     363                descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
     364                return true;
     365            }
     366        }
     367    }
     368   
     369    entry = JSDOMWindow::s_info.propHashTable(exec)->entry(exec, propertyName);
     370    if (entry) {
     371        PropertySlot slot;
     372        slot.setCustom(this, entry->propertyGetter());
     373        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     374        return true;
     375    }
     376   
     377    // Check for child frames by name before built-in properties to
     378    // match Mozilla. This does not match IE, but some sites end up
     379    // naming frames things that conflict with window properties that
     380    // are in Moz but not IE. Since we have some of these, we have to do
     381    // it the Moz way.
     382    if (impl()->frame()->tree()->child(propertyName)) {
     383        PropertySlot slot;
     384        slot.setCustom(this, childFrameGetter);
     385        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
     386        return true;
     387    }
     388   
     389    // Do prototype lookup early so that functions and attributes in the prototype can have
     390    // precedence over the index and name getters. 
     391    JSValue proto = prototype();
     392    if (proto.isObject()) {
     393        if (asObject(proto)->getPropertyDescriptor(exec, propertyName, descriptor)) {
     394            if (!allowsAccess) {
     395                printErrorMessage(errorMessage);
     396                descriptor.setUndefined();
     397            }
     398            return true;
     399        }
     400    }
     401
     402    bool ok;
     403    unsigned i = propertyName.toArrayIndex(&ok);
     404    if (ok && i < impl()->frame()->tree()->childCount()) {
     405        PropertySlot slot;
     406        slot.setCustomIndex(this, i, indexGetter);
     407        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
     408        return true;
     409    }
     410
     411    // Allow shortcuts like 'Image1' instead of document.images.Image1
     412    Document* document = impl()->frame()->document();
     413    if (document->isHTMLDocument()) {
     414        AtomicStringImpl* atomicPropertyName = AtomicString::find(propertyName);
     415        if (atomicPropertyName && (static_cast<HTMLDocument*>(document)->hasNamedItem(atomicPropertyName) || document->hasElementWithId(atomicPropertyName))) {
     416            PropertySlot slot;
     417            slot.setCustom(this, namedItemGetter);
     418            descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
     419            return true;
     420        }
     421    }
     422   
     423    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     424}
     425
    282426void JSDOMWindow::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    283427{
  • trunk/WebCore/bindings/js/JSDOMWindowShell.cpp

    r47022 r47780  
    8989}
    9090
     91bool JSDOMWindowShell::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     92{
     93    return m_window->getOwnPropertyDescriptor(exec, propertyName, descriptor);
     94}
     95
    9196void JSDOMWindowShell::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    9297{
  • trunk/WebCore/bindings/js/JSDOMWindowShell.h

    r47022 r47780  
    6868        virtual JSC::UString className() const;
    6969        virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);
     70        virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);
    7071        virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);
    7172        virtual void putWithAttributes(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, unsigned attributes);
  • trunk/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp

    r44677 r47780  
    3939}
    4040
     41bool JSHTMLAppletElement::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     42{
     43    return runtimeObjectCustomGetOwnPropertyDescriptor(exec, propertyName, descriptor, this);
     44}
     45
    4146bool JSHTMLAppletElement::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    4247{
  • trunk/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp

    r44677 r47780  
    3939}
    4040
     41bool JSHTMLEmbedElement::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     42{
     43    return runtimeObjectCustomGetOwnPropertyDescriptor(exec, propertyName, descriptor, this);
     44}
     45
    4146bool JSHTMLEmbedElement::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    4247{
  • trunk/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp

    r44677 r47780  
    3939}
    4040
     41bool JSHTMLObjectElement::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     42{
     43    return runtimeObjectCustomGetOwnPropertyDescriptor(exec, propertyName, descriptor, this);
     44}
     45
    4146bool JSHTMLObjectElement::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    4247{
  • trunk/WebCore/bindings/js/JSHistoryCustom.cpp

    r47236 r47780  
    9494}
    9595
     96bool JSHistory::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     97{
     98    // When accessing History cross-domain, functions are always the native built-in ones.
     99    // See JSDOMWindow::getOwnPropertySlotDelegate for additional details.
     100   
     101    // Our custom code is only needed to implement the Window cross-domain scheme, so if access is
     102    // allowed, return false so the normal lookup will take place.
     103    String message;
     104    if (allowsAccessFromFrame(exec, impl()->frame(), message))
     105        return false;
     106   
     107    // Check for the few functions that we allow, even when called cross-domain.
     108    const HashEntry* entry = JSHistoryPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
     109    if (entry) {
     110        PropertySlot slot;
     111        // Allow access to back(), forward() and go() from any frame.
     112        if (entry->attributes() & Function) {
     113            if (entry->function() == jsHistoryPrototypeFunctionBack) {
     114                slot.setCustom(this, nonCachingStaticBackFunctionGetter);
     115                descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     116                return true;
     117            } else if (entry->function() == jsHistoryPrototypeFunctionForward) {
     118                slot.setCustom(this, nonCachingStaticForwardFunctionGetter);
     119                descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     120                return true;
     121            } else if (entry->function() == jsHistoryPrototypeFunctionGo) {
     122                slot.setCustom(this, nonCachingStaticGoFunctionGetter);
     123                descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     124                return true;
     125            }
     126        }
     127    } else {
     128        // Allow access to toString() cross-domain, but always Object.toString.
     129        if (propertyName == exec->propertyNames().toString) {
     130            PropertySlot slot;
     131            slot.setCustom(this, objectToStringFunctionGetter);
     132            descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     133            return true;
     134        }
     135    }
     136   
     137    printErrorMessageForFrame(impl()->frame(), message);
     138    descriptor.setUndefined();
     139    return true;
     140}
     141
    96142bool JSHistory::putDelegate(ExecState* exec, const Identifier&, JSValue, PutPropertySlot&)
    97143{
  • trunk/WebCore/bindings/js/JSLocationCustom.cpp

    r47236 r47780  
    9595}
    9696
     97bool JSLocation::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     98{
     99    Frame* frame = impl()->frame();
     100    if (!frame) {
     101        descriptor.setUndefined();
     102        return true;
     103    }
     104   
     105    // When accessing Location cross-domain, functions are always the native built-in ones.
     106    // See JSDOMWindow::getOwnPropertySlotDelegate for additional details.
     107   
     108    // Our custom code is only needed to implement the Window cross-domain scheme, so if access is
     109    // allowed, return false so the normal lookup will take place.
     110    String message;
     111    if (allowsAccessFromFrame(exec, frame, message))
     112        return false;
     113   
     114    // Check for the few functions that we allow, even when called cross-domain.
     115    const HashEntry* entry = JSLocationPrototype::s_info.propHashTable(exec)->entry(exec, propertyName);
     116    PropertySlot slot;
     117    if (entry && (entry->attributes() & Function)) {
     118        if (entry->function() == jsLocationPrototypeFunctionReplace) {
     119            slot.setCustom(this, nonCachingStaticReplaceFunctionGetter);
     120            descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     121            return true;
     122        } else if (entry->function() == jsLocationPrototypeFunctionReload) {
     123            slot.setCustom(this, nonCachingStaticReloadFunctionGetter);
     124            descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     125            return true;
     126        } else if (entry->function() == jsLocationPrototypeFunctionAssign) {
     127            slot.setCustom(this, nonCachingStaticAssignFunctionGetter);
     128            descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     129            return true;
     130        }
     131    }
     132   
     133    // FIXME: Other implementers of the Window cross-domain scheme (Window, History) allow toString,
     134    // but for now we have decided not to, partly because it seems silly to return "[Object Location]" in
     135    // such cases when normally the string form of Location would be the URL.
     136   
     137    printErrorMessageForFrame(frame, message);
     138    descriptor.setUndefined();
     139    return true;
     140}
     141
    97142bool JSLocation::putDelegate(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    98143{
  • trunk/WebCore/bindings/js/JSNamedNodesCollection.cpp

    r46322 r47780  
    9090}
    9191
     92bool JSNamedNodesCollection::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     93{
     94    if (propertyName == exec->propertyNames().length) {
     95        descriptor.setDescriptor(jsNumber(exec, m_nodes->size()), ReadOnly | DontDelete | DontEnum);
     96        return true;
     97    }
     98   
     99    bool ok;
     100    unsigned index = propertyName.toUInt32(&ok);
     101    if (ok && index < m_nodes->size()) {
     102        PropertySlot slot;
     103        slot.setCustomIndex(this, index, indexGetter);
     104        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete);
     105        return true;
     106    }
     107   
     108    // For IE compatibility, we need to be able to look up elements in a
     109    // document.formName.name result by id as well as be index.
     110   
     111    AtomicString atomicPropertyName = propertyName;
     112    for (unsigned i = 0; i < m_nodes->size(); i++) {
     113        Node* node = (*m_nodes)[i].get();
     114        if (node->hasAttributes() && node->attributes()->id() == atomicPropertyName) {
     115            PropertySlot slot;
     116            slot.setCustomIndex(this, i, indexGetter);
     117            descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete);
     118            return true;
     119        }
     120    }
     121   
     122    return DOMObjectWithGlobalPointer::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     123}
     124
    92125} // namespace WebCore
  • trunk/WebCore/bindings/js/JSNamedNodesCollection.h

    r46320 r47780  
    4141
    4242        virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);
     43        virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);
    4344
    4445        virtual const JSC::ClassInfo* classInfo() const { return &s_info; }
  • trunk/WebCore/bindings/js/JSPluginElementFunctions.cpp

    r43372 r47780  
    8787}
    8888
     89bool runtimeObjectCustomGetOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, JSHTMLElement* element)
     90{
     91    RuntimeObjectImp* runtimeObject = getRuntimeObject(exec, element->impl());
     92    if (!runtimeObject)
     93        return false;
     94    if (!runtimeObject->hasProperty(exec, propertyName))
     95        return false;
     96    PropertySlot slot;
     97    slot.setCustom(element, runtimeObjectPropertyGetter);
     98    // While we don't know what the plugin allows, we do know that we prevent
     99    // enumeration or deletion of properties, so we mark plugin properties
     100    // as DontEnum | DontDelete
     101    descriptor.setDescriptor(slot.getValue(exec, propertyName), DontEnum | DontDelete);
     102    return true;
     103}
     104
    89105bool runtimeObjectCustomPut(ExecState* exec, const Identifier& propertyName, JSValue value, HTMLElement* element, PutPropertySlot& slot)
    90106{
  • trunk/WebCore/bindings/js/JSPluginElementFunctions.h

    r43122 r47780  
    3434    JSC::JSValue runtimeObjectPropertyGetter(JSC::ExecState*, const JSC::Identifier&, const JSC::PropertySlot&);
    3535    bool runtimeObjectCustomGetOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&, JSHTMLElement*);
     36    bool runtimeObjectCustomGetOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&, JSHTMLElement*);
    3637    bool runtimeObjectCustomPut(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, HTMLElement*, JSC::PutPropertySlot&);
    3738    JSC::CallType runtimeObjectGetCallData(HTMLElement*, JSC::CallData&);
  • trunk/WebCore/bindings/js/JSQuarantinedObjectWrapper.cpp

    r47022 r47780  
    139139}
    140140
     141bool JSQuarantinedObjectWrapper::getOwnPropertyDescriptor(ExecState* exec, const Identifier& identifier, PropertyDescriptor& descriptor)
     142{
     143    if (!allowsGetProperty()) {
     144        descriptor.setUndefined();
     145        return true;
     146    }
     147
     148    PropertyDescriptor unwrappedDescriptor;
     149    bool result = m_unwrappedObject->getOwnPropertyDescriptor(unwrappedExecState(), identifier, unwrappedDescriptor);
     150
     151    if (unwrappedDescriptor.hasAccessors()) {
     152        descriptor.setAccessorDescriptor(wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.getter()),
     153                                         wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.setter()),
     154                                         unwrappedDescriptor.attributes());
     155    } else
     156        descriptor.setDescriptor(wrapOutgoingValue(unwrappedExecState(), unwrappedDescriptor.value()), unwrappedDescriptor.attributes());
     157    transferExceptionToExecState(exec);
     158    return result;
     159}
     160
    141161void JSQuarantinedObjectWrapper::put(ExecState* exec, const Identifier& identifier, JSValue value, PutPropertySlot& slot)
    142162{
  • trunk/WebCore/bindings/js/JSQuarantinedObjectWrapper.h

    r47022 r47780  
    5959        virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);
    6060        virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned, JSC::PropertySlot&);
     61        virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);
    6162
    6263        virtual void put(JSC::ExecState*, const JSC::Identifier&, JSC::JSValue, JSC::PutPropertySlot&);
  • trunk/WebCore/bindings/js/JSWorkerContextCustom.cpp

    r47323 r47780  
    7878    // Look for overrides before looking at any of our own properties.
    7979    if (JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot))
     80        return true;
     81    return false;
     82}
     83
     84bool JSWorkerContext::getOwnPropertyDescriptorDelegate(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     85{
     86    // Look for overrides before looking at any of our own properties.
     87    if (JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor))
    8088        return true;
    8189    return false;
  • trunk/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r47288 r47780  
    349349}
    350350
     351sub GenerateGetOwnPropertyDescriptorBody
     352{
     353    my ($dataNode, $interfaceName, $className, $implClassName, $hasAttributes, $inlined) = @_;
     354   
     355    my $namespaceMaybe = ($inlined ? "JSC::" : "");
     356   
     357    my @getOwnPropertyDescriptorImpl = ();
     358   
     359    if ($interfaceName eq "NamedNodeMap" or $interfaceName eq "HTMLCollection") {
     360        push(@getOwnPropertyDescriptorImpl, "    ${namespaceMaybe}JSValue proto = prototype();\n");
     361        push(@getOwnPropertyDescriptorImpl, "    if (proto.isObject() && static_cast<${namespaceMaybe}JSObject*>(asObject(proto))->hasProperty(exec, propertyName))\n");
     362        push(@getOwnPropertyDescriptorImpl, "        return false;\n\n");
     363    }
     364   
     365    my $manualLookupGetterGeneration = sub {
     366        my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
     367        if ($requiresManualLookup) {
     368            push(@getOwnPropertyDescriptorImpl, "    const ${namespaceMaybe}HashEntry* entry = ${className}Table.entry(exec, propertyName);\n");
     369            push(@getOwnPropertyDescriptorImpl, "    if (entry) {\n");
     370            push(@getOwnPropertyDescriptorImpl, "        PropertySlot slot;\n");
     371            push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, entry->propertyGetter());\n");
     372            push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());\n");
     373            push(@getOwnPropertyDescriptorImpl, "        return true;\n");
     374            push(@getOwnPropertyDescriptorImpl, "    }\n");
     375        }
     376    };
     377   
     378    if (!$dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
     379        &$manualLookupGetterGeneration();
     380    }
     381   
     382    if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
     383        push(@getOwnPropertyDescriptorImpl, "    bool ok;\n");
     384        push(@getOwnPropertyDescriptorImpl, "    unsigned index = propertyName.toUInt32(&ok, false);\n");
     385        push(@getOwnPropertyDescriptorImpl, "    if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
     386        if ($dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
     387            # Assume that if there's a setter, the index will be writable
     388            if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
     389                push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete);\n");
     390            } else {
     391                push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(getByIndex(exec, index), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
     392            }
     393        } else {
     394            push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");
     395            push(@getOwnPropertyDescriptorImpl, "        slot.setCustomIndex(this, index, indexGetter);\n");
     396            # Assume that if there's a setter, the index will be writable
     397            if ($dataNode->extendedAttributes->{"HasIndexSetter"} || $dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
     398                push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete);\n");
     399            } else {
     400                push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ${namespaceMaybe}DontDelete | ${namespaceMaybe}ReadOnly);\n");
     401            }
     402        }
     403        push(@getOwnPropertyDescriptorImpl, "        return true;\n");
     404        push(@getOwnPropertyDescriptorImpl, "    }\n");
     405    }
     406   
     407    if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
     408        push(@getOwnPropertyDescriptorImpl, "    if (canGetItemsForName(exec, static_cast<$implClassName*>(impl()), propertyName)) {\n");
     409        push(@getOwnPropertyDescriptorImpl, "        ${namespaceMaybe}PropertySlot slot;\n");
     410        push(@getOwnPropertyDescriptorImpl, "        slot.setCustom(this, nameGetter);\n");
     411        push(@getOwnPropertyDescriptorImpl, "        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);\n");
     412        push(@getOwnPropertyDescriptorImpl, "        return true;\n");
     413        push(@getOwnPropertyDescriptorImpl, "    }\n");
     414        if ($inlined) {
     415            $headerIncludes{"AtomicString.h"} = 1;
     416        } else {
     417            $implIncludes{"AtomicString.h"} = 1;
     418        }
     419    }
     420   
     421    if ($dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
     422        &$manualLookupGetterGeneration();
     423    }
     424   
     425    if ($dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"}) {
     426        push(@getOwnPropertyDescriptorImpl, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
     427        push(@getOwnPropertyDescriptorImpl, "        return true;\n");
     428    }
     429   
     430    if ($hasAttributes) {
     431        if ($inlined) {
     432            die "Cannot inline if NoStaticTables is set." if ($dataNode->extendedAttributes->{"NoStaticTables"});
     433            push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, s_info.staticPropHashTable, this, propertyName, descriptor);\n");
     434        } else {
     435            push(@getOwnPropertyDescriptorImpl, "    return ${namespaceMaybe}getStaticValueDescriptor<$className, Base>(exec, " . hashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
     436        }
     437    } else {
     438        push(@getOwnPropertyDescriptorImpl, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");
     439    }
     440   
     441    return @getOwnPropertyDescriptorImpl;
     442}
     443
    351444sub GenerateHeader
    352445{
     
    461554    if ($hasGetter) {
    462555        push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&);\n");
     556        push(@headerContent, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);\n");
    463557        push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\n") if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) && !$dataNode->extendedAttributes->{"HasOverridingNameGetter"};
    464558        push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
     559        push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingGetOwnPropertySlot"};
    465560    }
    466561
     
    622717        push(@headerContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
    623718        push(@headerContent, "}\n\n");
     719        push(@headerContent, "ALWAYS_INLINE bool ${className}::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor)\n");
     720        push(@headerContent, "{\n");
     721        push(@headerContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 1));
     722        push(@headerContent, "}\n\n");
    624723    }
    625724
     
    663762    if ($numFunctions > 0 || $numConstants > 0 || $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
    664763        push(@headerContent, "    virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n");
     764        push(@headerContent, "    virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n");
    665765        push(@headerContent, "    bool getOwnPropertySlotDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertySlot&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};
     766        push(@headerContent, "    bool getOwnPropertyDescriptorDelegate(JSC::ExecState*, const JSC::Identifier&, JSC::PropertyDescriptor&);\n") if $dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"};
    666767
    667768        push(@headerContent,
     
    9381039        } else {
    9391040            push(@implContent, "    return getStaticPropertySlot<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, slot);\n");
     1041        }
     1042        push(@implContent, "}\n\n");
     1043
     1044        push(@implContent, "bool ${className}Prototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
     1045        push(@implContent, "{\n");
     1046       
     1047        if ($dataNode->extendedAttributes->{"DelegatingPrototypeGetOwnPropertySlot"}) {
     1048            push(@implContent, "    if (getOwnPropertyDescriptorDelegate(exec, propertyName, descriptor))\n");
     1049            push(@implContent, "        return true;\n");
     1050        }
     1051       
     1052        if ($numConstants eq 0 && $numFunctions eq 0) {
     1053            push(@implContent, "    return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor);\n");       
     1054        } elsif ($numConstants eq 0) {
     1055            push(@implContent, "    return getStaticFunctionDescriptor<JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
     1056        } elsif ($numFunctions eq 0) {
     1057            push(@implContent, "    return getStaticValueDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
     1058        } else {
     1059            push(@implContent, "    return getStaticPropertyDescriptor<${className}Prototype, JSObject>(exec, " . prototypeHashTableAccessor($dataNode->extendedAttributes->{"NoStaticTables"}, $className) . ", this, propertyName, descriptor);\n");
    9401060        }
    9411061        push(@implContent, "}\n\n");
     
    10671187            push(@implContent, "{\n");
    10681188            push(@implContent, GenerateGetOwnPropertySlotBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
     1189            push(@implContent, "}\n\n");
     1190            push(@implContent, "bool ${className}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)\n");
     1191            push(@implContent, "{\n");
     1192            push(@implContent, GenerateGetOwnPropertyDescriptorBody($dataNode, $interfaceName, $className, $implClassName, $numAttributes > 0, 0));
    10691193            push(@implContent, "}\n\n");
    10701194        }
     
    20482172    }
    20492173    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     2174    virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    20502175    virtual const ClassInfo* classInfo() const { return &s_info; }
    20512176    static const ClassInfo s_info;
     
    20812206}
    20822207
     2208bool ${constructorClassName}::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     2209{
     2210    return getStaticValueDescriptor<${constructorClassName}, DOMObject>(exec, &${constructorClassName}Table, this, propertyName, descriptor);
     2211}
     2212
    20832213EOF
    20842214
  • trunk/WebCore/bridge/objc/objc_runtime.h

    r43122 r47780  
    110110private:
    111111    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     112    virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    112113    virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    113114    virtual CallType getCallData(CallData&);
  • trunk/WebCore/bridge/objc/objc_runtime.mm

    r47288 r47780  
    204204}
    205205
     206bool ObjcFallbackObjectImp::getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor& descriptor)
     207{
     208    // keep the prototype from getting called instead of just returning false
     209    descriptor.setUndefined();
     210    return true;
     211}
     212
    206213void ObjcFallbackObjectImp::put(ExecState*, const Identifier&, JSValue, PutPropertySlot&)
    207214{
  • trunk/WebCore/bridge/runtime.h

    r45891 r47780  
    112112
    113113    virtual bool getOwnPropertySlot(JSObject*, ExecState*, const Identifier&, PropertySlot&) { return false; }
     114    virtual bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&) { return false; }
    114115    virtual void put(JSObject*, ExecState*, const Identifier&, JSValue, PutPropertySlot&) { }
    115116
  • trunk/WebCore/bridge/runtime_array.cpp

    r45724 r47780  
    7676}
    7777
     78bool RuntimeArray::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     79{
     80    if (propertyName == exec->propertyNames().length) {
     81        PropertySlot slot;
     82        slot.setCustom(this, lengthGetter);
     83        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
     84        return true;
     85    }
     86   
     87    bool ok;
     88    unsigned index = propertyName.toArrayIndex(&ok);
     89    if (ok) {
     90        if (index < getLength()) {
     91            PropertySlot slot;
     92            slot.setCustomIndex(this, index, indexGetter);
     93            descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | DontEnum);
     94            return true;
     95        }
     96    }
     97   
     98    return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     99}
     100
    78101bool RuntimeArray::getOwnPropertySlot(ExecState *exec, unsigned index, PropertySlot& slot)
    79102{
  • trunk/WebCore/bridge/runtime_array.h

    r43122 r47780  
    3838    virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
    3939    virtual bool getOwnPropertySlot(ExecState *, unsigned, PropertySlot&);
     40    virtual bool getOwnPropertyDescriptor(ExecState *, const Identifier&, PropertyDescriptor&);
    4041    virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    4142    virtual void put(ExecState*, unsigned propertyName, JSValue);
  • trunk/WebCore/bridge/runtime_method.cpp

    r47288 r47780  
    7474}
    7575
     76bool RuntimeMethod::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor &descriptor)
     77{
     78    if (propertyName == exec->propertyNames().length) {
     79        PropertySlot slot;
     80        slot.setCustom(this, lengthGetter);
     81        descriptor.setDescriptor(slot.getValue(exec, propertyName), ReadOnly | DontDelete | DontEnum);
     82        return true;
     83    }
     84   
     85    return InternalFunction::getOwnPropertyDescriptor(exec, propertyName, descriptor);
     86}
     87
    7688static JSValue JSC_HOST_CALL callRuntimeMethod(ExecState* exec, JSObject* function, JSValue thisValue, const ArgList& args)
    7789{
  • trunk/WebCore/bridge/runtime_method.h

    r43122 r47780  
    5454    static JSValue lengthGetter(ExecState*, const Identifier&, const PropertySlot&);
    5555    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
     56    virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
    5657    virtual CallType getCallData(CallData&);
    5758
  • trunk/WebCore/bridge/runtime_object.cpp

    r45724 r47780  
    168168}
    169169
     170bool RuntimeObjectImp::getOwnPropertyDescriptor(ExecState *exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
     171{
     172    if (!instance) {
     173        throwInvalidAccessError(exec);
     174        return false;
     175    }
     176   
     177    instance->begin();
     178   
     179    Class *aClass = instance->getClass();
     180   
     181    if (aClass) {
     182        // See if the instance has a field with the specified name.
     183        Field *aField = aClass->fieldNamed(propertyName, instance.get());
     184        if (aField) {
     185            PropertySlot slot;
     186            slot.setCustom(this, fieldGetter);
     187            instance->end();
     188            descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete);
     189            return true;
     190        } else {
     191            // Now check if a method with specified name exists, if so return a function object for
     192            // that method.
     193            MethodList methodList = aClass->methodsNamed(propertyName, instance.get());
     194            if (methodList.size() > 0) {
     195                PropertySlot slot;
     196                slot.setCustom(this, methodGetter);
     197                instance->end();
     198                descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly);
     199                return true;
     200            }
     201        }
     202       
     203        // Try a fallback object.
     204        if (!aClass->fallbackObject(exec, instance.get(), propertyName).isUndefined()) {
     205            PropertySlot slot;
     206            slot.setCustom(this, fallbackObjectGetter);
     207            instance->end();
     208            descriptor.setDescriptor(slot.getValue(exec, propertyName), DontDelete | ReadOnly | DontEnum);
     209            return true;
     210        }
     211    }
     212   
     213    instance->end();
     214   
     215    return instance->getOwnPropertyDescriptor(this, exec, propertyName, descriptor);
     216}
     217
    170218void RuntimeObjectImp::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
    171219{
  • trunk/WebCore/bridge/runtime_object.h

    r43122 r47780  
    3939
    4040    virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
     41    virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&);
    4142    virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
    4243    virtual bool deleteProperty(ExecState* , const Identifier& propertyName);
Note: See TracChangeset for help on using the changeset viewer.