Ignore:
Timestamp:
Oct 14, 2011, 6:25:53 PM (14 years ago)
Author:
[email protected]
Message:

Most built-in properties are not deletable
https://bugs.webkit.org/show_bug.cgi?id=61014

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Our static hash tables don't allow for deleting properties.
This is the cause of a bunch of expected failures in LayoutTests/sputnik.

This fixes the problem by reifying all static functions immediately prior
to the first deletion. Reification is tracked by a flag on the structure,
so properties will no longer 'bounce-back' on later access.

Theoretically there could probably also be an issue with custom accessor
properties, but we probably do not really require any of these to be
Configurable anyway. I'll follow up with a separate patch to address this.

  • runtime/ClassInfo.h:

(JSC::ClassInfo::hasStaticProperties):

  • detects static property tables.
  • runtime/JSObject.cpp:

(JSC::JSObject::deleteProperty):

  • call reifyStaticFunctions before deletion.

(JSC::JSObject::reifyStaticFunctions):

  • If the class has static functions, set them up now.
  • runtime/JSObject.h:

(JSC::JSObject::staticFunctionsReified):

  • returns true if static functions have been reified, and as such should no longer be added.
  • runtime/Lookup.cpp:

(JSC::setUpStaticFunctionSlot):

  • If static functions have been reified do not add.
  • runtime/Lookup.h:

(JSC::HashTable::ConstIterator::ConstIterator):
(JSC::HashTable::ConstIterator::operator->):
(JSC::HashTable::ConstIterator::operator*):
(JSC::HashTable::ConstIterator::operator!=):
(JSC::HashTable::ConstIterator::operator++):
(JSC::HashTable::ConstIterator::skipInvalidKeys):
(JSC::HashTable::begin):
(JSC::HashTable::end):
(JSC::getStaticPropertySlot):
(JSC::getStaticPropertyDescriptor):
(JSC::getStaticFunctionSlot):
(JSC::getStaticFunctionDescriptor):

  • setUpStaticFunctionSlot may not add, returns a bool.

(JSC::lookupPut):

  • remove redundant branch.
  • runtime/Structure.cpp:

(JSC::Structure::Structure):

  • initialize new flag in constructors.
  • runtime/Structure.h:

(JSC::Structure::staticFunctionsReified):
(JSC::Structure::setStaticFunctionsReified):

  • added flag

LayoutTests:

