Unzip initialization lists and constructors in JSCell hierarchy (5/7)
[WebKit-https.git] / Source / WebCore / bindings / js / JSDOMBinding.h
index ee541a2..c1c837e 100644 (file)
 #include "JSDOMWrapper.h"
 #include "DOMWrapperWorld.h"
 #include "Document.h"
-#include <runtime/Completion.h>
+#include "Element.h"
+#include "StyleBase.h"
+#include <heap/Weak.h>
+#include <runtime/FunctionPrototype.h>
 #include <runtime/Lookup.h>
+#include <runtime/ObjectPrototype.h>
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
 
-namespace JSC {
-    class JSGlobalData;
-    class DebuggerCallFrame;
-}
-
 namespace WebCore {
 
-    class Document;
     class Frame;
-    class JSNode;
     class KURL;
-    class Node;
-    class ScriptController;
-    class ScriptCachedFrameData;
 
     typedef int ExceptionCode;
 
-    // FIXME: This class should collapse into DOMObject once all DOMObjects are
-    // updated to store a globalObject pointer.
-    class DOMObjectWithGlobalPointer : public DOMObject {
-    public:
-        JSDOMGlobalObject* globalObject() const
-        {
-            return static_cast<JSDOMGlobalObject*>(DOMObject::globalObject());
-        }
-
-        ScriptExecutionContext* scriptExecutionContext() const
-        {
-            // FIXME: Should never be 0, but can be due to bug 27640.
-            return globalObject()->scriptExecutionContext();
-        }
-
-        static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
-        {
-            return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
-        }
-
-    protected:
-        DOMObjectWithGlobalPointer(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
-            : DOMObject(globalObject, structure)
-        {
-            // FIXME: This ASSERT is valid, but fires in fast/dom/gc-6.html when trying to create
-            // new JavaScript objects on detached windows due to DOMWindow::document()
-            // needing to reach through the frame to get to the Document*.  See bug 27640.
-            // ASSERT(globalObject->scriptExecutionContext());
-        }
-    };
-
     // Base class for all constructor objects in the JSC bindings.
-    class DOMConstructorObject : public DOMObjectWithGlobalPointer {
+    class DOMConstructorObject : public JSDOMWrapper {
     public:
-        static PassRefPtr<JSC::Structure> createStructure(JSC::JSGlobalData& globalData, JSC::JSValue prototype)
+        static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
         {
-            return JSC::Structure::create(globalData, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
+            return JSC::Structure::create(globalData, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
         }
 
     protected:
-        static const unsigned StructureFlags = JSC::ImplementsHasInstance | JSC::OverridesMarkChildren | DOMObjectWithGlobalPointer::StructureFlags;
-        DOMConstructorObject(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
-            : DOMObjectWithGlobalPointer(structure, globalObject)
+        static const unsigned StructureFlags = JSC::ImplementsHasInstance | JSC::OverridesVisitChildren | JSDOMWrapper::StructureFlags;
+        DOMConstructorObject(JSC::Structure* structure, JSDOMGlobalObject* globalObject)
+            : JSDOMWrapper(structure, globalObject)
         {
+            finishCreation(globalObject->globalData());
         }
     };
 
@@ -105,26 +69,15 @@ namespace WebCore {
         }
 
     protected:
-        DOMConstructorWithDocument(NonNullPassRefPtr<JSC::Structure> structure, JSDOMGlobalObject* globalObject)
+        DOMConstructorWithDocument(JSC::Structure* structure, JSDOMGlobalObject* globalObject)
             : DOMConstructorObject(structure, globalObject)
         {
             ASSERT(globalObject->scriptExecutionContext()->isDocument());
         }
     };
-
-    DOMObject* getCachedDOMObjectWrapper(DOMWrapperWorld*, void* objectHandle);
-    void cacheDOMObjectWrapper(DOMWrapperWorld*, void* objectHandle, DOMObject* wrapper);
-    void uncacheDOMObjectWrapper(DOMWrapperWorld*, void* objectHandle, DOMObject* wrapper);
-
-    JSNode* getCachedDOMNodeWrapper(DOMWrapperWorld*, Node*);
-    void cacheDOMNodeWrapper(DOMWrapperWorld*, Node*, JSNode* wrapper);
-    void uncacheDOMNodeWrapper(DOMWrapperWorld*, Node*, JSNode* wrapper);
     
-    void markActiveObjectsForContext(JSC::MarkStack&, JSC::JSGlobalData&, ScriptExecutionContext*);
-    void markDOMObjectWrapper(JSC::MarkStack&, JSC::JSGlobalData& globalData, void* object);
-
     JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*);
-    JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, NonNullPassRefPtr<JSC::Structure>, const JSC::ClassInfo*);
+    JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, JSC::Structure*, const JSC::ClassInfo*);
 
     inline JSDOMGlobalObject* deprecatedGlobalObjectForPrototype(JSC::ExecState* exec)
     {
@@ -138,54 +91,91 @@ namespace WebCore {
     {
         if (JSC::Structure* structure = getCachedDOMStructure(globalObject, &WrapperClass::s_info))
             return structure;
-        return cacheDOMStructure(globalObject, WrapperClass::createStructure(exec->globalData(), WrapperClass::createPrototype(exec, globalObject)), &WrapperClass::s_info);
+        return cacheDOMStructure(globalObject, WrapperClass::createStructure(exec->globalData(), globalObject, WrapperClass::createPrototype(exec, globalObject)), &WrapperClass::s_info);
     }
+
     template<class WrapperClass> inline JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState* exec)
     {
         // FIXME: This function is wrong.  It uses the wrong global object for creating the prototype structure.
         return getDOMStructure<WrapperClass>(exec, deprecatedGlobalObjectForPrototype(exec));
     }
+
     template<class WrapperClass> inline JSC::JSObject* getDOMPrototype(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject)
     {
         return static_cast<JSC::JSObject*>(asObject(getDOMStructure<WrapperClass>(exec, static_cast<JSDOMGlobalObject*>(globalObject))->storedPrototype()));
     }
-    #define CREATE_DOM_OBJECT_WRAPPER(exec, globalObject, className, object) createDOMObjectWrapper<JS##className>(exec, globalObject, static_cast<className*>(object))
-    template<class WrapperClass, class DOMClass> inline DOMObject* createDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object)
+
+    // Overload these functions to provide a fast path for wrapper access.
+    inline JSDOMWrapper* getInlineCachedWrapper(DOMWrapperWorld*, void*) { return 0; }
+    inline bool setInlineCachedWrapper(DOMWrapperWorld*, void*, JSDOMWrapper*) { return false; }
+    inline bool clearInlineCachedWrapper(DOMWrapperWorld*, void*, JSDOMWrapper*) { return false; }
+
+    // Overload these functions to provide a custom WeakHandleOwner.
+    inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld* world, void*) { return world->defaultWrapperOwner(); }
+    inline void* wrapperContext(DOMWrapperWorld*, void* domObject) { return domObject; }
+
+    template <typename DOMClass> inline JSDOMWrapper* getCachedWrapper(DOMWrapperWorld* world, DOMClass* domObject)
     {
-        ASSERT(object);
-        ASSERT(!getCachedDOMObjectWrapper(currentWorld(exec), object));
-        // FIXME: new (exec) could use a different globalData than the globalData this wrapper is cached on.
-        WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, object);
-        cacheDOMObjectWrapper(currentWorld(exec), object, wrapper);
-        return wrapper;
+        if (JSDOMWrapper* wrapper = getInlineCachedWrapper(world, domObject))
+            return wrapper;
+        return world->m_wrappers.get(domObject).get();
     }
