Title: [142483] trunk
Revision
142483
Author
jsb...@chromium.org
Date
2013-02-11 09:28:22 -0800 (Mon, 11 Feb 2013)

Log Message

[V8] IndexedDB: Minor GC can collect IDBDatabase wrapper with versionchange handler
https://bugs.webkit.org/show_bug.cgi?id=108670

Reviewed by Kentaro Hara.

Source/WebCore:

Prevent IDBDatabase's wrapper from being GC'd while the database is open if it has
listeners, as those listeners may close the database in response to events.

Also, removed extraneous super-calls from hasPendingActivity() overrides.

Test: storage/indexeddb/database-wrapper.html

* Modules/indexeddb/IDBDatabase.cpp:
(WebCore::IDBDatabase::hasPendingActivity): Implemented.
* Modules/indexeddb/IDBDatabase.h: Declared.
* Modules/indexeddb/IDBRequest.cpp:
(WebCore::IDBRequest::hasPendingActivity): Simplified.
* Modules/indexeddb/IDBTransaction.cpp:
(WebCore::IDBTransaction::hasPendingActivity): Simplified.

LayoutTests:

* storage/indexeddb/database-wrapper-expected.txt: Added.
* storage/indexeddb/database-wrapper.html: Added.
* storage/indexeddb/resources/database-wrapper.js: Added.
(test):
(openDB):
(onUpgradeNeeded):
(openSuccess.get request.onsuccess):
(onVersionChange):
(collectGarbage):
(openAgain):
(onBlocked):
(openAgainSuccess):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (142482 => 142483)


--- trunk/LayoutTests/ChangeLog	2013-02-11 17:17:45 UTC (rev 142482)
+++ trunk/LayoutTests/ChangeLog	2013-02-11 17:28:22 UTC (rev 142483)
@@ -1,3 +1,23 @@
+2013-02-11  Joshua Bell  <jsb...@chromium.org>
+
+        [V8] IndexedDB: Minor GC can collect IDBDatabase wrapper with versionchange handler
+        https://bugs.webkit.org/show_bug.cgi?id=108670
+
+        Reviewed by Kentaro Hara.
+
+        * storage/indexeddb/database-wrapper-expected.txt: Added.
+        * storage/indexeddb/database-wrapper.html: Added.
+        * storage/indexeddb/resources/database-wrapper.js: Added.
+        (test):
+        (openDB):
+        (onUpgradeNeeded):
+        (openSuccess.get request.onsuccess):
+        (onVersionChange):
+        (collectGarbage):
+        (openAgain):
+        (onBlocked):
+        (openAgainSuccess):
+
 2013-02-11  Christophe Dumez  <ch.du...@sisa.samsung.com>
 
         Unreviewed EFL gardening.

Added: trunk/LayoutTests/storage/indexeddb/database-wrapper-expected.txt (0 => 142483)


--- trunk/LayoutTests/storage/indexeddb/database-wrapper-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/database-wrapper-expected.txt	2013-02-11 17:28:22 UTC (rev 142483)
@@ -0,0 +1,38 @@
+Ensure IDBDatabase wrapper isn't prematurely collected.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+dbname = "database-wrapper.html"
+indexedDB.deleteDatabase(dbname)
+
+openDB():
+indexedDB.open(dbname, 1)
+
+onUpgradeNeeded():
+db = event.target.result
+db.createObjectStore('store').createIndex('index', 'keyPath')
+db = null
+
+openSuccess():
+sawVersionChangeEvent = false
+
+collectGarbage():
+self.gc()
+
+openAgain():
+indexedDB.open(dbname, 2)
+
+onVersionChange():
+event.target.close()
+sawVersionChangeEvent = true
+
+onBlocked():
+FIXME: Blocked event shouldn't fire. http://wkbug.com/71130
+
+openAgainSuccess():
+PASS sawVersionChangeEvent is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/storage/indexeddb/database-wrapper.html (0 => 142483)


--- trunk/LayoutTests/storage/indexeddb/database-wrapper.html	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/database-wrapper.html	2013-02-11 17:28:22 UTC (rev 142483)
@@ -0,0 +1,10 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Added: trunk/LayoutTests/storage/indexeddb/resources/database-wrapper.js (0 => 142483)


