Diff
Modified: trunk/LayoutTests/ChangeLog (271378 => 271379)
--- trunk/LayoutTests/ChangeLog 2021-01-11 21:36:41 UTC (rev 271378)
+++ trunk/LayoutTests/ChangeLog 2021-01-11 22:00:11 UTC (rev 271379)
@@ -1,3 +1,18 @@
+2021-01-11 Sihui Liu <[email protected]>
+
+ Keep newly created IDBObjectStores in deleted map when IDBTransaction is aborted
+ https://bugs.webkit.org/show_bug.cgi?id=220483
+ <rdar://problem/71934293>
+
+ Reviewed by Darin Adler.
+
+ * storage/indexeddb/modern/abort-objectstore-info-expected.txt:
+ * storage/indexeddb/modern/abort-objectstore-info-private-expected.txt:
+ * storage/indexeddb/modern/resources/abort-objectstore-info.js:
+ (prepareDatabase):
+ (secondUpgradeNeeded):
+ (checkState):
+
2021-01-11 Peng Liu <[email protected]>
A video element needs to ignore the request to enter/exit fullscreen before the current fullscreen mode change is completed
Modified: trunk/LayoutTests/storage/indexeddb/modern/abort-objectstore-info-expected.txt (271378 => 271379)
--- trunk/LayoutTests/storage/indexeddb/modern/abort-objectstore-info-expected.txt 2021-01-11 21:36:41 UTC (rev 271378)
+++ trunk/LayoutTests/storage/indexeddb/modern/abort-objectstore-info-expected.txt 2021-01-11 22:00:11 UTC (rev 271379)
@@ -11,11 +11,14 @@
objectStore1_1 = connection1.createObjectStore('objectStore1');
objectStore1_2 = connection1.createObjectStore('objectStore2');
objectStore1_2.createIndex('index', 'foo');
+objectStore1_4 = connection1.createObjectStore('objectStore4');
+objectStore1_4.createIndex('index', 'foo');
PASS connection1.version is 1
-PASS connection1.objectStoreNames.length is 2
+PASS connection1.objectStoreNames.length is 3
PASS objectStore1_1.indexNames.length is 0
PASS objectStore1_2.indexNames.length is 1
+PASS objectStore1_4.indexNames.length is 1
connection1.close();
secondRequest = indexedDB.open(dbname, 2);
@@ -24,22 +27,30 @@
objectStore2_1 = secondRequest.transaction.objectStore('objectStore1');
objectStore2_2 = secondRequest.transaction.objectStore('objectStore2');
objectStore2_3 = connection2.createObjectStore('objectStore3');
+objectStore2_4 = secondRequest.transaction.objectStore('objectStore4');
PASS connection2.version is 2
-PASS connection2.objectStoreNames.length is 3
+PASS connection2.objectStoreNames.length is 4
PASS objectStore2_1.indexNames.length is 0
PASS objectStore2_2.indexNames.length is 1
PASS objectStore2_3.indexNames.length is 0
+PASS objectStore2_4.indexNames.length is 1
objectStore2_1.createIndex('index', 'foo');
objectStore2_2.deleteIndex('index');
objectStore2_3.createIndex('index', 'foo');
+objectStore2_4.deleteIndex('index');
+connection2.deleteObjectStore('objectStore4');
+new_objectStore2_4 = connection2.createObjectStore('objectStore4');
+new_objectStore2_4.createIndex('index1', 'foo');
+new_objectStore2_4.createIndex('index2', 'bar');
PASS connection2.version is 2
-PASS connection2.objectStoreNames.length is 3
+PASS connection2.objectStoreNames.length is 4
PASS objectStore2_1.indexNames.length is 1
PASS objectStore2_2.indexNames.length is 0
PASS objectStore2_3.indexNames.length is 1
+PASS new_objectStore2_4.indexNames.length is 2
secondRequest.transaction.abort();
connection2.close()
@@ -46,15 +57,18 @@
checkState():
PASS connection1.version is 1
-PASS connection1.objectStoreNames.length is 2
+PASS connection1.objectStoreNames.length is 3
PASS objectStore1_1.indexNames.length is 0
PASS objectStore1_2.indexNames.length is 1
+PASS objectStore1_4.indexNames.length is 1
PASS connection2.version is 1
-PASS connection2.objectStoreNames.length is 2
+PASS connection2.objectStoreNames.length is 3
PASS objectStore2_1.indexNames.length is 0
PASS objectStore2_2.indexNames.length is 1
PASS objectStore2_3.indexNames.length is 0
+PASS objectStore2_4.indexNames.length is 1
+PASS new_objectStore2_4.indexNames.length is 0
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/storage/indexeddb/modern/abort-objectstore-info-private-expected.txt (271378 => 271379)
--- trunk/LayoutTests/storage/indexeddb/modern/abort-objectstore-info-private-expected.txt 2021-01-11 21:36:41 UTC (rev 271378)
+++ trunk/LayoutTests/storage/indexeddb/modern/abort-objectstore-info-private-expected.txt 2021-01-11 22:00:11 UTC (rev 271379)
@@ -11,11 +11,14 @@
objectStore1_1 = connection1.createObjectStore('objectStore1');
objectStore1_2 = connection1.createObjectStore('objectStore2');
objectStore1_2.createIndex('index', 'foo');
+objectStore1_4 = connection1.createObjectStore('objectStore4');
+objectStore1_4.createIndex('index', 'foo');
PASS connection1.version is 1
-PASS connection1.objectStoreNames.length is 2
+PASS connection1.objectStoreNames.length is 3
PASS objectStore1_1.indexNames.length is 0
PASS objectStore1_2.indexNames.length is 1
+PASS objectStore1_4.indexNames.length is 1
connection1.close();
secondRequest = indexedDB.open(dbname, 2);
@@ -24,22 +27,30 @@
objectStore2_1 = secondRequest.transaction.objectStore('objectStore1');
objectStore2_2 = secondRequest.transaction.objectStore('objectStore2');
objectStore2_3 = connection2.createObjectStore('objectStore3');
+objectStore2_4 = secondRequest.transaction.objectStore('objectStore4');
PASS connection2.version is 2
-PASS connection2.objectStoreNames.length is 3
+PASS connection2.objectStoreNames.length is 4
PASS objectStore2_1.indexNames.length is 0
PASS objectStore2_2.indexNames.length is 1
PASS objectStore2_3.indexNames.length is 0
+PASS objectStore2_4.indexNames.length is 1
objectStore2_1.createIndex('index', 'foo');
objectStore2_2.deleteIndex('index');
objectStore2_3.createIndex('index', 'foo');
+objectStore2_4.deleteIndex('index');
+connection2.deleteObjectStore('objectStore4');
+new_objectStore2_4 = connection2.createObjectStore('objectStore4');
+new_objectStore2_4.createIndex('index1', 'foo');
+new_objectStore2_4.createIndex('index2', 'bar');
PASS connection2.version is 2
-PASS connection2.objectStoreNames.length is 3
+PASS connection2.objectStoreNames.length is 4
PASS objectStore2_1.indexNames.length is 1
PASS objectStore2_2.indexNames.length is 0
PASS objectStore2_3.indexNames.length is 1
+PASS new_objectStore2_4.indexNames.length is 2
secondRequest.transaction.abort();
connection2.close()
@@ -46,15 +57,18 @@
checkState():
PASS connection1.version is 1
-PASS connection1.objectStoreNames.length is 2
+PASS connection1.objectStoreNames.length is 3
PASS objectStore1_1.indexNames.length is 0
PASS objectStore1_2.indexNames.length is 1
+PASS objectStore1_4.indexNames.length is 1
PASS connection2.version is 1
-PASS connection2.objectStoreNames.length is 2
+PASS connection2.objectStoreNames.length is 3
PASS objectStore2_1.indexNames.length is 0
PASS objectStore2_2.indexNames.length is 1
PASS objectStore2_3.indexNames.length is 0
+PASS objectStore2_4.indexNames.length is 1
+PASS new_objectStore2_4.indexNames.length is 0
PASS successfullyParsed is true
TEST COMPLETE
Modified: trunk/LayoutTests/storage/indexeddb/modern/resources/abort-objectstore-info.js (271378 => 271379)
--- trunk/LayoutTests/storage/indexeddb/modern/resources/abort-objectstore-info.js 2021-01-11 21:36:41 UTC (rev 271378)
+++ trunk/LayoutTests/storage/indexeddb/modern/resources/abort-objectstore-info.js 2021-01-11 22:00:11 UTC (rev 271379)
@@ -8,12 +8,15 @@
evalAndLog("objectStore1_1 = connection1.createObjectStore('objectStore1');");
evalAndLog("objectStore1_2 = connection1.createObjectStore('objectStore2');");
evalAndLog("objectStore1_2.createIndex('index', 'foo');");
+ evalAndLog("objectStore1_4 = connection1.createObjectStore('objectStore4');");
+ evalAndLog("objectStore1_4.createIndex('index', 'foo');");
debug("");
shouldBe("connection1.version", "1");
- shouldBe("connection1.objectStoreNames.length", "2");
+ shouldBe("connection1.objectStoreNames.length", "3");
shouldBe("objectStore1_1.indexNames.length", "0");
shouldBe("objectStore1_2.indexNames.length", "1");
+ shouldBe("objectStore1_4.indexNames.length", "1");
debug("");
}
@@ -35,25 +38,33 @@
evalAndLog("objectStore2_1 = secondRequest.transaction.objectStore('objectStore1');");
evalAndLog("objectStore2_2 = secondRequest.transaction.objectStore('objectStore2');");
evalAndLog("objectStore2_3 = connection2.createObjectStore('objectStore3');");
+ evalAndLog("objectStore2_4 = secondRequest.transaction.objectStore('objectStore4');");
debug("");
shouldBe("connection2.version", "2");
- shouldBe("connection2.objectStoreNames.length", "3");
+ shouldBe("connection2.objectStoreNames.length", "4");
shouldBe("objectStore2_1.indexNames.length", "0");
shouldBe("objectStore2_2.indexNames.length", "1");
shouldBe("objectStore2_3.indexNames.length", "0");
+ shouldBe("objectStore2_4.indexNames.length", "1");
debug("");
evalAndLog("objectStore2_1.createIndex('index', 'foo');");
evalAndLog("objectStore2_2.deleteIndex('index');");
evalAndLog("objectStore2_3.createIndex('index', 'foo');");
+ evalAndLog("objectStore2_4.deleteIndex('index');");
+ evalAndLog("connection2.deleteObjectStore('objectStore4');");
+ evalAndLog("new_objectStore2_4 = connection2.createObjectStore('objectStore4');");
+ evalAndLog("new_objectStore2_4.createIndex('index1', 'foo');");
+ evalAndLog("new_objectStore2_4.createIndex('index2', 'bar');");
+
debug("");
-
shouldBe("connection2.version", "2");
- shouldBe("connection2.objectStoreNames.length", "3");
+ shouldBe("connection2.objectStoreNames.length", "4");
shouldBe("objectStore2_1.indexNames.length", "1");
shouldBe("objectStore2_2.indexNames.length", "0");
shouldBe("objectStore2_3.indexNames.length", "1");
+ shouldBe("new_objectStore2_4.indexNames.length", "2");
debug("");
evalAndLog("secondRequest.transaction.abort();");
@@ -65,16 +76,19 @@
debug("checkState():");
shouldBe("connection1.version", "1");
- shouldBe("connection1.objectStoreNames.length", "2");
+ shouldBe("connection1.objectStoreNames.length", "3");
shouldBe("objectStore1_1.indexNames.length", "0");
shouldBe("objectStore1_2.indexNames.length", "1");
+ shouldBe("objectStore1_4.indexNames.length", "1");
debug("");
shouldBe("connection2.version", "1");
- shouldBe("connection2.objectStoreNames.length", "2");
+ shouldBe("connection2.objectStoreNames.length", "3");
shouldBe("objectStore2_1.indexNames.length", "0");
shouldBe("objectStore2_2.indexNames.length", "1");
shouldBe("objectStore2_3.indexNames.length", "0");
+ shouldBe("objectStore2_4.indexNames.length", "1");
+ shouldBe("new_objectStore2_4.indexNames.length", "0");
finishJSTest();
}
Modified: trunk/Source/WebCore/ChangeLog (271378 => 271379)
--- trunk/Source/WebCore/ChangeLog 2021-01-11 21:36:41 UTC (rev 271378)
+++ trunk/Source/WebCore/ChangeLog 2021-01-11 22:00:11 UTC (rev 271379)
@@ -1,3 +1,23 @@
+2021-01-11 Sihui Liu <[email protected]>
+
+ Keep newly created IDBObjectStores in deleted map when IDBTransaction is aborted
+ https://bugs.webkit.org/show_bug.cgi?id=220483
+ <rdar://problem/71934293>
+
+ Reviewed by Darin Adler.
+
+ When an upgrade transaction is aborted, we move objects from m_deletedObjectStores to m_referencedObjectStores
+ to revert the deletion operation. When updating m_referencedObjectStores, we did not check whether key already
+ exists (this can happen when an object store gets deleted and a new object store with the same name is
+ created; see updated layout test). Therefore, some object store in m_referencedObjectStores would be replaced
+ and destroyed (since m_referencedObjectStores holds unique pointers) when the object store is referenced by JS
+ object.
+
+ Test: storage/indexeddb/modern/abort-objectstore-info.html
+
+ * Modules/indexeddb/IDBTransaction.cpp:
+ (WebCore::IDBTransaction::internalAbort):
+
2021-01-11 Alex Christensen <[email protected]>
Use sendWithAsyncReply instead of dataCallback for icon loading
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp (271378 => 271379)
--- trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp 2021-01-11 21:36:41 UTC (rev 271378)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp 2021-01-11 22:00:11 UTC (rev 271379)
@@ -232,10 +232,14 @@
auto& info = m_database->info();
Vector<uint64_t> identifiersToRemove;
+ Vector<std::unique_ptr<IDBObjectStore>> objectStoresToDelete;
for (auto& iterator : m_deletedObjectStores) {
if (info.infoForExistingObjectStore(iterator.key)) {
auto name = iterator.value->info().name();
- m_referencedObjectStores.set(name, WTFMove(iterator.value));
+ auto result = m_referencedObjectStores.add(name, nullptr);
+ if (!result.isNewEntry)
+ objectStoresToDelete.append(std::exchange(result.iterator->value, nullptr));
+ result.iterator->value = std::exchange(iterator.value, nullptr);
identifiersToRemove.append(iterator.key);
}
}
@@ -245,6 +249,12 @@
for (auto& objectStore : m_referencedObjectStores.values())
objectStore->rollbackForVersionChangeAbort();
+
+ for (auto& objectStore : objectStoresToDelete) {
+ objectStore->rollbackForVersionChangeAbort();
+ auto objectStoreIdentifier = objectStore->info().identifier();
+ m_deletedObjectStores.set(objectStoreIdentifier, std::exchange(objectStore, nullptr));
+ }
}
transitionedToFinishing(IndexedDB::TransactionState::Aborting);