-    template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMObjectWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* object)
+
+    template <typename DOMClass> inline void cacheWrapper(DOMWrapperWorld* world, DOMClass* domObject, JSDOMWrapper* wrapper)
     {
-        if (!object)
-            return JSC::jsNull();
-        if (DOMObject* wrapper = getCachedDOMObjectWrapper(currentWorld(exec), object))
-            return wrapper;
-        return createDOMObjectWrapper<WrapperClass>(exec, globalObject, object);
+        if (setInlineCachedWrapper(world, domObject, wrapper))
+            return;
+        ASSERT(!world->m_wrappers.contains(domObject));
+        world->m_wrappers.set(domObject, JSC::Weak<JSDOMWrapper>(*world->globalData(), wrapper, wrapperOwner(world, domObject), wrapperContext(world, domObject)));
     }
 
-    #define CREATE_DOM_NODE_WRAPPER(exec, globalObject, className, object) createDOMNodeWrapper<JS##className>(exec, globalObject, static_cast<className*>(object))
-    template<class WrapperClass, class DOMClass> inline JSNode* createDOMNodeWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node)
+    template <typename DOMClass> inline void uncacheWrapper(DOMWrapperWorld* world, DOMClass* domObject, JSDOMWrapper* wrapper)
+    {
+        if (clearInlineCachedWrapper(world, domObject, wrapper))
+            return;
+        ASSERT(world->m_wrappers.find(domObject)->second.get() == wrapper);
+        world->m_wrappers.remove(domObject);
+    }
+    
+    #define CREATE_DOM_WRAPPER(exec, globalObject, className, object) createWrapper<JS##className>(exec, globalObject, static_cast<className*>(object))
+    template<class WrapperClass, class DOMClass> inline JSDOMWrapper* createWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node)
     {
         ASSERT(node);
-        ASSERT(!getCachedDOMNodeWrapper(currentWorld(exec), node));
-        WrapperClass* wrapper = new (exec) WrapperClass(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, node);
+        ASSERT(!getCachedWrapper(currentWorld(exec), node));
+        WrapperClass* wrapper = WrapperClass::create(getDOMStructure<WrapperClass>(exec, globalObject), globalObject, node);
         // FIXME: The entire function can be removed, once we fix caching.
         // This function is a one-off hack to make Nodes cache in the right global object.
-        cacheDOMNodeWrapper(currentWorld(exec), node, wrapper);
+        cacheWrapper(currentWorld(exec), node, wrapper);
         return wrapper;
     }
