Title: [264486] trunk
Revision
264486
Author
[email protected]
Date
2020-07-16 16:56:35 -0700 (Thu, 16 Jul 2020)

Log Message

IDB serialization of some DOM object types crashes the Networking process due to incorrect global object type (WPT IndexedDB/structured-clone.any tests fail)
https://bugs.webkit.org/show_bug.cgi?id=210735
<rdar://problem/62045703>

Patch by Sihui Liu <[email protected]> on 2020-07-16
Reviewed by Yusuke Suzuki.

Source/WebCore:

In r239746, IDB went back to use JSGlobalObject for serialization and deserialization. However, in our current
implementation, there is a strong assumption that DOM JS objects are tied to JSDOMGlobalObject, which is
derived from JSGlobalObject. For example, in SerializedScriptValue.cpp, we cast the global object to
JSDOMGlobalObject in many places.

We recently notice this issue when we enable some wpt test, which has been disabled since it was imported as
some types were not supported. The test fails as DOMMatrix object requires its global object to be
JSDOMGlobalObject. To fix this, introduce a new Class JSIDBSerializationGlobalObject, derived from
JSDOMGlobalObject, and use it for IDB serialization.

Tests: LayoutTests/storage/indexeddb/structured-clone.html
       LayoutTests/storage/indexeddb/structured-clone-private.html

* Modules/indexeddb/server/IDBSerializationContext.cpp:
(WebCore::IDBServer::IDBSerializationContext::initializeVM):
* Modules/indexeddb/server/IDBSerializationContext.h:
* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSDOMGlobalObject.cpp:
(WebCore::JSDOMGlobalObject::scriptExecutionContext const):
* bindings/js/JSIDBSerializationGlobalObject.cpp: Added.
(WebCore::JSIDBSerializationGlobalObject::JSIDBSerializationGlobalObject):
(WebCore::JSIDBSerializationGlobalObject::create):
(WebCore::JSIDBSerializationGlobalObject::finishCreation):
(WebCore::JSIDBSerializationGlobalObject::subspaceForImpl):
(WebCore::JSIDBSerializationGlobalObject::destroy):
* bindings/js/JSIDBSerializationGlobalObject.h: Added.
* bindings/js/WebCoreJSClientData.cpp:
(WebCore::JSVMClientData::JSVMClientData):
* bindings/js/WebCoreJSClientData.h:
(WebCore::JSVMClientData::idbSerializationSpace):
* dom/EmptyScriptExecutionContext.h: Added.
* worklets/WorkletScriptController.h:

LayoutTests:

* platform/ios/TestExpectations:
* platform/wk2/TestExpectations:
* storage/indexeddb/resources/structured-clone.js:
(testPrimitiveValue):
(testBoolean):
(testBooleanObject):
(testString):
(testStringObject):
(testNumber):
(testNumberObject):
(testBigInt):
(testBigIntObject.testOneBigIntObject):
(testBigIntObject):
(testDateObject):
(testTypedArray.testTypedArrayValue):
(testArrays):
(testGeometryTypes.testOneGeometryType):
(testRTCCertificate.promise.then):
(testRTCCertificate):
(testCryptoKey.promise.then):
(testBadTypes): Deleted.
* storage/indexeddb/structured-clone-expected.txt:
* storage/indexeddb/structured-clone-private-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (264485 => 264486)


--- trunk/LayoutTests/ChangeLog	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/LayoutTests/ChangeLog	2020-07-16 23:56:35 UTC (rev 264486)
@@ -1,3 +1,35 @@
+2020-07-16  Sihui Liu  <[email protected]>
+
+        IDB serialization of some DOM object types crashes the Networking process due to incorrect global object type (WPT IndexedDB/structured-clone.any tests fail)
+        https://bugs.webkit.org/show_bug.cgi?id=210735
+        <rdar://problem/62045703>
+
+        Reviewed by Yusuke Suzuki.
+
+        * platform/ios/TestExpectations:
+        * platform/wk2/TestExpectations:
+        * storage/indexeddb/resources/structured-clone.js:
+        (testPrimitiveValue):
+        (testBoolean):
+        (testBooleanObject):
+        (testString):
+        (testStringObject):
+        (testNumber):
+        (testNumberObject):
+        (testBigInt):
+        (testBigIntObject.testOneBigIntObject):
+        (testBigIntObject):
+        (testDateObject):
+        (testTypedArray.testTypedArrayValue):
+        (testArrays):
+        (testGeometryTypes.testOneGeometryType):
+        (testRTCCertificate.promise.then):
+        (testRTCCertificate):
+        (testCryptoKey.promise.then):
+        (testBadTypes): Deleted.
+        * storage/indexeddb/structured-clone-expected.txt:
+        * storage/indexeddb/structured-clone-private-expected.txt:
+
 2020-07-16  Hector Lopez  <[email protected]>
 
         [ macOS iOS ] imported/mozilla/svg/blend-saturation.svg is passing and need expectations removed 

Modified: trunk/LayoutTests/platform/ios/TestExpectations (264485 => 264486)


--- trunk/LayoutTests/platform/ios/TestExpectations	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/LayoutTests/platform/ios/TestExpectations	2020-07-16 23:56:35 UTC (rev 264486)
@@ -1408,8 +1408,6 @@
 webkit.org/b/181752 storage/indexeddb/removed.html [ Failure ]
 webkit.org/b/181752 storage/indexeddb/request-leak-private.html [ Failure ]
 webkit.org/b/181752 storage/indexeddb/request-leak.html [ Failure ]
-webkit.org/b/181752 storage/indexeddb/structured-clone-private.html [ Failure ]
-webkit.org/b/181752 storage/indexeddb/structured-clone.html [ Failure ]
 webkit.org/b/181752 storage/indexeddb/wasm-exceptions.html [ Failure ]
 webkit.org/b/181752 storage/indexeddb/database-quota-private.html [ Skip ]
 webkit.org/b/181752 storage/indexeddb/database-quota.html [ Skip ]

Modified: trunk/LayoutTests/platform/wk2/TestExpectations (264485 => 264486)


--- trunk/LayoutTests/platform/wk2/TestExpectations	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/LayoutTests/platform/wk2/TestExpectations	2020-07-16 23:56:35 UTC (rev 264486)
@@ -657,8 +657,6 @@
 security/contentSecurityPolicy/image-with-blob-url-allowed-by-img-src-star-with-AllowContentSecurityPolicySourceStarToMatchAnyProtocol-enabled.html
 security/contentSecurityPolicy/image-with-blob-url-blocked-by-img-src-star.html
 security/contentSecurityPolicy/video-with-blob-url-allowed-by-media-src-star.html
-storage/indexeddb/structured-clone.html
-storage/indexeddb/structured-clone-private.html
 
 # WebKitTestRunner doesn't have eventSender.fireKeyboardEventsToElement
 platform/mac/fast/events/objc-keyboard-event-creation.html

Modified: trunk/LayoutTests/storage/indexeddb/resources/structured-clone.js (264485 => 264486)


--- trunk/LayoutTests/storage/indexeddb/resources/structured-clone.js	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/LayoutTests/storage/indexeddb/resources/structured-clone.js	2020-07-16 23:56:35 UTC (rev 264486)
@@ -5,7 +5,7 @@
 
 description("Test structured clone permutations in IndexedDB. File/FileList tests require DumpRenderTree.");
 
-if (self.eventSender) {
+if (self.eventSender && eventSender.beginDragWithFiles) {
     var fileInput = document.getElementById("fileInput");
     var fileRect = fileInput.getClientRects()[0];
     var targetX = fileRect.left + fileRect.width / 2;
@@ -34,9 +34,11 @@
         testBoolean,
         testNumber,
         testString,
+        testBigInt,
         testBooleanObject,
         testNumberObject,
         testStringObject,
+        testBigIntObject,
         testDateObject,
         testRegExpObject,
         testImageData,
@@ -43,9 +45,15 @@
         testBlob,
         testFile,
         testFileList,
+        testObject,
         testArray,
-        testObject,
-        testTypedArray
+        testTypedArray,
+        testArrays,
+        testMap,
+        testSet,
+        testGeometryTypes,
+        testRTCCertificate,
+        testCryptoKey
     ];
 
     function nextTest() {
@@ -122,7 +130,6 @@
     testValue(test_data, function(result) {
         self.result = result;
         shouldBeTrue("is(test_data, result)");
-        debug("");
         callback();
     });
 }
@@ -139,7 +146,6 @@
         shouldBeTrue("test_data !== result");
         shouldBe("result.toString()", "test_data.toString()");
         shouldBeTrue("is(test_data.valueOf(), result.valueOf())");
-        debug("");
         callback();
     });
 }
