Bug 55736 - Implement seal/freeze/preventExtensions for normal object types.
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSObject.h
index 5ccef8e..2b4db43 100644 (file)
@@ -210,6 +210,13 @@ namespace JSC {
         virtual bool isStrictModeFunction() const { return false; }
         virtual bool isErrorInstance() const { return false; }
 
+        void seal();
+        void freeze();
+        void preventExtensions();
+        bool isSealed() { return m_structure->isSealed(); }
+        bool isFrozen() { return m_structure->isFrozen(); }
+        bool isExtensible() { return m_structure->isExtensible(); }
+
         virtual ComplType exceptionType() const { return Throw; }
 
         void allocatePropertyStorage(size_t oldSize, size_t newSize);
@@ -240,7 +247,7 @@ namespace JSC {
 
         static size_t offsetOfInlineStorage();
         
-        static const ClassInfo s_info;
+        static JS_EXPORTDATA const ClassInfo s_info;
 
     protected:
         static PassRefPtr<Structure> createStructure(JSValue prototype)
@@ -323,6 +330,7 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt
             : JSObject(structure, m_inlineStorage)
         {
             ASSERT(!(OBJECT_OFFSETOF(JSNonFinalObject, m_inlineStorage) % sizeof(double)));
+            ASSERT(this->structure()->propertyStorageCapacity() == JSNonFinalObject_inlineStorageCapacity);
         }
 
     private:
@@ -350,6 +358,7 @@ COMPILE_ASSERT((JSFinalObject_inlineStorageCapacity >= JSNonFinalObject_inlineSt
             : JSObject(structure, m_inlineStorage)
         {
             ASSERT(OBJECT_OFFSETOF(JSFinalObject, m_inlineStorage) % sizeof(double) == 0);
+            ASSERT(this->structure()->propertyStorageCapacity() == JSFinalObject_inlineStorageCapacity);
         }
 
         static const unsigned StructureFlags = JSObject::StructureFlags | IsJSFinalObject;
@@ -388,6 +397,7 @@ inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure, PropertyStorag
     : JSCell(structure.releaseRef()) // ~JSObject balances this ref()
     , m_propertyStorage(inlineStorage)
 {
+    ASSERT(inherits(&s_info));
     ASSERT(m_structure->propertyStorageCapacity() < baseExternalStorageCapacity);
     ASSERT(m_structure->isEmpty());
     ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype()));
@@ -568,6 +578,9 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
             return true;
         }
 
+        if (!isExtensible())
+            return false;
+
         size_t currentCapacity = m_structure->propertyStorageCapacity();
         offset = m_structure->addPropertyWithoutTransition(propertyName, attributes, specificFunction);
         if (currentCapacity != m_structure->propertyStorageCapacity())
@@ -629,15 +642,8 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi
         return true;
     }
 
-    // If we have a specific function, we may have got to this point if there is
-    // already a transition with the correct property name and attributes, but
-    // specialized to a different function.  In this case we just want to give up
-    // and despecialize the transition.
-    // In this case we clear the value of specificFunction which will result
-    // in us adding a non-specific transition, and any subsequent lookup in
-    // Structure::addPropertyTransitionToExistingStructure will just use that.
-    if (specificFunction && m_structure->hasTransition(propertyName, attributes))
-        specificFunction = 0;
+    if (!isExtensible())
+        return false;
 
     RefPtr<Structure> structure = Structure::addPropertyTransition(m_structure, propertyName, attributes, specificFunction, offset);