-    template<class WrapperClass, class DOMClass> inline JSC::JSValue getDOMNodeWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node)
+
+    template<class WrapperClass, class DOMClass> inline JSC::JSValue wrap(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* domObject)
     {
-        if (!node)
+        if (!domObject)
             return JSC::jsNull();
-        if (JSC::JSCell* wrapper = getCachedDOMNodeWrapper(currentWorld(exec), node))
+        if (JSDOMWrapper* wrapper = getCachedWrapper(currentWorld(exec), domObject))
             return wrapper;
-        return createDOMNodeWrapper<WrapperClass>(exec, globalObject, node);
+        return createWrapper<WrapperClass>(exec, globalObject, domObject);
+    }
+
+    inline void* root(Node* node)
+    {
+        if (node->inDocument())
+            return node->document();
+
+        while (node->parentOrHostNode())
+            node = node->parentOrHostNode();
+        return node;
+    }
+
+    inline void* root(StyleBase* styleBase)
+    {
+        while (styleBase->parent())
+            styleBase = styleBase->parent();
+
+        if (Node* node = styleBase->node())
+            return root(node);
+        return styleBase;
     }
 
     const JSC::HashTable* getHashTableForGlobalData(JSC::JSGlobalData&, const JSC::HashTable* staticTable);
@@ -240,23 +230,6 @@ namespace WebCore {
     // NaN if the value can't be converted to a date.
     double valueToDate(JSC::ExecState*, JSC::JSValue);
 
-    // FIXME: These are a stop-gap until all toJS calls can be converted to pass a globalObject
-    template <typename T>
-    inline JSC::JSValue toJS(JSC::ExecState* exec, T* ptr)
-    {
-        return toJS(exec, deprecatedGlobalObjectForPrototype(exec), ptr);
-    }
-    template <typename T>
-    inline JSC::JSValue toJS(JSC::ExecState* exec, PassRefPtr<T> ptr)
-    {
-        return toJS(exec, deprecatedGlobalObjectForPrototype(exec), ptr.get());
-    }
-    template <typename T>
-    inline JSC::JSValue toJSNewlyCreated(JSC::ExecState* exec, T* ptr)
-    {
-        return toJSNewlyCreated(exec, deprecatedGlobalObjectForPrototype(exec), ptr);
-    }
-
     template <typename T>
     inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<T> ptr)
     {
@@ -281,8 +254,7 @@ namespace WebCore {
     JSC::JSValue objectToStringFunctionGetter(JSC::ExecState*, JSC::JSValue, const JSC::Identifier& propertyName);
 
     Frame* toDynamicFrame(JSC::ExecState*);
-    bool processingUserGesture();
-    
+
     inline JSC::JSValue jsString(JSC::ExecState* exec, const String& s)
     {
         StringImpl* stringImpl = s.impl();
@@ -293,8 +265,9 @@ namespace WebCore {
             return jsString(exec, stringToUString(s));
 
         JSStringCache& stringCache = currentWorld(exec)->m_stringCache;
-        if (JSC::JSString* wrapper = stringCache.get(stringImpl))
-            return wrapper;
+        JSStringCache::iterator it = stringCache.find(stringImpl);
+        if (it != stringCache.end())
+            return it->second.get();
 
         return jsStringSlowCase(exec, stringCache, stringImpl);
     }