Mostly checking in passing results, added a couple of extra test cases to fast/js/delete-syntax.

  • fast/js/delete-syntax-expected.txt:
  • fast/js/script-tests/delete-syntax.js:
  • ietestcenter/Javascript/11.4.1-4.a-10-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.4_Array/15.4.4/S15.4.4_A1.1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/S15.5.4.1_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/S15.5.4_A1-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.5_String/15.5.4/S15.5.4_A3-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.6_Boolean/15.6.2/S15.6.2.1_A4-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.6_Boolean/15.6.3/15.6.3.1_Boolean.prototype/S15.6.3.1_A1-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.6_Boolean/15.6.4/S15.6.4_A1-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.7_Number/15.7.2/S15.7.2.1_A4-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.7_Number/15.7.3/15.7.3.1_Number.prototype/S15.7.3.1_A2_T1-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.7_Number/15.7.4/S15.7.4_A1-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.4/15.9.4.2_Date.parse/S15.9.4.2_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.4/15.9.4.3_Date.UTC/S15.9.4.3_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.10_Date.prototype.getFullYear/S15.9.5.10_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.11_Date.prototype.getUTCFullYear/S15.9.5.11_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.12_Date.prototype.getMonth/S15.9.5.12_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.13_Date.prototype.getUTCMonth/S15.9.5.13_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.14_Date.prototype.getDate/S15.9.5.14_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.15_Date.prototype.getUTCDate/S15.9.5.15_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.16_Date.prototype.getDay/S15.9.5.16_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.17_Date.prototype.getUTCDay/S15.9.5.17_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.18_Date.prototype.getHours/S15.9.5.18_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.19_Date.prototype.getUTCHours/S15.9.5.19_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.20_Date.prototype.getMinutes/S15.9.5.20_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.21_Date.prototype.getUTCMinutes/S15.9.5.21_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.22_Date.prototype.getSeconds/S15.9.5.22_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.23_Date.prototype.getUTCSeconds/S15.9.5.23_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.24_Date.prototype.getMilliseconds/S15.9.5.24_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.25_Date.prototype.getUTCMilliseconds/S15.9.5.25_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.26_Date.prototype.getTimezoneOffset/S15.9.5.26_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.27_Date.prototype.setTime/S15.9.5.27_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.28_Date.prototype.setMilliseconds/S15.9.5.28_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.29_Date.prototype.setUTCMilliseconds/S15.9.5.29_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.2_Date.prototype.toString/S15.9.5.2_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.30_Date.prototype.setSeconds/S15.9.5.30_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.31_Date.prototype.setUTCSeconds/S15.9.5.31_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.32_Date.prototype.setMinutes/S15.9.5.32_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.33_Date.prototype.setUTCMinutes/S15.9.5.33_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.34_Date.prototype.setHours/S15.9.5.34_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.35_Date.prototype.setUTCHours/S15.9.5.35_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.36_Date.prototype.setDate/S15.9.5.36_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.37_Date.prototype.setUTCDate/S15.9.5.37_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.38_Date.prototype.setMonth/S15.9.5.38_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.39_Date.prototype.setUTCMonth/S15.9.5.39_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.3_Date.prototype.toDateString/S15.9.5.3_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.40_Date.prototype.setFullYear/S15.9.5.40_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.41_Date.prototype.setUTCFullYear/S15.9.5.41_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.42_Date.prototype.toUTCString/S15.9.5.42_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.4_Date.prototype.toTimeString/S15.9.5.4_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.5_Date.prototype.toLocaleString/S15.9.5.5_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.6_Date.prototype.toLocaleDateString/S15.9.5.6_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.7_Date.prototype.toLocaleTimeString/S15.9.5.7_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.8_Date.prototype.valueOf/S15.9.5.8_A1_T2-expected.txt:
  • sputnik/Conformance/15_Native_Objects/15.9_Date/15.9.5/15.9.5.9_Date.prototype.getTime/S15.9.5.9_A1_T2-expected.txt:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/Lookup.h

    r97532 r97536  
    177177        }
    178178
     179        class ConstIterator {
     180        public:
     181            ConstIterator(const HashTable* table, int position)
     182                : m_table(table)
     183                , m_position(position)
     184            {
     185                skipInvalidKeys();
     186            }
     187
     188            const HashEntry* operator->()
     189            {
     190                return &m_table->table[m_position];
     191            }
     192
     193            const HashEntry* operator*()
     194            {
     195                return &m_table->table[m_position];
     196            }
     197
     198            bool operator!=(const ConstIterator& other)
     199            {
     200                ASSERT(m_table == other.m_table);
     201                return m_position != other.m_position;
     202            }
     203           
     204            ConstIterator& operator++()
     205            {
     206                ASSERT(m_position < m_table->compactSize);
     207                ++m_position;
     208                skipInvalidKeys();
     209                return *this;
     210            }
     211
     212        private:
     213            void skipInvalidKeys()
     214            {
     215                ASSERT(m_position <= m_table->compactSize);
     216                while (m_position < m_table->compactSize && !m_table->table[m_position].key())
     217                    ++m_position;
     218                ASSERT(m_position <= m_table->compactSize);
     219            }
     220           
     221            const HashTable* m_table;
     222            int m_position;
     223        };
     224
     225        ConstIterator begin(JSGlobalData& globalData) const
     226        {
     227            initializeIfNeeded(&globalData);
     228            return ConstIterator(this, 0);
     229        }
     230        ConstIterator end(JSGlobalData& globalData) const
     231        {
     232            initializeIfNeeded(&globalData);
     233            return ConstIterator(this, compactSize);
     234        }
     235
    179236    private:
    180237        ALWAYS_INLINE const HashEntry* entry(const Identifier& identifier) const
     
    200257    };
    201258
    202     void setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&);
     259    bool setUpStaticFunctionSlot(ExecState*, const HashEntry*, JSObject* thisObject, const Identifier& propertyName, PropertySlot&);
    203260
    204261    /**
     
    217274
    218275        if (entry->attributes() & Function)
    219             setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
    220         else
    221             slot.setCacheableCustom(thisObj, entry->propertyGetter());
    222 
     276            return setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
     277
     278        slot.setCacheableCustom(thisObj, entry->propertyGetter());
    223279        return true;
    224280    }
     
    233289 
    234290        PropertySlot slot;
    235         if (entry->attributes() & Function)
    236             setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
    237         else
    238             slot.setCustom(thisObj, entry->propertyGetter());
    239 
     291        if (entry->attributes() & Function) {
     292            bool present = setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
     293            if (present)
     294                descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     295            return present;
     296        }
     297
     298        slot.setCustom(thisObj, entry->propertyGetter());
    240299        descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
    241300        return true;
     
    257316            return false;
    258317
    259         setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
    260         return true;
     318        return setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
    261319    }
    262320   
     
    277335       
    278336        PropertySlot slot;
    279         setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
    280         descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
    281         return true;
     337        bool present = setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
     338        if (present)
     339            descriptor.setDescriptor(slot.getValue(exec, propertyName), entry->attributes());
     340        return present;
    282341    }
    283342
     
    332391            return false;
    333392
    334         if (entry->attributes() & Function) { // function: put as override property
    335             if (LIKELY(value.isCell()))
    336                 thisObj->putDirect(exec->globalData(), propertyName, value.asCell());
    337             else
    338                 thisObj->putDirect(exec->globalData(), propertyName, value);
    339         } else if (!(entry->attributes() & ReadOnly))
     393        // If this is a function put it as an override property.
     394        if (entry->attributes() & Function)
     395            thisObj->putDirect(exec->globalData(), propertyName, value);
     396        else if (!(entry->attributes() & ReadOnly))
    340397            entry->propertyPutter()(exec, thisObj, value);
    341398
Note: See TracChangeset for help on using the changeset viewer.