Title: [276605] branches/safari-607-branch
Revision
276605
Author
repst...@apple.com
Date
2021-04-26 11:42:53 -0700 (Mon, 26 Apr 2021)

Log Message

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

Modified Paths

Added Paths

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
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to