Separated a DOMWrapperWorld's behavior of keeping wrappers alive from
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 14 Apr 2010 00:29:03 +0000 (00:29 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 14 Apr 2010 00:29:03 +0000 (00:29 +0000)
its own lifetime, so a DOMWrapperWorld's controller can throw away
its wrappers even before its refcount reaches 0.

Reviewed by Oliver Hunt.

WebCore:

* WebCore.base.exp:
* bindings/js/DOMWrapperWorld.cpp:
(WebCore::DOMWrapperWorld::DOMWrapperWorld):
(WebCore::DOMWrapperWorld::~DOMWrapperWorld):
(WebCore::DOMWrapperWorld::registerWorld):
(WebCore::DOMWrapperWorld::unregisterWorld):
* bindings/js/DOMWrapperWorld.h: Factored out DOMWrapperWorld registration
and unregistration into helper functions, so unregistering could be done manually.

* bindings/js/ScriptController.cpp:
(WebCore::ScriptController::destroyWindowShell): Added an ASSERT to match
similar code.

WebKit/mac:

* WebView/WebScriptWorld.h:
* WebView/WebScriptWorld.mm:
(-[WebScriptWorld unregisterWorld]): Exported this function through WebKit.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@57555 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/WebCore.base.exp
WebCore/bindings/js/DOMWrapperWorld.cpp
WebCore/bindings/js/DOMWrapperWorld.h
WebCore/bindings/js/ScriptController.cpp
WebKit/mac/ChangeLog
WebKit/mac/WebView/WebScriptWorld.h
WebKit/mac/WebView/WebScriptWorld.mm

index 2778f00..e1d02b4 100644 (file)
@@ -1,3 +1,24 @@
+2010-04-13  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Separated a DOMWrapperWorld's behavior of keeping wrappers alive from
+        its own lifetime, so a DOMWrapperWorld's controller can throw away
+        its wrappers even before its refcount reaches 0.
+
+        * WebCore.base.exp:
+        * bindings/js/DOMWrapperWorld.cpp:
+        (WebCore::DOMWrapperWorld::DOMWrapperWorld):
+        (WebCore::DOMWrapperWorld::~DOMWrapperWorld):
+        (WebCore::DOMWrapperWorld::registerWorld):
+        (WebCore::DOMWrapperWorld::unregisterWorld):
+        * bindings/js/DOMWrapperWorld.h: Factored out DOMWrapperWorld registration
+        and unregistration into helper functions, so unregistering could be done manually.
+
+        * bindings/js/ScriptController.cpp:
+        (WebCore::ScriptController::destroyWindowShell): Added an ASSERT to match
+        similar code.
+
 2010-04-13  Chang Shu  <chang.shu@nokia.com>
 
         Reviewed by Darin Fisher.
index ac5e83e..6df22b6 100644 (file)
@@ -342,6 +342,7 @@ __ZN7WebCore15BackForwardList8goToItemEPNS_11HistoryItemE
 __ZN7WebCore15BackForwardList9goForwardEv
 __ZN7WebCore15BackForwardListC1EPNS_4PageE
 __ZN7WebCore15BackForwardListD1Ev
+__ZN7WebCore15DOMWrapperWorld15unregisterWorldEv
 __ZN7WebCore15DOMWrapperWorldD1Ev
 __ZN7WebCore15DatabaseTracker12deleteOriginEPNS_14SecurityOriginE
 __ZN7WebCore15DatabaseTracker14deleteDatabaseEPNS_14SecurityOriginERKNS_6StringE
index 52b1a13..10c3fdd 100644 (file)
@@ -32,18 +32,35 @@ namespace WebCore {
 DOMWrapperWorld::DOMWrapperWorld(JSC::JSGlobalData* globalData, bool isNormal)
     : m_globalData(globalData)
     , m_isNormal(isNormal)
+    , m_isRegistered(false)
+{
+    registerWorld();
+}
+
+DOMWrapperWorld::~DOMWrapperWorld()
+{
+    unregisterWorld();
+}
+
+void DOMWrapperWorld::registerWorld()
 {
     JSGlobalData::ClientData* clientData = m_globalData->clientData;
     ASSERT(clientData);
     static_cast<WebCoreJSClientData*>(clientData)->rememberWorld(this);
+    m_isRegistered = true;
 }
 
-DOMWrapperWorld::~DOMWrapperWorld()
+void DOMWrapperWorld::unregisterWorld()
 {
+    if (!m_isRegistered)
+        return;
+    m_isRegistered = false;
+
     JSGlobalData::ClientData* clientData = m_globalData->clientData;
     ASSERT(clientData);
     static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(this);
 
+    // These items are created lazily.
     while (!m_documentsWithWrapperCaches.isEmpty())
         (*m_documentsWithWrapperCaches.begin())->destroyWrapperCache(this);
 
index 8e98f33..832c5e0 100644 (file)
@@ -42,6 +42,9 @@ public:
         return adoptRef(new DOMWrapperWorld(globalData, isNormal));
     }
     ~DOMWrapperWorld();
+    
+    void registerWorld();
+    void unregisterWorld();
 
     void didCreateWrapperCache(Document* document) { m_documentsWithWrapperCaches.add(document); }
     void didDestroyWrapperCache(Document* document) { m_documentsWithWrapperCaches.remove(document); }
@@ -63,6 +66,7 @@ private:
     HashSet<Document*> m_documentsWithWrapperCaches;
     HashSet<ScriptController*> m_scriptControllersWithWindowShells;
     bool m_isNormal;
+    bool m_isRegistered;
 };
 
 DOMWrapperWorld* normalWorld(JSC::JSGlobalData&);
index bb517da..a14330e 100644 (file)
@@ -93,6 +93,7 @@ ScriptController::~ScriptController()
 
 void ScriptController::destroyWindowShell(DOMWrapperWorld* world)
 {
+    ASSERT(m_windowShells.contains(world));
     m_windowShells.remove(world);
     world->didDestroyWindowShell(this);
 }
index db2fb02..d70085f 100644 (file)
@@ -1,3 +1,15 @@
+2010-04-13  Geoffrey Garen  <ggaren@apple.com>
+
+        Reviewed by Oliver Hunt.
+
+        Separated a DOMWrapperWorld's behavior of keeping wrappers alive from
+        its own lifetime, so a DOMWrapperWorld's controller can throw away
+        its wrappers even before its refcount reaches 0.
+
+        * WebView/WebScriptWorld.h:
+        * WebView/WebScriptWorld.mm:
+        (-[WebScriptWorld unregisterWorld]): Exported this function through WebKit.
+
 2010-04-12  Timothy Hatcher  <timothy@apple.com>
 
         SecurityOrigin needs a way to remove individual OriginAccessEntries
index 7059b76..9a05f7f 100644 (file)
@@ -36,4 +36,6 @@ typedef struct OpaqueJSContext* JSGlobalContextRef;
 
 + (WebScriptWorld *)scriptWorldForGlobalContext:(JSGlobalContextRef)globalContext;
 
+- (void)unregisterWorld;
+
 @end
index 7dab1b3..8ca6f44 100644 (file)
@@ -75,6 +75,11 @@ static WorldMap& allWorlds()
     return [self initWithWorld:ScriptController::createWorld()];
 }
 
+- (void)unregisterWorld
+{
+    _private->world->unregisterWorld();
+}
+
 - (void)dealloc
 {
     ASSERT(allWorlds().contains(_private->world.get()));