Diff
Modified: trunk/LayoutTests/ChangeLog (120221 => 120222)
--- trunk/LayoutTests/ChangeLog 2012-06-13 17:24:59 UTC (rev 120221)
+++ trunk/LayoutTests/ChangeLog 2012-06-13 17:30:52 UTC (rev 120222)
@@ -1,3 +1,28 @@
+2012-06-13 David Grogan <[email protected]>
+
+ IndexedDB: Add tests, an assert, and some comments around open/close/setVersion call sequencing
+ https://bugs.webkit.org/show_bug.cgi?id=88829
+
+ Reviewed by Tony Chang.
+
+ * storage/indexeddb/factory-deletedatabase-interactions-expected.txt:
+ * storage/indexeddb/resources/factory-deletedatabase-interactions.js:
+ (Connection.this.open.req.onsuccess.that.handle.onversionchange):
+ (Connection.this.open.req.onsuccess):
+ (Connection.this.open):
+ (test3):
+ (test4.runSteps.):
+ (test4):
+ (test4.):
+ * storage/indexeddb/resources/three-setversion-calls.js: Added.
+ (test):
+ (openDBConnection):
+ (successHandler.return.trans.oncomplete):
+ (openSuccess1.deleteRequest.onsuccess):
+ (openSuccess1):
+ * storage/indexeddb/three-setversion-calls-expected.txt: Added.
+ * storage/indexeddb/three-setversion-calls.html: Added.
+
2012-06-13 Levi Weintraub <[email protected]>
Unreviewed Chromium test expectation update after r119893.
Modified: trunk/LayoutTests/storage/indexeddb/factory-deletedatabase-interactions-expected.txt (120221 => 120222)
--- trunk/LayoutTests/storage/indexeddb/factory-deletedatabase-interactions-expected.txt 2012-06-13 17:24:59 UTC (rev 120221)
+++ trunk/LayoutTests/storage/indexeddb/factory-deletedatabase-interactions-expected.txt 2012-06-13 17:30:52 UTC (rev 120222)
@@ -12,6 +12,7 @@
'h.open.onsuccess'
'deleteDatabase()'
'h.onversionchange'
+ in versionchange, old = "" new = ""
h closing, but not immediately
'deleteDatabase().onblocked'
'h.close'
@@ -24,6 +25,7 @@
'h.open.onsuccess'
'deleteDatabase()'
'h.onversionchange'
+ in versionchange, old = "" new = ""
h closing immediately
'h.close'
'deleteDatabase().onblocked'
@@ -40,11 +42,36 @@
'h.setVersion.onsuccess'
'h.setVersion.transaction-complete'
'h.onversionchange'
+ in versionchange, old = "1" new = ""
h closing, but not immediately
'deleteDatabase().onblocked'
'h.close'
'deleteDatabase().onsuccess'
PASS self.steps.toString() is "h.open,h.open.onsuccess,h.setVersion,deleteDatabase(),h.setVersion.onsuccess,h.setVersion.transaction-complete,h.onversionchange,deleteDatabase().onblocked,h.close,deleteDatabase().onsuccess"
+
+TEST: Correct order when there are pending setVersion, delete and open calls.
+self.dbname = 'test4'; self.ver = 1; self.steps = []
+'h.open'
+'h.open.onsuccess'
+'h2.open'
+'h2.open.onsuccess'
+'h.setVersion'
+'deleteDatabase()'
+'h2.onversionchange'
+ in versionchange, old = "" new = "1"
+'h.setVersion.onblocked'
+'h3.open'
+'h2.close'
+'h.setVersion.onsuccess'
+'h.setVersion.transaction-complete'
+'h.onversionchange'
+ in versionchange, old = "1" new = ""
+ h closing, but not immediately
+'deleteDatabase().onblocked'
+'h.close'
+'deleteDatabase().onsuccess'
+'h3.open.onsuccess'
+PASS self.steps.toString() is "h.open,h.open.onsuccess,h2.open,h2.open.onsuccess,h.setVersion,deleteDatabase(),h2.onversionchange,h.setVersion.onblocked,h3.open,h2.close,h.setVersion.onsuccess,h.setVersion.transaction-complete,h.onversionchange,deleteDatabase().onblocked,h.close,deleteDatabase().onsuccess,h3.open.onsuccess"
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/storage/indexeddb/resources/factory-deletedatabase-interactions.js (120221 => 120222)
--- trunk/LayoutTests/storage/indexeddb/resources/factory-deletedatabase-interactions.js 2012-06-13 17:24:59 UTC (rev 120221)
+++ trunk/LayoutTests/storage/indexeddb/resources/factory-deletedatabase-interactions.js 2012-06-13 17:30:52 UTC (rev 120222)
@@ -17,6 +17,7 @@
self.steps.push(evalAndLog("'" + id + ".open.onsuccess'"));
that.handle._onversionchange_ = function(e) {
self.steps.push(evalAndLog("'" + id + ".onversionchange'"));
+ debug(" in versionchange, old = " + JSON.stringify(e.target.version) + " new = " + JSON.stringify(e.version));
if (opts && opts.onversion) { opts.onversion.call(that); }
};
if (opts && opts.onsuccess) { opts.onsuccess.call(that); }
@@ -179,8 +180,55 @@
"h.close",
"deleteDatabase().onsuccess"
].toString());
+ test4();
+ }
+}
+
+function test4() {
+ debug("");
+ debug("TEST: Correct order when there are pending setVersion, delete and open calls.");
+ evalAndLog("self.dbname = 'test4'; self.ver = 1; self.steps = []");
+ var h = new Connection("h");
+ var h2 = new Connection("h2");
+ var h3 = new Connection("h3");
+ runSteps([function(doNext) { h.open({onsuccess: doNext,
+ onversion: function() {
+ debug(" h closing, but not immediately");
+ setTimeout(function() { h.close(); }, 0);
+ }});
+ },
+ function(doNext) { h2.open({onsuccess: doNext}); },
+ function(doNext) { h.setVersion({onblocked: function() {
+ h3.open({onsuccess: finishTest});
+ h2.close();
+ }});
+ doNext();
+ },
+ function(doNext) { deleteDatabase("", self.dbname); },
+ ]);
+
+ function finishTest() {
+ shouldBeEqualToString("self.steps.toString()",
+ ["h.open",
+ "h.open.onsuccess",
+ "h2.open",
+ "h2.open.onsuccess",
+ "h.setVersion",
+ "deleteDatabase()",
+ "h2.onversionchange",
+ "h.setVersion.onblocked",
+ "h3.open",
+ "h2.close",
+ "h.setVersion.onsuccess",
+ "h.setVersion.transaction-complete",
+ "h.onversionchange",
+ "deleteDatabase().onblocked",
+ "h.close",
+ "deleteDatabase().onsuccess",
+ "h3.open.onsuccess"
+ ].toString());
finishJSTest();
}
}
-test();
\ No newline at end of file
+test();
Added: trunk/LayoutTests/storage/indexeddb/resources/three-setversion-calls.js (0 => 120222)
--- trunk/LayoutTests/storage/indexeddb/resources/three-setversion-calls.js (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/resources/three-setversion-calls.js 2012-06-13 17:30:52 UTC (rev 120222)
@@ -0,0 +1,60 @@
+if (this.importScripts) {
+ importScripts('../../../fast/js/resources/js-test-pre.js');
+ importScripts('shared.js');
+}
+
+description("Three setVersion calls are queued correctly - exercises an otherwise-untested code path");
+
+function test()
+{
+ removeVendorPrefixes();
+ openDBConnection();
+}
+
+function openDBConnection()
+{
+ request = evalAndLog("indexedDB.open('three-setversion-calls')");
+ request._onsuccess_ = openSuccess1;
+ request._onerror_ = unexpectedErrorCallback;
+}
+
+function successHandler(id)
+{
+ return function(e) {
+ trans = e.target.result;
+ debug("setVersion " + id);
+ trans._onerror_ = unexpectedErrorCallback;
+ trans._onabort_ = unexpectedAbortCallback;
+ trans._oncomplete_ = function(evt) {
+ debug("setVersion " + id + " complete");
+ if (id == kNumVersionCalls - 1) {
+ evalAndLog("finishedAllSetVersions = true");
+ connection.close();
+ }
+ }
+ }
+}
+
+finishedAllSetVersions = false;
+kNumVersionCalls = 3;
+function openSuccess1(e)
+{
+ connection = e.target.result;
+ for (var i = 0; i < kNumVersionCalls; i++) {
+ vcRequest = evalAndLog('connection.setVersion("version ' + i + '")');
+ vcRequest._onblocked_ = unexpectedBlockedCallback;
+ vcRequest._onerror_ = unexpectedErrorCallback;
+ vcRequest._onsuccess_ = successHandler(i);
+ if (!i) {
+ deleteRequest = evalAndLog('indexedDB.deleteDatabase("three-setversion-calls")');
+ deleteRequest._onerror_ = unexpectedErrorCallback;
+ deleteRequest._onsuccess_ = function() {
+ debug("Successfully deleted database");
+ shouldBeTrue("finishedAllSetVersions");
+ finishJSTest();
+ };
+ }
+ }
+}
+
+test();
Added: trunk/LayoutTests/storage/indexeddb/three-setversion-calls-expected.txt (0 => 120222)
--- trunk/LayoutTests/storage/indexeddb/three-setversion-calls-expected.txt (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/three-setversion-calls-expected.txt 2012-06-13 17:30:52 UTC (rev 120222)
@@ -0,0 +1,25 @@
+Three setVersion calls are queued correctly - exercises an otherwise-untested code path
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+indexedDB = self.indexedDB || self.webkitIndexedDB || self.mozIndexedDB || self.msIndexedDB || self.OIndexedDB;
+
+indexedDB.open('three-setversion-calls')
+connection.setVersion("version 0")
+indexedDB.deleteDatabase("three-setversion-calls")
+connection.setVersion("version 1")
+connection.setVersion("version 2")
+setVersion 0
+setVersion 0 complete
+setVersion 1
+setVersion 1 complete
+setVersion 2
+setVersion 2 complete
+finishedAllSetVersions = true
+Successfully deleted database
+PASS finishedAllSetVersions is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/storage/indexeddb/three-setversion-calls.html (0 => 120222)
--- trunk/LayoutTests/storage/indexeddb/three-setversion-calls.html (rev 0)
+++ trunk/LayoutTests/storage/indexeddb/three-setversion-calls.html 2012-06-13 17:30:52 UTC (rev 120222)
@@ -0,0 +1,10 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (120221 => 120222)
--- trunk/Source/WebCore/ChangeLog 2012-06-13 17:24:59 UTC (rev 120221)
+++ trunk/Source/WebCore/ChangeLog 2012-06-13 17:30:52 UTC (rev 120222)
@@ -1,3 +1,15 @@
+2012-06-13 David Grogan <[email protected]>
+
+ IndexedDB: Add tests, an assert, and some comments around open/close/setVersion call sequencing
+ https://bugs.webkit.org/show_bug.cgi?id=88829
+
+ Reviewed by Tony Chang.
+
+ Test: storage/indexeddb/three-setversion-calls.html
+
+ * Modules/indexeddb/IDBDatabaseBackendImpl.cpp:
+ (WebCore::IDBDatabaseBackendImpl::processPendingCalls):
+
2012-06-09 Vsevolod Vlasov <[email protected]>
Web Inspector: Errors when pending console messages are attached to _javascript_SourceFrame.
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp (120221 => 120222)
--- trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp 2012-06-13 17:24:59 UTC (rev 120221)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBDatabaseBackendImpl.cpp 2012-06-13 17:30:52 UTC (rev 120222)
@@ -280,6 +280,8 @@
void IDBDatabaseBackendImpl::processPendingCalls()
{
+ ASSERT(m_databaseCallbacksSet.size() <= 1);
+
// Pending calls may be requeued or aborted
Deque<RefPtr<PendingSetVersionCall> > pendingSetVersionCalls;
m_pendingSetVersionCalls.swap(pendingSetVersionCalls);
@@ -290,6 +292,17 @@
ASSERT(!ec);
}
+ // If there were any pending set version calls, we better have started one.
+ ASSERT(m_pendingSetVersionCalls.isEmpty() || m_runningVersionChangeTransaction);
+
+ // m_pendingSetVersionCalls is non-empty in two cases:
+ // 1) When two versionchange transactions are requested while another
+ // version change transaction is running.
+ // 2) When three versionchange transactions are requested in a row, before
+ // any of their event handlers are run.
+ // Note that this check is only an optimization to reduce queue-churn and
+ // not necessary for correctness; deleteDatabase and openConnection will
+ // requeue their calls if this condition is true.
if (m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty())
return;
@@ -301,13 +314,19 @@
deleteDatabase(pendingDeleteCall->callbacks());
}
+ // This check is also not really needed, openConnection would just requeue its calls.
if (m_runningVersionChangeTransaction || !m_pendingSetVersionCalls.isEmpty() || !m_pendingDeleteCalls.isEmpty())
return;
- while (!m_pendingOpenCalls.isEmpty()) {
- RefPtr<PendingOpenCall> pendingOpenCall = m_pendingOpenCalls.takeFirst();
+ // Given the check above, it appears that calls cannot be requeued by
+ // openConnection, but use a different queue for iteration to be safe.
+ Deque<RefPtr<PendingOpenCall> > pendingOpenCalls;
+ m_pendingOpenCalls.swap(pendingOpenCalls);
+ while (!pendingOpenCalls.isEmpty()) {
+ RefPtr<PendingOpenCall> pendingOpenCall = pendingOpenCalls.takeFirst();
openConnection(pendingOpenCall->callbacks());
}
+ ASSERT(m_pendingOpenCalls.isEmpty());
}
PassRefPtr<IDBTransactionBackendInterface> IDBDatabaseBackendImpl::transaction(DOMStringList* objectStoreNames, unsigned short mode, ExceptionCode& ec)