@@ -157,7 +163,6 @@
 function testBoolean(callback)
 {
     debug("Testing boolean primitives");
-    debug("");
     forEachWithCallback(testPrimitiveValue, ["true", "false"], callback);
 }
 
@@ -164,7 +169,6 @@
 function testBooleanObject(callback)
 {
     debug("Testing Boolean objects");
-    debug("");
     forEachWithCallback(testObjectWithValue, [
         "new Boolean(true)",
         "new Boolean(false)"
@@ -174,7 +178,6 @@
 function testString(callback)
 {
     debug("Testing string primitives");
-    debug("");
     forEachWithCallback(testPrimitiveValue, [
         "''",
         "'this is a sample string'",
@@ -185,7 +188,6 @@
 function testStringObject(callback)
 {
     debug("Testing String objects");
-    debug("");
     forEachWithCallback(testObjectWithValue, [
         "new String()",
         "new String('this is a sample string')",
@@ -196,7 +198,6 @@
 function testNumber(callback)
 {
     debug("Testing number primitives");
-    debug("");
     forEachWithCallback(testPrimitiveValue, [
         "NaN",
         "-Infinity",
@@ -221,7 +222,6 @@
 function testNumberObject(callback)
 {
     debug("Testing Number objects");
-    debug("");
     forEachWithCallback(testObjectWithValue, [
         "new Number(NaN)",
         "new Number(-Infinity)",
@@ -235,10 +235,45 @@
     ], callback);
 }
 
+function testBigInt(callback)
+{
+    debug("Testing BigInt primitives");
+    forEachWithCallback(testPrimitiveValue, [
+        "-12345678901234567890n",
+        "-1n",
+        "0n",
+        "1n",
+        "12345678901234567890n",
+    ], callback);
+}
+
+function testBigIntObject(callback)
+{
+    debug("Testing BigInt objects");
+    function testOneBigIntObject(string, callback) {
+        debug("Testing BigInt object: " + string);
+        var value = eval("value = (" + string + ")");
+        test_data = value;
+        testValue(test_data, function(result) {
+            self.result = result;
+            shouldBeEqualToString("typeof result", "bigint");
+            shouldBe("test_data.toString()", "result.toString()");
+            callback();
+        });
+    }
+    forEachWithCallback(testOneBigIntObject, [
+        "BigInt(-12345678901234567890)",
+        "BigInt(-1)",
+        "BigInt(0)",
+        "BigInt(1)",
+        "BigInt(-0)",
+        "BigInt('0x1fffffffffffff')"
+    ], callback);
+}
+
 function testDateObject(callback)
 {
     debug("Testing Date objects");
-    debug("");
     forEachWithCallback(testObjectWithValue, [
         "new Date(-1e13)",
         "new Date(-1e12)",
@@ -257,7 +292,6 @@
 function testRegExpObject(callback)
 {
     debug("Testing RegExp objects");
-    debug("");
     function testRegExp(string, callback) {
         debug("Testing RegExp: " + string);
         var value = eval("value = (" + string + ")");
@@ -353,8 +387,7 @@
 {
     debug("Testing Blob");
 
-    // FIXME: Blob, File, and FileList support is incomplete.
-    // http://crbug.com/108012
+    // FIXME: https://bugs.webkit.org/show_bug.cgi?id=214425
     debug("Skipping test");
     callback();
     return;
@@ -395,8 +428,7 @@
 {
     debug("Testing File");
 
-    // FIXME: Blob, File, and FileList support is incomplete.
-    // http://crbug.com/108012
+    // FIXME: eventSender.beginDragWithFiles is not supported.
     debug("Skipping test");
     callback();
     return;
@@ -415,8 +447,7 @@
 {
     debug("Testing FileList");
 
-    // FIXME: Blob, File, and FileList support is incomplete.
-    // http://crbug.com/108012
+    // FIXME: eventSender.beginDragWithFiles is not supported.
     debug("Skipping test");
     callback();
     return;
@@ -442,7 +473,8 @@
     });
 }
 
-function testArray(callback) {
+function testArray(callback) 
+{
     debug("Testing Array");
     evalAndLog("test_data = []");
     evalAndLog("test_data[0] = 'foo'");
@@ -465,7 +497,8 @@
     });
 }
 
-function testObject(callback) {
+function testObject(callback) 
+{
     debug("Testing Object");
     evalAndLog("test_data = []");
     evalAndLog("test_data[0] = 'foo'");
@@ -488,9 +521,9 @@
     });
 }
 
-function testTypedArray(callback) {
+function testTypedArray(callback) 
+{
     debug("Testing TypedArray");
-
     function testTypedArrayValue(string, callback) {
         evalAndLog("value = " + string);
         test_data = value;
@@ -502,7 +535,6 @@
             for (i = 0; i < test_data.length; ++i) {
                 shouldBeTrue("is(test_data[" + i + "], result[" + i + "])");
             }
-            debug("");
             callback();
         });
     }
@@ -521,11 +553,124 @@
     ], callback);
 }
 
+function testArrays(callback)
+{
+    debug("Testing Arrays");
+    evalAndLog("test_data = []");
+    evalAndLog("test_data[0] = []");
+    evalAndLog("test_data[1] = [1, 2, 3]");
+    evalAndLog("test_data[10] = Object.assign(['foo', 'bar'], {10: true, 11: false, 20: 123, 21: 456, 30: null})");
+    evalAndLog("test_data[11] = Object.assign(['foo', 'bar'], {a: true, b: false, foo: 123, bar: 456, '': null})");
+    testValue(test_data, function(result) {
+        self.result = result;
+        shouldBeTrue("test_data !== result");
+        shouldBe("typeof test_data", "typeof result");
+        shouldBeTrue("test_data.length === result.length");
+        Object.keys(test_data).forEach((key) => {
+            shouldBeTrue("arrayCompare(test_data[" + key + "], result[" + key + "])");
+        });
+        callback();
+    });
+}
+
+function testMap(callback)
+{
+    debug("Testing Map");
+    evalAndLog("test_data = new Map([[1,2],[3,4]])");
+    testValue(test_data, function(result) {
+        self.result = result;
+        shouldBe("typeof test_data", "typeof result");
+        shouldBe("test_data.size", "result.size");
+        Object.keys(test_data).forEach((key) => {
+            shouldBeTrue("test_data[" + key + "] === result[" + key + "]");
+        });
+        callback();
+    });
+}
+
+function testSet(callback)
+{
+    debug("Testing Set");
+    evalAndLog("test_data = new Set([1,2,3,4])");
+    testValue(test_data, function(result) {
+        self.result = result;
+        shouldBe("typeof test_data", "typeof result");
+        shouldBe("test_data.size", "result.size");
+        for (var element of test_data)
+            shouldBeTrue("result.has("+ element +")");
+        callback();
+    });
+}
+
+function testGeometryTypes(callback)
+{
+    debug("Testing geometry types");
+    function testOneGeometryType(string, callback) {
+        debug("Testing geometry type: " + string);
+        var value = eval("value = (" + string + ")");
+        test_data = value;
+        testValue(test_data, function(result) {
+            self.result = result;
+            shouldBeTrue("test_data !== result");
+            shouldBeEqualToString("typeof result", "object");
+            shouldBe("Object.prototype.toString.call(test_data)", "Object.prototype.toString.call(result)");
+            shouldBe("test_data.toString()", "result.toString()");
+            callback();
+        });
+    }
+    forEachWithCallback(testOneGeometryType, [
+        "new DOMMatrix()",
+        "new DOMMatrixReadOnly()",
+        "new DOMPoint()",
+        "new DOMPointReadOnly()",
+        "new DOMRect()",
+        "new DOMRectReadOnly()",
+        "new DOMQuad()"
+    ], callback);
+}
+
+function testRTCCertificate(callback)
+{
+    debug("Testing RTCCertificate");
+    evalAndLog("promise = RTCPeerConnection.generateCertificate({ name: 'RSASSA-PKCS1-v1_5', modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: 'SHA-256'})");
+    promise.then((test_data) => {
+        self.test_data = test_data;
+        testValue(test_data, function(result) {
+            self.result = result;
+            shouldBeTrue("test_data !== result");
+            shouldBeEqualToString("Object.prototype.toString.call(result)", "[object RTCCertificate]");
+            shouldBe("test_data.expires", "result.expires");
+            evalAndLog("dataFingerPrints = test_data.getFingerprints()");
+            evalAndLog("resultFingerPrints = result.getFingerprints()");
+            shouldBe("dataFingerPrints.length", "resultFingerPrints.length");
+            shouldBe("test_data.getFingerprints()[0].algorithm", "resultFingerPrints[0].algorithm");
+            shouldBe("test_data.getFingerprints()[0].value", "resultFingerPrints[0].value");
+            callback();
+        });
+    });
+}
+
+function testCryptoKey(callback)
+{
+    debug("Testing CryptoKey");
+    evalAndLog("promise = crypto.subtle.generateKey({ name: 'HMAC', hash: {name: 'SHA-512'}}, true, ['sign', 'verify']);");
+    promise.then((test_data) => {
+        self.test_data = test_data;
+        testValue(test_data, function(result) {
+            self.result = result;
+            shouldBe("typeof test_data", "typeof result");
+            shouldBe("test_data.type", "result.type");
+            shouldBe("test_data.extractable", "result.extractable");
+            shouldBe("test_data.algorithm.toString()", "result.algorithm.toString()");
+            shouldBeTrue("arrayCompare(test_data.usages, result.usages)");
+            callback();
+        });
+    });
+}
+
 function testBadTypes()
 {
-    debug("");
     debug("Test types that can't be cloned:");
-    debug("");
 
     evalAndLog("transaction = db.transaction('storeName', 'readwrite')");
     evalAndLog("store = transaction.objectStore('storeName')");
@@ -533,13 +678,14 @@
     transaction._onabort_ = unexpectedAbortCallback;
     transaction._oncomplete_ = finishJSTest;
 
-    debug("");
-    debug("Other _javascript_ object types:");
+    debug("Testing Error");
     evalAndExpectException("store.put(new Error, 'key')", "DOMException.DATA_CLONE_ERR");
+    debug("Testing Function");
     evalAndExpectException("store.put(new Function, 'key')", "DOMException.DATA_CLONE_ERR");
+    debug("Testing DOMException");
+    evalAndExpectException("store.put(new DOMException, 'key')", "DOMException.DATA_CLONE_ERR");
 
-    debug("");
-    debug("Other host object types:");
+    debug("Testing other host object types");
     evalAndExpectException("store.put(self, 'key')", "DOMException.DATA_CLONE_ERR");
     evalAndExpectException("store.put(document, 'key')", "DOMException.DATA_CLONE_ERR");
     evalAndExpectException("store.put(document.body, 'key')", "DOMException.DATA_CLONE_ERR");

Modified: trunk/LayoutTests/storage/indexeddb/structured-clone-expected.txt (264485 => 264486)


--- trunk/LayoutTests/storage/indexeddb/structured-clone-expected.txt	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/LayoutTests/storage/indexeddb/structured-clone-expected.txt	2020-07-16 23:56:35 UTC (rev 264486)
@@ -20,7 +20,6 @@
 store.get('key')
 PASS is(test_data, result) is true
 
-
 Testing: null
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -28,9 +27,7 @@
 store.get('key')
 PASS is(test_data, result) is true
 
-
 Testing boolean primitives
-
 Testing: true
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -37,7 +34,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: false
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -45,9 +41,7 @@
 store.get('key')
 PASS is(test_data, result) is true
 
-
 Testing number primitives
-
 Testing: NaN
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -54,7 +48,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -Infinity
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -61,7 +54,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -Number.MAX_VALUE
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -68,7 +60,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -0xffffffff
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -75,7 +66,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -0x80000000
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -82,7 +72,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -0x7fffffff
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -89,7 +78,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -1
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -96,7 +84,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -Number.MIN_VALUE
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -103,7 +90,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -0
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -110,7 +96,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 0
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -117,7 +102,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 1
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -124,7 +108,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: Number.MIN_VALUE
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -131,7 +114,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 0x7fffffff
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -138,7 +120,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 0x80000000
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -145,7 +126,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 0xffffffff
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -152,7 +132,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: Number.MAX_VALUE
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -159,7 +138,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: Infinity
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -167,9 +145,7 @@
 store.get('key')
 PASS is(test_data, result) is true
 
-
 Testing string primitives
-
 Testing: ''
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -176,7 +152,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 'this is a sample string'
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -183,7 +158,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 'null(\0)'
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -191,9 +165,39 @@
 store.get('key')
 PASS is(test_data, result) is true
 
+Testing BigInt primitives
+Testing: -12345678901234567890n
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS is(test_data, result) is true
+Testing: -1n
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS is(test_data, result) is true
+Testing: 0n
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS is(test_data, result) is true
+Testing: 1n
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS is(test_data, result) is true
+Testing: 12345678901234567890n
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS is(test_data, result) is true
 
 Testing Boolean objects
-
 Testing: new Boolean(true)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -204,7 +208,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Boolean(false)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -216,9 +219,7 @@
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
 
-
 Testing Number objects
-
 Testing: new Number(NaN)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -229,7 +230,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(-Infinity)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -240,7 +240,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(-Number.MAX_VALUE)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -251,7 +250,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(-Number.MIN_VALUE)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -262,7 +260,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(-0)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -273,7 +270,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(0)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -284,7 +280,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(Number.MIN_VALUE)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -295,7 +290,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(Number.MAX_VALUE)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -306,7 +300,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(Infinity)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -318,9 +311,7 @@
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
 
-
 Testing String objects
-
 Testing: new String()
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -331,7 +322,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new String('this is a sample string')
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -342,7 +332,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new String('null(\0)')
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -354,9 +343,51 @@
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
 
+Testing BigInt objects
+Testing BigInt object: BigInt(-12345678901234567890)
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
+Testing BigInt object: BigInt(-1)
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
+Testing BigInt object: BigInt(0)
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
+Testing BigInt object: BigInt(1)
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
+Testing BigInt object: BigInt(-0)
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
+Testing BigInt object: BigInt('0x1fffffffffffff')
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
 
 Testing Date objects
-
 Testing: new Date(-1e13)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -367,7 +398,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(-1e12)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -378,7 +408,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(-1e9)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -389,7 +418,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(-1e6)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -400,7 +428,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(-1e3)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -411,7 +438,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(0)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -422,7 +448,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(1e3)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -433,7 +458,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(1e6)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -444,7 +468,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(1e9)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -455,7 +478,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(1e12)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -466,7 +488,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(1e13)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -478,9 +499,7 @@
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
 
-
 Testing RegExp objects
-
 Testing RegExp: new RegExp()
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -588,6 +607,29 @@
 Testing FileList
 Skipping test
 
+Testing Object
+test_data = []
+test_data[0] = 'foo'
+test_data[1] = 'bar'
+test_data['a'] = true
+test_data['b'] = false
+test_data['foo'] = 123
+test_data['bar'] = 456
+test_data[''] = null
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS arrayCompare(Object.keys(result).sort(), Object.keys(test_data).sort()) is true
+PASS test_data["0"] is result["0"]
+PASS test_data["1"] is result["1"]
+PASS test_data["a"] is result["a"]
+PASS test_data["b"] is result["b"]
+PASS test_data["foo"] is result["foo"]
+PASS test_data["bar"] is result["bar"]
+PASS test_data[""] is result[""]
+
 Testing Array
 test_data = []
 test_data[0] = 'foo'
@@ -611,29 +653,6 @@
 PASS test_data[21] is result[21]
 PASS test_data[30] is result[30]
 
-Testing Object
-test_data = []
-test_data[0] = 'foo'
-test_data[1] = 'bar'
-test_data['a'] = true
-test_data['b'] = false
-test_data['foo'] = 123
-test_data['bar'] = 456
-test_data[''] = null
-transaction = db.transaction('storeName', 'readwrite')
-store = transaction.objectStore('storeName')
-store.put(value, 'key')
-store.get('key')
-PASS test_data !== result is true
-PASS arrayCompare(Object.keys(result).sort(), Object.keys(test_data).sort()) is true
-PASS test_data["0"] is result["0"]
-PASS test_data["1"] is result["1"]
-PASS test_data["a"] is result["a"]
-PASS test_data["b"] is result["b"]
-PASS test_data["foo"] is result["foo"]
-PASS test_data["bar"] is result["bar"]
-PASS test_data[""] is result[""]
-
 Testing TypedArray
 value = new Uint8Array([])
 transaction = db.transaction('storeName', 'readwrite')
@@ -643,7 +662,6 @@
 PASS test_data !== result is true
 PASS Object.prototype.toString.call(result) is Object.prototype.toString.call(test_data)
 PASS test_data.length === result.length is true
-
 value = new Uint8Array([0, 1, 254, 255])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -656,7 +674,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Uint16Array([0x0000, 0x0001, 0xFFFE, 0xFFFF])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -669,7 +686,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Uint32Array([0x00000000, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -682,7 +698,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Int8Array([0, 1, 254, 255])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -695,7 +710,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Int16Array([0x0000, 0x0001, 0xFFFE, 0xFFFF])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -708,7 +722,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Int32Array([0x00000000, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -721,7 +734,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Uint8ClampedArray([0, 1, 254, 255])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -734,7 +746,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Float32Array([-Infinity, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, Infinity, NaN])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -753,7 +764,6 @@
 PASS is(test_data[7], result[7]) is true
 PASS is(test_data[8], result[8]) is true
 PASS is(test_data[9], result[9]) is true
-
 value = new Float64Array([-Infinity, -Number.MAX_VALUE, -Number.MIN_VALUE, 0, Number.MIN_VALUE, Number.MAX_VALUE, Infinity, NaN])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -771,24 +781,157 @@
 PASS is(test_data[6], result[6]) is true
 PASS is(test_data[7], result[7]) is true
 
+Testing Arrays
+test_data = []
+test_data[0] = []
+test_data[1] = [1, 2, 3]
+test_data[10] = Object.assign(['foo', 'bar'], {10: true, 11: false, 20: 123, 21: 456, 30: null})
+test_data[11] = Object.assign(['foo', 'bar'], {a: true, b: false, foo: 123, bar: 456, '': null})
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof test_data is typeof result
+PASS test_data.length === result.length is true
+PASS arrayCompare(test_data[0], result[0]) is true
+PASS arrayCompare(test_data[1], result[1]) is true
+PASS arrayCompare(test_data[10], result[10]) is true
+PASS arrayCompare(test_data[11], result[11]) is true
 
+Testing Map
+test_data = new Map([[1,2],[3,4]])
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof test_data is typeof result
+PASS test_data.size is result.size
 
-Test types that can't be cloned:
+Testing Set
+test_data = new Set([1,2,3,4])
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof test_data is typeof result
+PASS test_data.size is result.size
+PASS result.has(1) is true
+PASS result.has(2) is true
+PASS result.has(3) is true
+PASS result.has(4) is true
 
+Testing geometry types
+Testing geometry type: new DOMMatrix()
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMMatrixReadOnly()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMPoint()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMPointReadOnly()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMRect()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMRectReadOnly()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMQuad()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
 
-Other _javascript_ object types:
+Testing RTCCertificate
+promise = RTCPeerConnection.generateCertificate({ name: 'RSASSA-PKCS1-v1_5', modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: 'SHA-256'})
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS Object.prototype.toString.call(result) is "[object RTCCertificate]"
+PASS test_data.expires is result.expires
+dataFingerPrints = test_data.getFingerprints()
+resultFingerPrints = result.getFingerprints()
+PASS dataFingerPrints.length is resultFingerPrints.length
+PASS test_data.getFingerprints()[0].algorithm is resultFingerPrints[0].algorithm
+PASS test_data.getFingerprints()[0].value is resultFingerPrints[0].value
+
+Testing CryptoKey
+promise = crypto.subtle.generateKey({ name: 'HMAC', hash: {name: 'SHA-512'}}, true, ['sign', 'verify']);
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof test_data is typeof result
+PASS test_data.type is result.type
+PASS test_data.extractable is result.extractable
+PASS test_data.algorithm.toString() is result.algorithm.toString()
+PASS arrayCompare(test_data.usages, result.usages) is true
+
+Test types that can't be cloned:
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+Testing Error
 Expecting exception from store.put(new Error, 'key')
 PASS Exception was thrown.
 PASS code is DOMException.DATA_CLONE_ERR
 Exception message: The object can not be cloned.
+Testing Function
 Expecting exception from store.put(new Function, 'key')
 PASS Exception was thrown.
 PASS code is DOMException.DATA_CLONE_ERR
 Exception message: The object can not be cloned.
-
-Other host object types:
+Testing DOMException
+Expecting exception from store.put(new DOMException, 'key')
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+Exception message: The object can not be cloned.
+Testing other host object types
 Expecting exception from store.put(self, 'key')
 PASS Exception was thrown.
 PASS code is DOMException.DATA_CLONE_ERR

Modified: trunk/LayoutTests/storage/indexeddb/structured-clone-private-expected.txt (264485 => 264486)


--- trunk/LayoutTests/storage/indexeddb/structured-clone-private-expected.txt	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/LayoutTests/storage/indexeddb/structured-clone-private-expected.txt	2020-07-16 23:56:35 UTC (rev 264486)
@@ -20,7 +20,6 @@
 store.get('key')
 PASS is(test_data, result) is true
 
-
 Testing: null
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -28,9 +27,7 @@
 store.get('key')
 PASS is(test_data, result) is true
 
-
 Testing boolean primitives
-
 Testing: true
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -37,7 +34,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: false
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -45,9 +41,7 @@
 store.get('key')
 PASS is(test_data, result) is true
 
-
 Testing number primitives
-
 Testing: NaN
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -54,7 +48,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -Infinity
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -61,7 +54,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -Number.MAX_VALUE
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -68,7 +60,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -0xffffffff
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -75,7 +66,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -0x80000000
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -82,7 +72,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -0x7fffffff
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -89,7 +78,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -1
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -96,7 +84,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -Number.MIN_VALUE
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -103,7 +90,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: -0
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -110,7 +96,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 0
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -117,7 +102,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 1
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -124,7 +108,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: Number.MIN_VALUE
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -131,7 +114,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 0x7fffffff
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -138,7 +120,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 0x80000000
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -145,7 +126,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 0xffffffff
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -152,7 +132,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: Number.MAX_VALUE
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -159,7 +138,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: Infinity
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -167,9 +145,7 @@
 store.get('key')
 PASS is(test_data, result) is true
 
-
 Testing string primitives
-
 Testing: ''
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -176,7 +152,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 'this is a sample string'
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -183,7 +158,6 @@
 store.put(value, 'key')
 store.get('key')
 PASS is(test_data, result) is true
-
 Testing: 'null(\0)'
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -191,9 +165,39 @@
 store.get('key')
 PASS is(test_data, result) is true
 
+Testing BigInt primitives
+Testing: -12345678901234567890n
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS is(test_data, result) is true
+Testing: -1n
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS is(test_data, result) is true
+Testing: 0n
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS is(test_data, result) is true
+Testing: 1n
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS is(test_data, result) is true
+Testing: 12345678901234567890n
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS is(test_data, result) is true
 
 Testing Boolean objects
-
 Testing: new Boolean(true)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -204,7 +208,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Boolean(false)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -216,9 +219,7 @@
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
 
-
 Testing Number objects
-
 Testing: new Number(NaN)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -229,7 +230,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(-Infinity)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -240,7 +240,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(-Number.MAX_VALUE)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -251,7 +250,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(-Number.MIN_VALUE)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -262,7 +260,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(-0)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -273,7 +270,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(0)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -284,7 +280,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(Number.MIN_VALUE)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -295,7 +290,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(Number.MAX_VALUE)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -306,7 +300,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Number(Infinity)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -318,9 +311,7 @@
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
 
-
 Testing String objects
-
 Testing: new String()
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -331,7 +322,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new String('this is a sample string')
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -342,7 +332,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new String('null(\0)')
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -354,9 +343,51 @@
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
 
+Testing BigInt objects
+Testing BigInt object: BigInt(-12345678901234567890)
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
+Testing BigInt object: BigInt(-1)
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
+Testing BigInt object: BigInt(0)
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
+Testing BigInt object: BigInt(1)
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
+Testing BigInt object: BigInt(-0)
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
+Testing BigInt object: BigInt('0x1fffffffffffff')
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof result is "bigint"
+PASS test_data.toString() is result.toString()
 
 Testing Date objects
-
 Testing: new Date(-1e13)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -367,7 +398,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(-1e12)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -378,7 +408,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(-1e9)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -389,7 +418,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(-1e6)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -400,7 +428,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(-1e3)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -411,7 +438,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(0)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -422,7 +448,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(1e3)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -433,7 +458,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(1e6)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -444,7 +468,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(1e9)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -455,7 +478,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(1e12)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -466,7 +488,6 @@
 PASS test_data !== result is true
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
-
 Testing: new Date(1e13)
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -478,9 +499,7 @@
 PASS result.toString() is test_data.toString()
 PASS is(test_data.valueOf(), result.valueOf()) is true
 
-
 Testing RegExp objects
-
 Testing RegExp: new RegExp()
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -588,6 +607,29 @@
 Testing FileList
 Skipping test
 
+Testing Object
+test_data = []
+test_data[0] = 'foo'
+test_data[1] = 'bar'
+test_data['a'] = true
+test_data['b'] = false
+test_data['foo'] = 123
+test_data['bar'] = 456
+test_data[''] = null
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS arrayCompare(Object.keys(result).sort(), Object.keys(test_data).sort()) is true
+PASS test_data["0"] is result["0"]
+PASS test_data["1"] is result["1"]
+PASS test_data["a"] is result["a"]
+PASS test_data["b"] is result["b"]
+PASS test_data["foo"] is result["foo"]
+PASS test_data["bar"] is result["bar"]
+PASS test_data[""] is result[""]
+
 Testing Array
 test_data = []
 test_data[0] = 'foo'
@@ -611,29 +653,6 @@
 PASS test_data[21] is result[21]
 PASS test_data[30] is result[30]
 
-Testing Object
-test_data = []
-test_data[0] = 'foo'
-test_data[1] = 'bar'
-test_data['a'] = true
-test_data['b'] = false
-test_data['foo'] = 123
-test_data['bar'] = 456
-test_data[''] = null
-transaction = db.transaction('storeName', 'readwrite')
-store = transaction.objectStore('storeName')
-store.put(value, 'key')
-store.get('key')
-PASS test_data !== result is true
-PASS arrayCompare(Object.keys(result).sort(), Object.keys(test_data).sort()) is true
-PASS test_data["0"] is result["0"]
-PASS test_data["1"] is result["1"]
-PASS test_data["a"] is result["a"]
-PASS test_data["b"] is result["b"]
-PASS test_data["foo"] is result["foo"]
-PASS test_data["bar"] is result["bar"]
-PASS test_data[""] is result[""]
-
 Testing TypedArray
 value = new Uint8Array([])
 transaction = db.transaction('storeName', 'readwrite')
@@ -643,7 +662,6 @@
 PASS test_data !== result is true
 PASS Object.prototype.toString.call(result) is Object.prototype.toString.call(test_data)
 PASS test_data.length === result.length is true
-
 value = new Uint8Array([0, 1, 254, 255])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -656,7 +674,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Uint16Array([0x0000, 0x0001, 0xFFFE, 0xFFFF])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -669,7 +686,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Uint32Array([0x00000000, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -682,7 +698,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Int8Array([0, 1, 254, 255])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -695,7 +710,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Int16Array([0x0000, 0x0001, 0xFFFE, 0xFFFF])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -708,7 +722,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Int32Array([0x00000000, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -721,7 +734,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Uint8ClampedArray([0, 1, 254, 255])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -734,7 +746,6 @@
 PASS is(test_data[1], result[1]) is true
 PASS is(test_data[2], result[2]) is true
 PASS is(test_data[3], result[3]) is true
-
 value = new Float32Array([-Infinity, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, Infinity, NaN])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -753,7 +764,6 @@
 PASS is(test_data[7], result[7]) is true
 PASS is(test_data[8], result[8]) is true
 PASS is(test_data[9], result[9]) is true
-
 value = new Float64Array([-Infinity, -Number.MAX_VALUE, -Number.MIN_VALUE, 0, Number.MIN_VALUE, Number.MAX_VALUE, Infinity, NaN])
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
@@ -771,24 +781,157 @@
 PASS is(test_data[6], result[6]) is true
 PASS is(test_data[7], result[7]) is true
 
+Testing Arrays
+test_data = []
+test_data[0] = []
+test_data[1] = [1, 2, 3]
+test_data[10] = Object.assign(['foo', 'bar'], {10: true, 11: false, 20: 123, 21: 456, 30: null})
+test_data[11] = Object.assign(['foo', 'bar'], {a: true, b: false, foo: 123, bar: 456, '': null})
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof test_data is typeof result
+PASS test_data.length === result.length is true
+PASS arrayCompare(test_data[0], result[0]) is true
+PASS arrayCompare(test_data[1], result[1]) is true
+PASS arrayCompare(test_data[10], result[10]) is true
+PASS arrayCompare(test_data[11], result[11]) is true
 
+Testing Map
+test_data = new Map([[1,2],[3,4]])
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof test_data is typeof result
+PASS test_data.size is result.size
 
-Test types that can't be cloned:
+Testing Set
+test_data = new Set([1,2,3,4])
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof test_data is typeof result
+PASS test_data.size is result.size
+PASS result.has(1) is true
+PASS result.has(2) is true
+PASS result.has(3) is true
+PASS result.has(4) is true
 
+Testing geometry types
+Testing geometry type: new DOMMatrix()
 transaction = db.transaction('storeName', 'readwrite')
 store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMMatrixReadOnly()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMPoint()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMPointReadOnly()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMRect()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMRectReadOnly()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
+Testing geometry type: new DOMQuad()
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS typeof result is "object"
+PASS Object.prototype.toString.call(test_data) is Object.prototype.toString.call(result)
+PASS test_data.toString() is result.toString()
 
-Other _javascript_ object types:
+Testing RTCCertificate
+promise = RTCPeerConnection.generateCertificate({ name: 'RSASSA-PKCS1-v1_5', modulusLength: 2048, publicExponent: new Uint8Array([1, 0, 1]), hash: 'SHA-256'})
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS test_data !== result is true
+PASS Object.prototype.toString.call(result) is "[object RTCCertificate]"
+PASS test_data.expires is result.expires
+dataFingerPrints = test_data.getFingerprints()
+resultFingerPrints = result.getFingerprints()
+PASS dataFingerPrints.length is resultFingerPrints.length
+PASS test_data.getFingerprints()[0].algorithm is resultFingerPrints[0].algorithm
+PASS test_data.getFingerprints()[0].value is resultFingerPrints[0].value
+
+Testing CryptoKey
+promise = crypto.subtle.generateKey({ name: 'HMAC', hash: {name: 'SHA-512'}}, true, ['sign', 'verify']);
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+store.put(value, 'key')
+store.get('key')
+PASS typeof test_data is typeof result
+PASS test_data.type is result.type
+PASS test_data.extractable is result.extractable
+PASS test_data.algorithm.toString() is result.algorithm.toString()
+PASS arrayCompare(test_data.usages, result.usages) is true
+
+Test types that can't be cloned:
+transaction = db.transaction('storeName', 'readwrite')
+store = transaction.objectStore('storeName')
+Testing Error
 Expecting exception from store.put(new Error, 'key')
 PASS Exception was thrown.
 PASS code is DOMException.DATA_CLONE_ERR
 Exception message: The object can not be cloned.
+Testing Function
 Expecting exception from store.put(new Function, 'key')
 PASS Exception was thrown.
 PASS code is DOMException.DATA_CLONE_ERR
 Exception message: The object can not be cloned.
-
-Other host object types:
+Testing DOMException
+Expecting exception from store.put(new DOMException, 'key')
+PASS Exception was thrown.
+PASS code is DOMException.DATA_CLONE_ERR
+Exception message: The object can not be cloned.
+Testing other host object types
 Expecting exception from store.put(self, 'key')
 PASS Exception was thrown.
 PASS code is DOMException.DATA_CLONE_ERR

Modified: trunk/Source/WebCore/ChangeLog (264485 => 264486)


--- trunk/Source/WebCore/ChangeLog	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/Source/WebCore/ChangeLog	2020-07-16 23:56:35 UTC (rev 264486)
@@ -1,3 +1,45 @@
+2020-07-16  Sihui Liu  <[email protected]>
+
+        IDB serialization of some DOM object types crashes the Networking process due to incorrect global object type (WPT IndexedDB/structured-clone.any tests fail)
+        https://bugs.webkit.org/show_bug.cgi?id=210735
+        <rdar://problem/62045703>
+
+        Reviewed by Yusuke Suzuki.
+
+        In r239746, IDB went back to use JSGlobalObject for serialization and deserialization. However, in our current
+        implementation, there is a strong assumption that DOM JS objects are tied to JSDOMGlobalObject, which is 
+        derived from JSGlobalObject. For example, in SerializedScriptValue.cpp, we cast the global object to
+        JSDOMGlobalObject in many places. 
+
+        We recently notice this issue when we enable some wpt test, which has been disabled since it was imported as 
+        some types were not supported. The test fails as DOMMatrix object requires its global object to be
+        JSDOMGlobalObject. To fix this, introduce a new Class JSIDBSerializationGlobalObject, derived from 
+        JSDOMGlobalObject, and use it for IDB serialization.
+
+        Tests: LayoutTests/storage/indexeddb/structured-clone.html
+               LayoutTests/storage/indexeddb/structured-clone-private.html
+
+        * Modules/indexeddb/server/IDBSerializationContext.cpp:
+        (WebCore::IDBServer::IDBSerializationContext::initializeVM):
+        * Modules/indexeddb/server/IDBSerializationContext.h:
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSDOMGlobalObject.cpp:
+        (WebCore::JSDOMGlobalObject::scriptExecutionContext const):
+        * bindings/js/JSIDBSerializationGlobalObject.cpp: Added.
+        (WebCore::JSIDBSerializationGlobalObject::JSIDBSerializationGlobalObject):
+        (WebCore::JSIDBSerializationGlobalObject::create):
+        (WebCore::JSIDBSerializationGlobalObject::finishCreation):
+        (WebCore::JSIDBSerializationGlobalObject::subspaceForImpl):
+        (WebCore::JSIDBSerializationGlobalObject::destroy):
+        * bindings/js/JSIDBSerializationGlobalObject.h: Added.
+        * bindings/js/WebCoreJSClientData.cpp:
+        (WebCore::JSVMClientData::JSVMClientData):
+        * bindings/js/WebCoreJSClientData.h:
+        (WebCore::JSVMClientData::idbSerializationSpace):
+        * dom/EmptyScriptExecutionContext.h: Added.
+        * worklets/WorkletScriptController.h:
+
 2020-07-16  Eric Carlson  <[email protected]>
 
         Use AVRoutePickerView when available for choosing AirPlay devices

Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBSerializationContext.cpp (264485 => 264486)


--- trunk/Source/WebCore/Modules/indexeddb/server/IDBSerializationContext.cpp	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBSerializationContext.cpp	2020-07-16 23:56:35 UTC (rev 264486)
@@ -26,6 +26,8 @@
 #include "config.h"
 #include "IDBSerializationContext.h"
 
+#include "DOMWrapperWorld.h"
+#include "WebCoreJSClientData.h"
 #include <_javascript_Core/JSObjectInlines.h>
 #include <pal/SessionID.h>
 
@@ -76,9 +78,11 @@
 
     ASSERT(!m_globalObject);
     m_vm = JSC::VM::create();
+    m_vm->heap.acquireAccess();
+    JSVMClientData::initNormalWorld(m_vm.get());
 
     JSC::JSLockHolder locker(m_vm.get());
-    m_globalObject.set(*m_vm, JSC::JSGlobalObject::create(*m_vm, JSC::JSGlobalObject::createStructure(*m_vm, JSC::jsNull())));
+    m_globalObject.set(*m_vm, JSIDBSerializationGlobalObject::create(*m_vm, JSIDBSerializationGlobalObject::createStructure(*m_vm, JSC::jsNull()), normalWorld(*m_vm)));
 }
 
 JSC::VM& IDBSerializationContext::vm()

Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBSerializationContext.h (264485 => 264486)


--- trunk/Source/WebCore/Modules/indexeddb/server/IDBSerializationContext.h	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBSerializationContext.h	2020-07-16 23:56:35 UTC (rev 264486)
@@ -27,6 +27,7 @@
 
 #if ENABLE(INDEXED_DATABASE)
 
+#include "JSIDBSerializationGlobalObject.h"
 #include <_javascript_Core/StrongInlines.h>
 #include <_javascript_Core/StructureInlines.h>
 #include <pal/SessionID.h>
@@ -54,7 +55,7 @@
     void initializeVM();
 
     RefPtr<JSC::VM> m_vm;
-    JSC::Strong<JSC::JSGlobalObject> m_globalObject;
+    JSC::Strong<JSIDBSerializationGlobalObject> m_globalObject;
     PAL::SessionID m_sessionID;
 };
 

Modified: trunk/Source/WebCore/Sources.txt (264485 => 264486)


--- trunk/Source/WebCore/Sources.txt	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/Source/WebCore/Sources.txt	2020-07-16 23:56:35 UTC (rev 264486)
@@ -520,6 +520,7 @@
 bindings/js/JSIDBObjectStoreCustom.cpp
 bindings/js/JSIDBRequestCustom.cpp
 bindings/js/JSIDBTransactionCustom.cpp
+bindings/js/JSIDBSerializationGlobalObject.cpp
 bindings/js/JSImageDataCustom.cpp
 bindings/js/JSIntersectionObserverEntryCustom.cpp
 bindings/js/JSLazyEventListener.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (264485 => 264486)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-07-16 23:56:35 UTC (rev 264486)
@@ -2693,6 +2693,8 @@
 		9382AAB40D8C386100F357A6 /* NodeWithIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 9382AAB10D8C386100F357A6 /* NodeWithIndex.h */; };
 		9382DF5810A8D5C900925652 /* ColorSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = 9382DF5710A8D5C900925652 /* ColorSpace.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		938430B42475DE40003F9617 /* DictationContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 938430B22475DE3F003F9617 /* DictationContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		93849C1F24BE404B00448D5A /* EmptyScriptExecutionContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 93849C1E24BE404A00448D5A /* EmptyScriptExecutionContext.h */; };
+		93849C2324BEDD8900448D5A /* JSIDBSerializationGlobalObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 93849C2124BEDD8800448D5A /* JSIDBSerializationGlobalObject.h */; };
 		938E65F109F09840008A48EC /* JSHTMLElementWrapperFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 938E65F009F09840008A48EC /* JSHTMLElementWrapperFactory.h */; };
 		938E666209F09B87008A48EC /* JSHTMLCanvasElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 938E666109F09B87008A48EC /* JSHTMLCanvasElement.h */; };
 		9391A991162746CB00297330 /* ScrollingCoordinatorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 9391A990162746CB00297330 /* ScrollingCoordinatorMac.h */; };
@@ -10969,6 +10971,9 @@
 		9382AAB10D8C386100F357A6 /* NodeWithIndex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeWithIndex.h; sourceTree = "<group>"; };
 		9382DF5710A8D5C900925652 /* ColorSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColorSpace.h; sourceTree = "<group>"; };
 		938430B22475DE3F003F9617 /* DictationContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DictationContext.h; sourceTree = "<group>"; };
+		93849C1624BE12E500448D5A /* JSIDBSerializationGlobalObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSIDBSerializationGlobalObject.cpp; sourceTree = "<group>"; };
+		93849C1E24BE404A00448D5A /* EmptyScriptExecutionContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EmptyScriptExecutionContext.h; sourceTree = "<group>"; };
+		93849C2124BEDD8800448D5A /* JSIDBSerializationGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSIDBSerializationGlobalObject.h; sourceTree = "<group>"; };
 		938E65F009F09840008A48EC /* JSHTMLElementWrapperFactory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = JSHTMLElementWrapperFactory.h; path = DerivedSources/WebCore/JSHTMLElementWrapperFactory.h; sourceTree = BUILT_PRODUCTS_DIR; };
 		938E65F609F0985D008A48EC /* JSHTMLElementWrapperFactory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = JSHTMLElementWrapperFactory.cpp; path = DerivedSources/WebCore/JSHTMLElementWrapperFactory.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
 		938E662509F09956008A48EC /* HTMLCanvasElement.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = HTMLCanvasElement.idl; sourceTree = "<group>"; };
@@ -25998,6 +26003,8 @@
 				8F934D841189F1EE00508D5D /* JSExecState.cpp */,
 				8F934D831189F1EE00508D5D /* JSExecState.h */,
 				B56576E417DA599F00A56BDC /* JSExecStateInstrumentation.h */,
+				93849C1624BE12E500448D5A /* JSIDBSerializationGlobalObject.cpp */,
+				93849C2124BEDD8800448D5A /* JSIDBSerializationGlobalObject.h */,
 				E3C9AEC92113147400419B92 /* JSMicrotaskCallback.h */,
 				93B70D4F09EB0C7C009D8468 /* JSPluginElementFunctions.cpp */,
 				93B70D5009EB0C7C009D8468 /* JSPluginElementFunctions.h */,
@@ -28926,6 +28933,7 @@
 				4FAB48641643A66D00F70C07 /* ElementRareData.cpp */,
 				637B7ADE0E8767B800E32194 /* ElementRareData.h */,
 				E4D58EBA17B8F12800CBDCA8 /* ElementTraversal.h */,
+				93849C1E24BE404A00448D5A /* EmptyScriptExecutionContext.h */,
 				2ECF7ADE10162B5800427DE7 /* ErrorEvent.cpp */,
 				2ECF7ADF10162B5800427DE7 /* ErrorEvent.h */,
 				2ECF7AE010162B5800427DE7 /* ErrorEvent.idl */,
@@ -30680,6 +30688,7 @@
 				B25599A50D00D8BA00BB825C /* EmptyClients.h in Headers */,
 				414DEDE71F9FE91E0047C40D /* EmptyFrameLoaderClient.h in Headers */,
 				515BE1901D54F5FB00DD7C68 /* EmptyGamepadProvider.h in Headers */,
+				93849C1F24BE404B00448D5A /* EmptyScriptExecutionContext.h in Headers */,
 				7C77C3D71DEF850A00A50BFA /* EndingType.h in Headers */,
 				F403E7872363B58C00044550 /* EnterKeyHint.h in Headers */,
 				1D2F8E042344751600993B68 /* EnterPictureInPictureEvent.h in Headers */,
@@ -31679,6 +31688,7 @@
 				C585A68D11D4FB08004C3E4B /* JSIDBKeyRange.h in Headers */,
 				C585A68F11D4FB08004C3E4B /* JSIDBObjectStore.h in Headers */,
 				C585A69111D4FB08004C3E4B /* JSIDBRequest.h in Headers */,
+				93849C2324BEDD8900448D5A /* JSIDBSerializationGlobalObject.h in Headers */,
 				B6566270120B1227006EA85C /* JSIDBTransaction.h in Headers */,
 				838EF53C1DC14A7C008F0C39 /* JSIDBTransactionMode.h in Headers */,
 				269239961505E1AA009E57FC /* JSIDBVersionChangeEvent.h in Headers */,

Modified: trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp (264485 => 264486)


--- trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp	2020-07-16 23:56:35 UTC (rev 264486)
@@ -32,6 +32,7 @@
 #include "JSDOMPromiseDeferred.h"
 #include "JSDOMWindow.h"
 #include "JSEventListener.h"
+#include "JSIDBSerializationGlobalObject.h"
 #include "JSMediaStream.h"
 #include "JSMediaStreamTrack.h"
 #include "JSRTCIceCandidate.h"
@@ -170,6 +171,10 @@
     if (inherits<JSWorkletGlobalScopeBase>(vm()))
         return jsCast<const JSWorkletGlobalScopeBase*>(this)->scriptExecutionContext();
 #endif
+#if ENABLE(INDEXED_DATABASE)
+    if (inherits<JSIDBSerializationGlobalObject>(vm()))
+        return jsCast<const JSIDBSerializationGlobalObject*>(this)->scriptExecutionContext();
+#endif
     dataLog("Unexpected global object: ", JSValue(this), "\n");
     RELEASE_ASSERT_NOT_REACHED();
     return nullptr;

Added: trunk/Source/WebCore/bindings/js/JSIDBSerializationGlobalObject.cpp (0 => 264486)


--- trunk/Source/WebCore/bindings/js/JSIDBSerializationGlobalObject.cpp	                        (rev 0)
+++ trunk/Source/WebCore/bindings/js/JSIDBSerializationGlobalObject.cpp	2020-07-16 23:56:35 UTC (rev 264486)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSIDBSerializationGlobalObject.h"
+
+#include "WebCoreJSClientData.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+namespace WebCore {
+
+using namespace JSC;
+
+const ClassInfo JSIDBSerializationGlobalObject::s_info = { "JSIDBSerializationGlobalObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSIDBSerializationGlobalObject) };
+
+inline JSIDBSerializationGlobalObject::JSIDBSerializationGlobalObject(VM& vm, Structure* structure, Ref<DOMWrapperWorld>&& impl)
+    : Base(vm, structure, WTFMove(impl))
+    , m_scriptExecutionContext(EmptyScriptExecutionContext::create(vm))
+{
+}
+
+JSIDBSerializationGlobalObject* JSIDBSerializationGlobalObject::create(VM& vm, Structure* structure, Ref<DOMWrapperWorld>&& impl)
+{
+    JSIDBSerializationGlobalObject* ptr =  new (NotNull, allocateCell<JSIDBSerializationGlobalObject>(vm.heap)) JSIDBSerializationGlobalObject(vm, structure, WTFMove(impl));
+    ptr->finishCreation(vm);
+    return ptr;
+}
+
+void JSIDBSerializationGlobalObject::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+}
+
+IsoSubspace* JSIDBSerializationGlobalObject::subspaceForImpl(VM& vm)
+{
+    return &static_cast<JSVMClientData*>(vm.clientData)->idbSerializationSpace();
+}
+
+void JSIDBSerializationGlobalObject::destroy(JSCell* cell)
+{
+    static_cast<JSIDBSerializationGlobalObject*>(cell)->JSIDBSerializationGlobalObject::~JSIDBSerializationGlobalObject();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
+

Added: trunk/Source/WebCore/bindings/js/JSIDBSerializationGlobalObject.h (0 => 264486)


--- trunk/Source/WebCore/bindings/js/JSIDBSerializationGlobalObject.h	                        (rev 0)
+++ trunk/Source/WebCore/bindings/js/JSIDBSerializationGlobalObject.h	2020-07-16 23:56:35 UTC (rev 264486)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "EmptyScriptExecutionContext.h"
+#include "JSDOMGlobalObject.h"
+
+namespace WebCore {
+
+class JSIDBSerializationGlobalObject final : public JSDOMGlobalObject {
+public:
+    using Base = JSDOMGlobalObject;
+    static JSIDBSerializationGlobalObject* create(JSC::VM&, JSC::Structure*, Ref<DOMWrapperWorld>&&);
+
+    template<typename, JSC::SubspaceAccess mode>
+    static JSC::IsoSubspace* subspaceFor(JSC::VM& vm)
+    {
+        if constexpr (mode == JSC::SubspaceAccess::Concurrently)
+            return nullptr;
+        return subspaceForImpl(vm);
+    }
+    static JSC::IsoSubspace* subspaceForImpl(JSC::VM&);
+
+    DECLARE_INFO;
+    static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSValue prototype)
+    {
+        return JSC::Structure::create(vm, 0, prototype, JSC::TypeInfo(JSC::GlobalObjectType, StructureFlags), info());
+    }
+    static void destroy(JSC::JSCell*);
+
+    ScriptExecutionContext* scriptExecutionContext() const { return m_scriptExecutionContext.ptr(); }
+
+private:
+    JSIDBSerializationGlobalObject(JSC::VM&, JSC::Structure*, Ref<DOMWrapperWorld>&&);
+    void finishCreation(JSC::VM&);
+
+    Ref<EmptyScriptExecutionContext> m_scriptExecutionContext;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
+

Modified: trunk/Source/WebCore/bindings/js/WebCoreJSClientData.cpp (264485 => 264486)


--- trunk/Source/WebCore/bindings/js/WebCoreJSClientData.cpp	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/Source/WebCore/bindings/js/WebCoreJSClientData.cpp	2020-07-16 23:56:35 UTC (rev 264486)
@@ -33,6 +33,7 @@
 #include "JSDOMWindow.h"
 #include "JSDOMWindowProperties.h"
 #include "JSDedicatedWorkerGlobalScope.h"
+#include "JSIDBSerializationGlobalObject.h"
 #include "JSPaintWorkletGlobalScope.h"
 #include "JSRemoteDOMWindow.h"
 #include "JSServiceWorkerGlobalScope.h"
@@ -71,6 +72,9 @@
     , m_heapCellTypeForJSPaintWorkletGlobalScope(JSC::IsoHeapCellType::create<JSPaintWorkletGlobalScope>())
     , m_heapCellTypeForJSWorkletGlobalScope(JSC::IsoHeapCellType::create<JSWorkletGlobalScope>())
 #endif
+#if ENABLE(INDEXED_DATABASE)
+    , m_heapCellTypeForJSIDBSerializationGlobalObject(JSC::IsoHeapCellType::create<JSIDBSerializationGlobalObject>())
+#endif
     , m_domBuiltinConstructorSpace ISO_SUBSPACE_INIT(vm.heap, vm.cellHeapCellType.get(), JSDOMBuiltinConstructorBase)
     , m_domConstructorSpace ISO_SUBSPACE_INIT(vm.heap, vm.cellHeapCellType.get(), JSDOMConstructorBase)
     , m_domWindowPropertiesSpace ISO_SUBSPACE_INIT(vm.heap, vm.cellHeapCellType.get(), JSDOMWindowProperties)
@@ -78,6 +82,9 @@
     , m_runtimeMethodSpace ISO_SUBSPACE_INIT(vm.heap, vm.cellHeapCellType.get(), RuntimeMethod) // Hash:0xf70c4a85
     , m_runtimeObjectSpace ISO_SUBSPACE_INIT(vm.heap, m_runtimeObjectHeapCellType.get(), JSC::Bindings::RuntimeObject)
     , m_windowProxySpace ISO_SUBSPACE_INIT(vm.heap, m_windowProxyHeapCellType.get(), JSWindowProxy)
+#if ENABLE(INDEXED_DATABASE)
+    , m_idbSerializationSpace ISO_SUBSPACE_INIT(vm.heap, m_heapCellTypeForJSIDBSerializationGlobalObject.get(), JSIDBSerializationGlobalObject)
+#endif
     , m_subspaces(makeUnique<DOMIsoSubspaces>())
 {
 }

Modified: trunk/Source/WebCore/bindings/js/WebCoreJSClientData.h (264485 => 264486)


--- trunk/Source/WebCore/bindings/js/WebCoreJSClientData.h	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/Source/WebCore/bindings/js/WebCoreJSClientData.h	2020-07-16 23:56:35 UTC (rev 264486)
@@ -68,7 +68,8 @@
     JSC::IsoSubspace& runtimeMethodSpace() { return m_runtimeMethodSpace; }
     JSC::IsoSubspace& runtimeObjectSpace() { return m_runtimeObjectSpace; }
     JSC::IsoSubspace& windowProxySpace() { return m_windowProxySpace; }
-    
+    JSC::IsoSubspace& idbSerializationSpace() { return m_idbSerializationSpace; }
+
     Vector<JSC::IsoSubspace*>& outputConstraintSpaces() { return m_outputConstraintSpaces; }
 
     template<typename Func>
@@ -102,6 +103,9 @@
     std::unique_ptr<JSC::HeapCellType> m_heapCellTypeForJSPaintWorkletGlobalScope;
     std::unique_ptr<JSC::HeapCellType> m_heapCellTypeForJSWorkletGlobalScope;
 #endif
+#if ENABLE(INDEXED_DATABASE)
+    std::unique_ptr<JSC::HeapCellType> m_heapCellTypeForJSIDBSerializationGlobalObject;
+#endif
 private:
     JSC::IsoSubspace m_domBuiltinConstructorSpace;
     JSC::IsoSubspace m_domConstructorSpace;
@@ -110,6 +114,9 @@
     JSC::IsoSubspace m_runtimeMethodSpace;
     JSC::IsoSubspace m_runtimeObjectSpace;
     JSC::IsoSubspace m_windowProxySpace;
+#if ENABLE(INDEXED_DATABASE)
+    JSC::IsoSubspace m_idbSerializationSpace;
+#endif
     std::unique_ptr<DOMIsoSubspaces> m_subspaces;
     Vector<JSC::IsoSubspace*> m_outputConstraintSpaces;
 };

Added: trunk/Source/WebCore/dom/EmptyScriptExecutionContext.h (0 => 264486)


--- trunk/Source/WebCore/dom/EmptyScriptExecutionContext.h	                        (rev 0)
+++ trunk/Source/WebCore/dom/EmptyScriptExecutionContext.h	2020-07-16 23:56:35 UTC (rev 264486)
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "EventLoop.h"
+#include "Microtasks.h"
+#include "ReferrerPolicy.h"
+#include "ScriptExecutionContext.h"
+#include "SecurityOrigin.h"
+
+#include <wtf/IsoMalloc.h>
+
+namespace WebCore {
+
+class EmptyScriptExecutionContext final : public RefCounted<EmptyScriptExecutionContext>, public ScriptExecutionContext {
+public:
+    static Ref<EmptyScriptExecutionContext> create(JSC::VM& vm)
+    {
+        return adoptRef(*new EmptyScriptExecutionContext(vm));
+    }
+
+    bool isSecureContext() const final { return false; }
+    bool isJSExecutionForbidden() const final { return false; }
+    EventLoopTaskGroup& eventLoop() final
+    {
+        ASSERT_NOT_REACHED();
+        return *m_eventLoopTaskGroup;
+    }
+    const URL& url() const final { return m_url; }
+    URL completeURL(const String&, ForceUTF8 = ForceUTF8::No) const final { return { }; };
+    String userAgent(const URL&) const final { return emptyString(); }
+    ReferrerPolicy referrerPolicy() const final { return ReferrerPolicy::EmptyString; }
+
+    void disableEval(const String&) final { };
+    void disableWebAssembly(const String&) final { };
+
+#if ENABLE(INDEXED_DATABASE)
+    IDBClient::IDBConnectionProxy* idbConnectionProxy() final { return nullptr; }
+#endif
+    SocketProvider* socketProvider() final { return nullptr; }
+
+    void addConsoleMessage(std::unique_ptr<Inspector::ConsoleMessage>&&) final { }
+    void addConsoleMessage(MessageSource, MessageLevel, const String&, unsigned long) final { };
+
+    SecurityOrigin& topOrigin() const final { return m_origin.get(); };
+
+    void postTask(Task&&) final { ASSERT_NOT_REACHED(); }
+    EventTarget* errorEventTarget() final { return nullptr; };
+
+#if ENABLE(WEB_CRYPTO)
+    bool wrapCryptoKey(const Vector<uint8_t>&, Vector<uint8_t>&) final { return false; }
+    bool unwrapCryptoKey(const Vector<uint8_t>&, Vector<uint8_t>&) final { return false; }
+#endif
+
+    using RefCounted::ref;
+    using RefCounted::deref;
+
+private:
+    EmptyScriptExecutionContext(JSC::VM& vm)
+        : m_origin(SecurityOrigin::createUnique())
+        , m_eventLoop(EmptyEventLoop::create(vm))
+        , m_eventLoopTaskGroup(makeUnique<EventLoopTaskGroup>(m_eventLoop))
+    {
+    }
+
+    void addMessage(MessageSource, MessageLevel, const String&, const String&, unsigned, unsigned, RefPtr<Inspector::ScriptCallStack>&&, JSC::JSGlobalObject* = nullptr, unsigned long = 0) final { }
+    void logExceptionToConsole(const String&, const String&, int, int, RefPtr<Inspector::ScriptCallStack>&&) final { };
+    void refScriptExecutionContext() final { ref(); };
+    void derefScriptExecutionContext() final { deref(); };
+
+    class EmptyEventLoop final : public EventLoop {
+    public:
+        static Ref<EmptyEventLoop> create(JSC::VM& vm)
+        {
+            return adoptRef(*new EmptyEventLoop(vm));
+        }
+
+        MicrotaskQueue& microtaskQueue() final { return m_queue; };
+
+    private:
+        EmptyEventLoop(JSC::VM& vm)
+            : m_queue(MicrotaskQueue(vm))
+        {
+        }
+
+        void scheduleToRun() final { ASSERT_NOT_REACHED(); };
+        bool isContextThread() const final { return false; };
+
+        MicrotaskQueue m_queue;
+    };
+
+    Ref<SecurityOrigin> m_origin;
+    URL m_url;
+    Ref<EmptyEventLoop> m_eventLoop;
+    std::unique_ptr<EventLoopTaskGroup> m_eventLoopTaskGroup;
+};
+
+} // namespace WebCore

Modified: trunk/Source/WebCore/worklets/WorkletScriptController.h (264485 => 264486)


--- trunk/Source/WebCore/worklets/WorkletScriptController.h	2020-07-16 23:35:22 UTC (rev 264485)
+++ trunk/Source/WebCore/worklets/WorkletScriptController.h	2020-07-16 23:56:35 UTC (rev 264486)
@@ -49,7 +49,7 @@
 class WorkletScriptController {
     WTF_MAKE_NONCOPYABLE(WorkletScriptController); WTF_MAKE_FAST_ALLOCATED;
 public:
-    WorkletScriptController(Ref<VM>&&, WorkletGlobalScope*);
+    WorkletScriptController(Ref<JSC::VM>&&, WorkletGlobalScope*);
     ~WorkletScriptController();
 
     JSWorkletGlobalScope* workletGlobalScopeWrapper()
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to