--- trunk/LayoutTests/storage/indexeddb/resources/database-wrapper.js	                        (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/resources/database-wrapper.js	2013-02-11 17:28:22 UTC (rev 142483)
@@ -0,0 +1,90 @@
+if (this.importScripts) {
+    importScripts('../../../fast/js/resources/js-test-pre.js');
+    importScripts('shared.js');
+}
+
+description("Ensure IDBDatabase wrapper isn't prematurely collected.");
+
+test();
+
+function test()
+{
+    setDBNameFromPath();
+    var deleteRequest = evalAndLog("indexedDB.deleteDatabase(dbname)");
+    deleteRequest._onblocked_ = unexpectedBlockedCallback;
+    deleteRequest._onerror_ = unexpectedErrorCallback;
+    deleteRequest._onsuccess_ = openDB;
+}
+
+function openDB()
+{
+    preamble();
+
+    var openRequest = evalAndLog("indexedDB.open(dbname, 1)");
+    openRequest._onblocked_ = unexpectedBlockedCallback;
+    openRequest._onerror_ = unexpectedErrorCallback;
+    openRequest._onupgradeneeded_ = onUpgradeNeeded;
+    openRequest._onsuccess_ = openSuccess;
+}
+
+function onUpgradeNeeded(evt) {
+    preamble(evt);
+    evalAndLog("db = event.target.result");
+    evalAndLog("db.createObjectStore('store').createIndex('index', 'keyPath')");
+    evalAndLog("db = null");
+}
+
+function openSuccess(evt)
+{
+    preamble(evt);
+    var db = event.target.result;
+    db._onversionchange_ = onVersionChange;
+    evalAndLog("sawVersionChangeEvent = false");
+
+    // All these local references should get collected, but the database's
+    // wrapper shouldn't get collected before the database itself.
+    var transaction = db.transaction('store', 'readonly');
+    var objectStore = transaction.objectStore('store');
+    var request = objectStore.get(0);
+    request._onsuccess_ = function() {
+        setTimeout(collectGarbage, 0);
+    };
+}
+
+function onVersionChange(evt)
+{
+    preamble(evt);
+    evalAndLog("event.target.close()");
+    evalAndLog("sawVersionChangeEvent = true");
+}
+
+function collectGarbage()
+{
+    preamble();
+    evalAndLog("self.gc()");
+
+    setTimeout(openAgain, 0);
+}
+
+function openAgain()
+{
+    preamble();
+
+    var openRequest = evalAndLog("indexedDB.open(dbname, 2)");
+    openRequest._onblocked_ = onBlocked;
+    openRequest._onerror_ = unexpectedErrorCallback;
+    openRequest._onsuccess_ = openAgainSuccess;
+}
+
+function onBlocked()
+{
+    preamble();
+    debug("FIXME: Blocked event shouldn't fire. http://wkbug.com/71130");
+}
+
+function openAgainSuccess(evt)
+{
+    preamble(evt);
+    shouldBeTrue("sawVersionChangeEvent");
+    finishJSTest();
+}

Modified: trunk/Source/WebCore/ChangeLog (142482 => 142483)


--- trunk/Source/WebCore/ChangeLog	2013-02-11 17:17:45 UTC (rev 142482)
+++ trunk/Source/WebCore/ChangeLog	2013-02-11 17:28:22 UTC (rev 142483)
@@ -1,3 +1,25 @@
+2013-02-11  Joshua Bell  <jsb...@chromium.org>
+
+        [V8] IndexedDB: Minor GC can collect IDBDatabase wrapper with versionchange handler
+        https://bugs.webkit.org/show_bug.cgi?id=108670
+
+        Reviewed by Kentaro Hara.
+
+        Prevent IDBDatabase's wrapper from being GC'd while the database is open if it has
+        listeners, as those listeners may close the database in response to events.
+
+        Also, removed extraneous super-calls from hasPendingActivity() overrides.
+
+        Test: storage/indexeddb/database-wrapper.html
+
+        * Modules/indexeddb/IDBDatabase.cpp:
+        (WebCore::IDBDatabase::hasPendingActivity): Implemented.
+        * Modules/indexeddb/IDBDatabase.h: Declared.
+        * Modules/indexeddb/IDBRequest.cpp:
+        (WebCore::IDBRequest::hasPendingActivity): Simplified.
+        * Modules/indexeddb/IDBTransaction.cpp:
+        (WebCore::IDBTransaction::hasPendingActivity): Simplified.
+
 2013-02-11  Eric Seidel  <e...@webkit.org>
 
         Remove AttributeBase now that NEW_XML is gone

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp (142482 => 142483)


--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp	2013-02-11 17:17:45 UTC (rev 142482)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.cpp	2013-02-11 17:28:22 UTC (rev 142483)
@@ -354,6 +354,13 @@
     return IDBObjectStoreMetadata::InvalidId;
 }
 
+bool IDBDatabase::hasPendingActivity() const
+{
+    // The script wrapper must not be collected before the object is closed or
+    // we can't fire a "versionchange" event to let script manually close the connection.
+    return !m_closePending && !m_eventTargetData.eventListenerMap.isEmpty();
+}
+
 void IDBDatabase::stop()
 {
     ActiveDOMObject::stop();

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.h (142482 => 142483)


--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.h	2013-02-11 17:17:45 UTC (rev 142482)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabase.h	2013-02-11 17:28:22 UTC (rev 142483)
@@ -82,6 +82,7 @@
     virtual void onComplete(int64_t);
 
     // ActiveDOMObject
+    virtual bool hasPendingActivity() const OVERRIDE;
     virtual void stop() OVERRIDE;
 
     // EventTarget

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp (142482 => 142483)


--- trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp	2013-02-11 17:17:45 UTC (rev 142482)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp	2013-02-11 17:28:22 UTC (rev 142483)
@@ -406,7 +406,7 @@
     // FIXME: In an ideal world, we should return true as long as anyone has a or can
     //        get a handle to us and we have event listeners. This is order to handle
     //        user generated events properly.
-    return m_hasPendingActivity || ActiveDOMObject::hasPendingActivity();
+    return m_hasPendingActivity;
 }
 
 void IDBRequest::stop()

Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp (142482 => 142483)


--- trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp	2013-02-11 17:17:45 UTC (rev 142482)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp	2013-02-11 17:28:22 UTC (rev 142483)
@@ -332,7 +332,7 @@
     // FIXME: In an ideal world, we should return true as long as anyone has a or can
     //        get a handle to us or any child request object and any of those have
     //        event listeners. This is  in order to handle user generated events properly.
-    return m_hasPendingActivity || ActiveDOMObject::hasPendingActivity();
+    return m_hasPendingActivity;
 }
 
 IDBTransaction::Mode IDBTransaction::stringToMode(const String& modeString, ScriptExecutionContext* context, ExceptionCode& ec)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to