Diff
Modified: branches/safari-607-branch/LayoutTests/ChangeLog (276604 => 276605)
--- branches/safari-607-branch/LayoutTests/ChangeLog 2021-04-26 18:12:16 UTC (rev 276604)
+++ branches/safari-607-branch/LayoutTests/ChangeLog 2021-04-26 18:42:53 UTC (rev 276605)
@@ -1,3 +1,61 @@
+2021-04-26 Russell Epstein <repst...@apple.com>
+
+ Cherry-pick r271368. rdar://problem/77160704
+
+ Keep newly created IDBIndex objects in deleted map when IDBTransaction is aborted
+ https://bugs.webkit.org/show_bug.cgi?id=220489
+ <rdar://problem/70498831>
+
+ Patch by Sihui Liu <sihui_...@appe.com> on 2021-01-11
+ Reviewed by Youenn Fablet.
+
+ Source/WebCore:
+
+ When an upgrade transaction is aborted, we move objects from m_deletedIndexes to m_referencedIndexes to revert
+ the index deletion operation. When updating m_referencedIndexes, we did not check whether key already exists.
+ Therefore, some indexes in m_referencedIndexes would be replaced and destroyed (since m_referencedIndexes holds
+ unique pointers) when the index is still referenced by JS.
+
+ Tests: storage/indexeddb/modern/abort-index-info-private.html
+ storage/indexeddb/modern/abort-index-info.html
+
+ * Modules/indexeddb/IDBObjectStore.cpp:
+ (WebCore::IDBObjectStore::rollbackForVersionChangeAbort):
+
+ LayoutTests:
+
+ * storage/indexeddb/modern/abort-index-info-expected.txt: Added.
+ * storage/indexeddb/modern/abort-index-info-private-expected.txt: Added.
+ * storage/indexeddb/modern/abort-index-info-private.html: Added.
+ * storage/indexeddb/modern/abort-index-info.html: Added.
+ * storage/indexeddb/modern/resources/abort-index-info.js: Added.
+ (prepareDatabase):
+ (versionChangeSuccessCallback.secondRequest.onerror):
+ (versionChangeSuccessCallback):
+ (secondUpgradeNeeded):
+ (checkState):
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271368 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-01-11 Sihui Liu <sihui_...@appe.com>
+
+ Keep newly created IDBIndex objects in deleted map when IDBTransaction is aborted
+ https://bugs.webkit.org/show_bug.cgi?id=220489
+ <rdar://problem/70498831>
+
+ Reviewed by Youenn Fablet.
+
+ * storage/indexeddb/modern/abort-index-info-expected.txt: Added.
+ * storage/indexeddb/modern/abort-index-info-private-expected.txt: Added.
+ * storage/indexeddb/modern/abort-index-info-private.html: Added.
+ * storage/indexeddb/modern/abort-index-info.html: Added.
+ * storage/indexeddb/modern/resources/abort-index-info.js: Added.
+ (prepareDatabase):
+ (versionChangeSuccessCallback.secondRequest.onerror):
+ (versionChangeSuccessCallback):
+ (secondUpgradeNeeded):
+ (checkState):
+
2019-07-01 Alan Coon <alanc...@apple.com>
Cherry-pick r244621. rdar://problem/52492610
Added: branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info-expected.txt (0 => 276605)
--- branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info-expected.txt (rev 0)
+++ branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info-expected.txt 2021-04-26 18:42:53 UTC (rev 276605)
@@ -0,0 +1,51 @@
+Explores the edge cases of what IDBIndex objects look like after a version change transaction that changed them aborts.
+
+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.deleteDatabase(dbname)
+indexedDB.open(dbname)
+connection1 = event.target.result;
+objectStore1 = connection1.createObjectStore('objectStore');
+index1_1 = objectStore1.createIndex('foo', 'foo');
+
+PASS connection1.version is 1
+PASS objectStore1.indexNames.length is 1
+PASS index1_1.name is "foo"
+connection1.close();
+secondRequest = indexedDB.open(dbname, 2);
+secondRequest._onupgradeneeded_ = secondUpgradeNeeded;
+
+connection2 = event.target.result;
+objectStore2 = secondRequest.transaction.objectStore('objectStore');
+index2_1 = objectStore2.index('foo');
+
+PASS connection2.version is 2
+PASS objectStore2.indexNames.length is 1
+PASS index2_1.name is "foo"
+
+objectStore2.deleteIndex('foo');
+new_index2_1 = objectStore2.createIndex('foo', 'foo');
+index2_2 = objectStore2.createIndex('bar', 'bar');
+
+PASS objectStore2.indexNames.length is 2
+PASS new_index2_1.name is "foo"
+PASS index2_2.name is "bar"
+
+secondRequest.transaction.abort();
+connection2.close()
+
+PASS connection1.version is 1
+PASS objectStore1.indexNames.length is 1
+PASS index1_1.name is "foo"
+PASS connection2.version is 1
+PASS objectStore2.indexNames.length is 1
+PASS index2_1.name is "foo"
+PASS new_index2_1.name is "foo"
+PASS index2_2.name is "bar"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info-private-expected.txt (0 => 276605)
--- branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info-private-expected.txt (rev 0)
+++ branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info-private-expected.txt 2021-04-26 18:42:53 UTC (rev 276605)
@@ -0,0 +1,51 @@
+Explores the edge cases of what IDBIndex objects look like after a version change transaction that changed them aborts.
+
+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.deleteDatabase(dbname)
+indexedDB.open(dbname)
+connection1 = event.target.result;
+objectStore1 = connection1.createObjectStore('objectStore');
+index1_1 = objectStore1.createIndex('foo', 'foo');
+
+PASS connection1.version is 1
+PASS objectStore1.indexNames.length is 1
+PASS index1_1.name is "foo"
+connection1.close();
+secondRequest = indexedDB.open(dbname, 2);
+secondRequest._onupgradeneeded_ = secondUpgradeNeeded;
+
+connection2 = event.target.result;
+objectStore2 = secondRequest.transaction.objectStore('objectStore');
+index2_1 = objectStore2.index('foo');
+
+PASS connection2.version is 2
+PASS objectStore2.indexNames.length is 1
+PASS index2_1.name is "foo"
+
+objectStore2.deleteIndex('foo');
+new_index2_1 = objectStore2.createIndex('foo', 'foo');
+index2_2 = objectStore2.createIndex('bar', 'bar');
+
+PASS objectStore2.indexNames.length is 2
+PASS new_index2_1.name is "foo"
+PASS index2_2.name is "bar"
+
+secondRequest.transaction.abort();
+connection2.close()
+
+PASS connection1.version is 1
+PASS objectStore1.indexNames.length is 1
+PASS index1_1.name is "foo"
+PASS connection2.version is 1
+PASS objectStore2.indexNames.length is 1
+PASS index2_1.name is "foo"
+PASS new_index2_1.name is "foo"
+PASS index2_2.name is "bar"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info-private.html (0 => 276605)
--- branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info-private.html (rev 0)
+++ branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info-private.html 2021-04-26 18:42:53 UTC (rev 276605)
@@ -0,0 +1,10 @@
+<!-- webkit-test-runner [ useEphemeralSession=true ] -->
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+</body>
+</html>
\ No newline at end of file
Added: branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info.html (0 => 276605)
--- branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info.html (rev 0)
+++ branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/abort-index-info.html 2021-04-26 18:42:53 UTC (rev 276605)
@@ -0,0 +1,9 @@
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+</body>
+</html>
\ No newline at end of file
Added: branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/resources/abort-index-info.js (0 => 276605)
--- branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/resources/abort-index-info.js (rev 0)
+++ branches/safari-607-branch/LayoutTests/storage/indexeddb/modern/resources/abort-index-info.js 2021-04-26 18:42:53 UTC (rev 276605)
@@ -0,0 +1,68 @@
+description("Explores the edge cases of what IDBIndex objects look like after a version change transaction that changed them aborts.");
+
+indexedDBTest(prepareDatabase, versionChangeSuccessCallback);
+
+function prepareDatabase()
+{
+ evalAndLog("connection1 = event.target.result;");
+ evalAndLog("objectStore1 = connection1.createObjectStore('objectStore');");
+ evalAndLog("index1_1 = objectStore1.createIndex('foo', 'foo');");
+
+ debug("");
+ shouldBe("connection1.version", "1");
+ shouldBe("objectStore1.indexNames.length", "1");
+ shouldBeEqualToString("index1_1.name", "foo");
+}
+
+function versionChangeSuccessCallback()
+{
+ evalAndLog("connection1.close();");
+ evalAndLog("secondRequest = indexedDB.open(dbname, 2);");
+ evalAndLog("secondRequest._onupgradeneeded_ = secondUpgradeNeeded;");
+ secondRequest._onsuccess_ = unexpectedSuccessCallback;
+ secondRequest._onerror_ = function() {
+ evalAndLog("connection2.close()");
+ checkState();
+ };
+}
+
+function secondUpgradeNeeded()
+{
+ debug("");
+ evalAndLog("connection2 = event.target.result;");
+ evalAndLog("objectStore2 = secondRequest.transaction.objectStore('objectStore');");
+ evalAndLog("index2_1 = objectStore2.index('foo');");
+
+ debug("");
+ shouldBe("connection2.version", "2");
+ shouldBe("objectStore2.indexNames.length", "1");
+ shouldBeEqualToString("index2_1.name", "foo");
+
+ debug("");
+ evalAndLog("objectStore2.deleteIndex('foo');");
+ evalAndLog("new_index2_1 = objectStore2.createIndex('foo', 'foo');");
+ evalAndLog("index2_2 = objectStore2.createIndex('bar', 'bar');");
+
+ debug("");
+ shouldBe("objectStore2.indexNames.length", "2");
+ shouldBeEqualToString("new_index2_1.name", "foo");
+ shouldBeEqualToString("index2_2.name", "bar");
+
+ debug("");
+ evalAndLog("secondRequest.transaction.abort();");
+}
+
+function checkState()
+{
+ debug("");
+ shouldBe("connection1.version", "1");
+ shouldBe("objectStore1.indexNames.length", "1");
+ shouldBeEqualToString("index1_1.name", "foo");
+ shouldBe("connection2.version", "1");
+ shouldBe("objectStore2.indexNames.length", "1");
+ shouldBeEqualToString("index2_1.name", "foo");
+ shouldBeEqualToString("new_index2_1.name", "foo");
+ shouldBeEqualToString("index2_2.name", "bar");
+
+ finishJSTest();
+}
Modified: branches/safari-607-branch/Source/WebCore/ChangeLog (276604 => 276605)
--- branches/safari-607-branch/Source/WebCore/ChangeLog 2021-04-26 18:12:16 UTC (rev 276604)
+++ branches/safari-607-branch/Source/WebCore/ChangeLog 2021-04-26 18:42:53 UTC (rev 276605)
@@ -1,3 +1,61 @@
+2021-04-26 Russell Epstein <repst...@apple.com>
+
+ Cherry-pick r271368. rdar://problem/77160704
+
+ Keep newly created IDBIndex objects in deleted map when IDBTransaction is aborted
+ https://bugs.webkit.org/show_bug.cgi?id=220489
+ <rdar://problem/70498831>
+
+ Patch by Sihui Liu <sihui_...@appe.com> on 2021-01-11
+ Reviewed by Youenn Fablet.
+
+ Source/WebCore:
+
+ When an upgrade transaction is aborted, we move objects from m_deletedIndexes to m_referencedIndexes to revert
+ the index deletion operation. When updating m_referencedIndexes, we did not check whether key already exists.
+ Therefore, some indexes in m_referencedIndexes would be replaced and destroyed (since m_referencedIndexes holds
+ unique pointers) when the index is still referenced by JS.
+
+ Tests: storage/indexeddb/modern/abort-index-info-private.html
+ storage/indexeddb/modern/abort-index-info.html
+
+ * Modules/indexeddb/IDBObjectStore.cpp:
+ (WebCore::IDBObjectStore::rollbackForVersionChangeAbort):
+
+ LayoutTests:
+
+ * storage/indexeddb/modern/abort-index-info-expected.txt: Added.
+ * storage/indexeddb/modern/abort-index-info-private-expected.txt: Added.
+ * storage/indexeddb/modern/abort-index-info-private.html: Added.
+ * storage/indexeddb/modern/abort-index-info.html: Added.
+ * storage/indexeddb/modern/resources/abort-index-info.js: Added.
+ (prepareDatabase):
+ (versionChangeSuccessCallback.secondRequest.onerror):
+ (versionChangeSuccessCallback):
+ (secondUpgradeNeeded):
+ (checkState):
+
+ git-svn-id: https://svn.webkit.org/repository/webkit/trunk@271368 268f45cc-cd09-0410-ab3c-d52691b4dbfc
+
+ 2021-01-11 Sihui Liu <sihui_...@appe.com>
+
+ Keep newly created IDBIndex objects in deleted map when IDBTransaction is aborted
+ https://bugs.webkit.org/show_bug.cgi?id=220489
+ <rdar://problem/70498831>
+
+ Reviewed by Youenn Fablet.
+
+ When an upgrade transaction is aborted, we move objects from m_deletedIndexes to m_referencedIndexes to revert
+ the index deletion operation. When updating m_referencedIndexes, we did not check whether key already exists.
+ Therefore, some indexes in m_referencedIndexes would be replaced and destroyed (since m_referencedIndexes holds
+ unique pointers) when the index is still referenced by JS.
+
+ Tests: storage/indexeddb/modern/abort-index-info-private.html
+ storage/indexeddb/modern/abort-index-info.html
+
+ * Modules/indexeddb/IDBObjectStore.cpp:
+ (WebCore::IDBObjectStore::rollbackForVersionChangeAbort):
+
2019-07-08 Alan Coon <alanc...@apple.com>
Cherry-pick r246808. rdar://problem/52505041
Modified: branches/safari-607-branch/Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp (276604 => 276605)
--- branches/safari-607-branch/Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp 2021-04-26 18:12:16 UTC (rev 276604)
+++ branches/safari-607-branch/Source/WebCore/Modules/indexeddb/IDBObjectStore.cpp 2021-04-26 18:42:53 UTC (rev 276605)
@@ -650,10 +650,14 @@
Locker<Lock> locker(m_referencedIndexLock);
Vector<uint64_t> identifiersToRemove;
+ Vector<std::unique_ptr<IDBIndex>> indexesToDelete;
for (auto& iterator : m_deletedIndexes) {
if (m_info.hasIndex(iterator.key)) {
auto name = iterator.value->info().name();
- m_referencedIndexes.set(name, WTFMove(iterator.value));
+ auto result = m_referencedIndexes.add(name, nullptr);
+ if (!result.isNewEntry)
+ indexesToDelete.append(std::exchange(result.iterator->value, nullptr));
+ result.iterator->value = std::exchange(iterator.value, nullptr);
identifiersToRemove.append(iterator.key);
}
}
@@ -663,6 +667,12 @@
for (auto& index : m_referencedIndexes.values())
index->rollbackInfoForVersionChangeAbort();
+
+ for (auto& index : indexesToDelete) {
+ index->rollbackInfoForVersionChangeAbort();
+ auto indexIdentifier = index->info().identifier();
+ m_deletedIndexes.set(indexIdentifier, std::exchange(index, nullptr));
+ }
}
void IDBObjectStore::visitReferencedIndexes(SlotVisitor& visitor) const