File's structured serialization should serialize lastModified attribute
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 May 2018 02:24:18 +0000 (02:24 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 May 2018 02:24:18 +0000 (02:24 +0000)
https://bugs.webkit.org/show_bug.cgi?id=185773

Reviewed by Youenn Fablet.

LayoutTests/imported/w3c:

Re-sync workers/semantics/structured-clone WPT tests after:
https://github.com/w3c/web-platform-tests/pull/9218

* web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-harness.js: Added.
(runStructuredCloneBatteryOfTests):
* web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js: Added.
(structuredCloneBatteryOfTests.push.async.f):
* web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests.js: Renamed from LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/common.js.
(async.compare_Blob):
(get_canvas_1x1_transparent_black):
(get_canvas_1x1_non_transparent_non_black):
(compare_ImageBitmap):
(structuredCloneBatteryOfTests.push.async.f):
* web-platform-tests/html/webappapis/structured-clone/w3c-import.log: Copied from LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/w3c-import.log.
* web-platform-tests/workers/semantics/structured-clone/dedicated-expected.txt:
* web-platform-tests/workers/semantics/structured-clone/dedicated.html:
* web-platform-tests/workers/semantics/structured-clone/dedicated.js: Removed.
* web-platform-tests/workers/semantics/structured-clone/shared-expected.txt:
* web-platform-tests/workers/semantics/structured-clone/shared.html:
* web-platform-tests/workers/semantics/structured-clone/shared.js: Removed.
* web-platform-tests/workers/semantics/structured-clone/w3c-import.log:
* web-platform-tests/workers/semantics/structured-clone/worker-common.js: Removed.

Source/WebCore:

Update our implementation for the stuctured serialization of a File to include
its lastModified attribute, as per:
- https://w3c.github.io/FileAPI/#file-section

No new tests, rebaselined existing test.

* bindings/js/SerializedScriptValue.cpp:
(WebCore::CloneSerializer::write):
(WebCore::CloneDeserializer::readFile):
* fileapi/File.cpp:
(WebCore::File::File):
* fileapi/File.h:

LayoutTests:

Unskip structured serialization tests that no longer fail / time out.

* TestExpectations:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232043 268f45cc-cd09-0410-ab3c-d52691b4dbfc

21 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/fast/storage/serialized-script-value.html
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/IndexedDB/keypath-special-identifiers-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-harness.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests.js [moved from LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/common.js with 73% similarity]
LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/w3c-import.log [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/dedicated-expected.txt
LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/dedicated.html
LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/dedicated.js [deleted file]
LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/shared-expected.txt
LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/shared.html
LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/shared.js [deleted file]
LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/w3c-import.log
LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/worker-common.js [deleted file]
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/SerializedScriptValue.cpp
Source/WebCore/fileapi/File.cpp
Source/WebCore/fileapi/File.h

index ac5ffa8..1a85f31 100644 (file)
@@ -1,3 +1,14 @@
+2018-05-21  Chris Dumez  <cdumez@apple.com>
+
+        File's structured serialization should serialize lastModified attribute
+        https://bugs.webkit.org/show_bug.cgi?id=185773
+
+        Reviewed by Youenn Fablet.
+
+        Unskip structured serialization tests that no longer fail / time out.
+
+        * TestExpectations:
+
 2018-05-21  Jiewen Tan  <jiewen_tan@apple.com>
 
         Unreviewed, update crypto/subtle/ecdh-import-jwk-private-key-p384.html to correct input
index 87c8c10..72aeb04 100644 (file)
@@ -241,8 +241,6 @@ imported/w3c/web-platform-tests/workers/interfaces/WorkerUtils/importScripts/006
 imported/w3c/web-platform-tests/workers/nested_worker.worker.html [ Skip ]
 imported/w3c/web-platform-tests/workers/opaque-origin.html [ Skip ]
 imported/w3c/web-platform-tests/workers/semantics/interface-objects/003.html [ Skip ]
-imported/w3c/web-platform-tests/workers/semantics/structured-clone/shared.html [ Skip ]
-imported/w3c/web-platform-tests/workers/semantics/structured-clone/dedicated.html [ Skip ]
 imported/w3c/web-platform-tests/workers/semantics/multiple-workers/003.html [ Skip ]
 imported/w3c/web-platform-tests/workers/semantics/multiple-workers/005.html [ Skip ]
 imported/w3c/web-platform-tests/workers/Worker_cross_origin_security_err.htm [ Skip ]
index 5bd89fa..d11fe03 100644 (file)
@@ -6,6 +6,8 @@
     <body>
         <script>
 
+const currentVersion = 0x07;
+
 // Here's a little Q&D helper for future adventurers needing to rebaseline this.
 
 function dec2hex(n) {
@@ -43,7 +45,7 @@ function testSerialization(obj, values, oldFormat, serializeExceptionValue) {
 
 testSerialization({foo: 'zoo', bar: {baz: 'myNewKey'}},
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00,
     0x80, 0x66, 0x6f, 0x6f, 0x10, 0x03, 0x00, 0x00,
     0x80, 0x7a, 0x6f, 0x6f, 0x03, 0x00, 0x00, 0x80,
     0x62, 0x61, 0x72, 0x02, 0x03, 0x00, 0x00, 0x80,
@@ -66,7 +68,7 @@ testSerialization({foo: 'zoo', bar: {baz: 'myNewKey'}},
 
 testSerialization({foo: 'zoo', bar: 'myNewKey'},
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00,
     0x80, 0x66, 0x6f, 0x6f, 0x10, 0x03, 0x00, 0x00,
     0x80, 0x7a, 0x6f, 0x6f, 0x03, 0x00, 0x00, 0x80,
     0x62, 0x61, 0x72, 0x10, 0x08, 0x00, 0x00, 0x80,
@@ -74,7 +76,7 @@ testSerialization({foo: 'zoo', bar: 'myNewKey'},
     0xff, 0xff, 0xff, 0xff
 ],
 [
-    0x03, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00,
     0x00, 0x66, 0x00, 0x6f, 0x00, 0x6f, 0x00, 0x10,
     0x03, 0x00, 0x00, 0x00, 0x7a, 0x00, 0x6f, 0x00,
     0x6f, 0x00, 0x03, 0x00, 0x00, 0x00, 0x62, 0x00,
@@ -86,7 +88,7 @@ testSerialization({foo: 'zoo', bar: 'myNewKey'},
 
 testSerialization([],
 [
-    0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
     0x00, 0xff, 0xff, 0xff, 0xff
 ],
 [
@@ -95,7 +97,7 @@ testSerialization([],
 ]);
 testSerialization({foo: "zoo"},
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00,
     0x80, 0x66, 0x6f, 0x6f, 0x10, 0x03, 0x00, 0x00,
     0x80, 0x7a, 0x6f, 0x6f, 0xff, 0xff, 0xff, 0xff
 ],
@@ -107,7 +109,7 @@ testSerialization({foo: "zoo"},
 ]);
 testSerialization({foo: null},
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00,
     0x80, 0x66, 0x6f, 0x6f, 0x04, 0xff, 0xff, 0xff,
     0xff
 ],
@@ -119,7 +121,7 @@ testSerialization({foo: null},
 
 testSerialization({},
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0xff,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0xff, 0xff, 0xff,
     0xff
 ],
 [
@@ -129,28 +131,28 @@ testSerialization({},
 
 testSerialization(undefined,
 [
-    0x06, 0x00, 0x00, 0x00, 0x03
+    currentVersion, 0x00, 0x00, 0x00, 0x03
 ],
 [
     0x03, 0x00, 0x00, 0x00, 0x03
 ]);
 testSerialization(true,
 [
-    0x06, 0x00, 0x00, 0x00, 0x09
+    currentVersion, 0x00, 0x00, 0x00, 0x09
 ],
 [
     0x03, 0x00, 0x00, 0x00, 0x09
 ]);
 testSerialization(false,
 [
-    0x06, 0x00, 0x00, 0x00, 0x08
+    currentVersion, 0x00, 0x00, 0x00, 0x08
 ],
 [
     0x03, 0x00, 0x00, 0x00, 0x08
 ]);
 testSerialization(new Array(100),
 [
-    0x06, 0x00, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00,
     0x00, 0xff, 0xff, 0xff, 0xff
 ],
 [
@@ -159,7 +161,7 @@ testSerialization(new Array(100),
 ]);
 testSerialization(10,
 [
-    0x06, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x00, 0x00,
     0x00
 ],
 [
@@ -168,7 +170,7 @@ testSerialization(10,
 ]);
 testSerialization(-10,
 [
-    0x06, 0x00, 0x00, 0x00, 0x05, 0xf6, 0xff, 0xff,
+    currentVersion, 0x00, 0x00, 0x00, 0x05, 0xf6, 0xff, 0xff,
     0xff
 ],
 [
@@ -177,7 +179,7 @@ testSerialization(-10,
 ]);
 testSerialization(Math.pow(2,30),
 [
-    0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
     0x40
 ],
 [
@@ -186,7 +188,7 @@ testSerialization(Math.pow(2,30),
 ]);
 testSerialization(Math.pow(2,55),
 [
-    0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x60, 0x43,
 ],
 [
@@ -195,7 +197,7 @@ testSerialization(Math.pow(2,55),
 ]);
 testSerialization(1.23,
 [
-    0x06, 0x00, 0x00, 0x00, 0x0a, 0xae, 0x47, 0xe1,
+    currentVersion, 0x00, 0x00, 0x00, 0x0a, 0xae, 0x47, 0xe1,
     0x7a, 0x14, 0xae, 0xf3, 0x3f
 ],
 [
@@ -204,14 +206,14 @@ testSerialization(1.23,
 ]);
 testSerialization("",
 [
-    0x06, 0x00, 0x00, 0x00, 0x11
+    currentVersion, 0x00, 0x00, 0x00, 0x11
 ],
 [
     0x03, 0x00, 0x00, 0x00, 0x11
 ]);
 testSerialization("abc",
 [
-    0x06, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00,
     0x80, 0x61, 0x62, 0x63
 ],
 [
@@ -220,7 +222,7 @@ testSerialization("abc",
 ]);
 testSerialization({integer: 123},
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x07, 0x00, 0x00,
     0x80, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72,
     0x05, 0x7b, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
     0xff
@@ -233,7 +235,7 @@ testSerialization({integer: 123},
 ]);
 testSerialization({string: "str"},
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x06, 0x00, 0x00,
     0x80, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x10,
     0x03, 0x00, 0x00, 0x80, 0x73, 0x74, 0x72, 0xff,
     0xff, 0xff, 0xff
@@ -247,7 +249,7 @@ testSerialization({string: "str"},
 ]);
 testSerialization({list: [1,2,3]},
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
     0x80, 0x6c, 0x69, 0x73, 0x74, 0x01, 0x03, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01,
     0x00, 0x00, 0x00, 0x05, 0x02, 0x00, 0x00, 0x00,
@@ -266,14 +268,14 @@ testSerialization({list: [1,2,3]},
 ]);
 testSerialization(null,
 [
-    0x06, 0x00, 0x00, 0x00, 0x04
+    currentVersion, 0x00, 0x00, 0x00, 0x04
 ],
 [
     0x03, 0x00, 0x00, 0x00, 0x04
 ]);
 testSerialization(/abc/,
 [
-    0x06, 0x00, 0x00, 0x00, 0x12, 0x03, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x12, 0x03, 0x00, 0x00,
     0x80, 0x61, 0x62, 0x63, 0x00, 0x00, 0x00, 0x80
 ],
 [
@@ -287,7 +289,7 @@ var outerObject = {inner: innerObject};
 outerObject['outer'] = innerObject;
 testSerialization(outerObject,
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00,
     0x80, 0x69, 0x6e, 0x6e, 0x65, 0x72, 0x02, 0x05,
     0x00, 0x00, 0x80, 0x68, 0x65, 0x6c, 0x6c, 0x6f,
     0x10, 0x05, 0x00, 0x00, 0x80, 0x74, 0x68, 0x65,
@@ -309,7 +311,7 @@ testSerialization(outerObject,
 ]);
 testSerialization(innerObject,
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00,
     0x80, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x10, 0x05,
     0x00, 0x00, 0x80, 0x74, 0x68, 0x65, 0x72, 0x65,
     0xff, 0xff, 0xff, 0xff
@@ -325,7 +327,7 @@ testSerialization(innerObject,
 var unicodeObject = {a: 'a', u: String.fromCharCode(0x03B1,0x03B2), d: 42};
 testSerialization(unicodeObject,
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00,
     0x80, 0x61, 0x10, 0xfe, 0xff, 0xff, 0xff, 0x00,
     0x01, 0x00, 0x00, 0x80, 0x75, 0x10, 0x02, 0x00,
     0x00, 0x00, 0xb1, 0x03, 0xb2, 0x03, 0x01, 0x00,
@@ -343,7 +345,7 @@ testSerialization(unicodeObject,
 unicodeObject.a = 'ab';
 testSerialization(unicodeObject,
 [
-    0x06, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00,
     0x80, 0x61, 0x10, 0x02, 0x00, 0x00, 0x80, 0x61,
     0x62, 0x01, 0x00, 0x00, 0x80, 0x75, 0x10, 0x02,
     0x00, 0x00, 0x00, 0xb1, 0x03, 0xb2, 0x03, 0x01,
@@ -368,7 +370,7 @@ arrayObject['bar'] = 456;
 arrayObject[''] = null;
 testSerialization(arrayObject,
 [
-    0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
     0x00, 0xfd, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00,
     0x80, 0x61, 0x09, 0x01, 0x00, 0x00, 0x80, 0x62,
     0x08, 0x03, 0x00, 0x00, 0x80, 0x66, 0x6f, 0x6f,
@@ -382,7 +384,7 @@ arrayObject[0] = 'foo';
 arrayObject[1] = 'bar';
 testSerialization(arrayObject,
 [
-    0x06, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x03, 0x00,
     0x00, 0x80, 0x66, 0x6f, 0x6f, 0x01, 0x00, 0x00,
     0x00, 0x10, 0x03, 0x00, 0x00, 0x80, 0x62, 0x61,
@@ -403,7 +405,7 @@ mapObject.expando = {};
 
 testSerialization(mapObject,
 [
-    0x06, 0x00, 0x00, 0x00, 0x1e, 0x07, 0x05, 0x02,
+    currentVersion, 0x00, 0x00, 0x00, 0x1e, 0x07, 0x05, 0x02,
     0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0xf8, 0x3f, 0x02, 0xff, 0xff, 0xff,
     0xff, 0x13, 0x00, 0x10, 0x03, 0x00, 0x00, 0x80,
@@ -424,7 +426,7 @@ setObject.expando = {};
 
 testSerialization(setObject,
 [
-    0x06, 0x00, 0x00, 0x00, 0x1d, 0x07, 0x0a, 0x00,
+    currentVersion, 0x00, 0x00, 0x00, 0x1d, 0x07, 0x0a, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x13,
     0x00, 0x10, 0x03, 0x00, 0x00, 0x80, 0x62, 0x61,
     0x72, 0x1a, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x20,
index df20193..6a278ad 100644 (file)
@@ -1,3 +1,33 @@
+2018-05-21  Chris Dumez  <cdumez@apple.com>
+
+        File's structured serialization should serialize lastModified attribute
+        https://bugs.webkit.org/show_bug.cgi?id=185773
+
+        Reviewed by Youenn Fablet.
+
+        Re-sync workers/semantics/structured-clone WPT tests after:
+        https://github.com/w3c/web-platform-tests/pull/9218
+
+        * web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-harness.js: Added.
+        (runStructuredCloneBatteryOfTests):
+        * web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js: Added.
+        (structuredCloneBatteryOfTests.push.async.f):
+        * web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests.js: Renamed from LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/common.js.
+        (async.compare_Blob):
+        (get_canvas_1x1_transparent_black):
+        (get_canvas_1x1_non_transparent_non_black):
+        (compare_ImageBitmap):
+        (structuredCloneBatteryOfTests.push.async.f):
+        * web-platform-tests/html/webappapis/structured-clone/w3c-import.log: Copied from LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/w3c-import.log.
+        * web-platform-tests/workers/semantics/structured-clone/dedicated-expected.txt:
+        * web-platform-tests/workers/semantics/structured-clone/dedicated.html:
+        * web-platform-tests/workers/semantics/structured-clone/dedicated.js: Removed.
+        * web-platform-tests/workers/semantics/structured-clone/shared-expected.txt:
+        * web-platform-tests/workers/semantics/structured-clone/shared.html:
+        * web-platform-tests/workers/semantics/structured-clone/shared.js: Removed.
+        * web-platform-tests/workers/semantics/structured-clone/w3c-import.log:
+        * web-platform-tests/workers/semantics/structured-clone/worker-common.js: Removed.
+
 2018-05-21  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r232030.
index d27b7c3..be90589 100644 (file)
@@ -4,6 +4,6 @@ PASS Type: Array, identifier: length
 PASS Type: Blob, identifier: size 
 PASS Type: Blob, identifier: type 
 PASS Type: File, identifier: name 
-FAIL Type: File, identifier: lastModified assert_equals: Property should be used as key expected 0 but got 1
+PASS Type: File, identifier: lastModified 
 FAIL Type: File, identifier: lastModifiedDate Provided data is inadequate.
 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-harness.js b/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-harness.js
new file mode 100644 (file)
index 0000000..624f983
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * Runs a collection of tests that determine if an API implements structured clone
+ * correctly.
+ *
+ * The `runner` parameter has the following properties:
+ * - `setup()`: An optional function run once before testing starts
+ * - `teardown()`: An option function run once after all tests are done
+ * - `preTest()`: An optional, async function run before a test
+ * - `postTest()`: An optional, async function run after a test is done
+ * - `structuredClone(obj, transferList)`: Required function that somehow
+ *                                         structurally clones an object.
+ * - `noTransferTests`: When true, disables tests with transferables
+ */
+
+function runStructuredCloneBatteryOfTests(runner) {
+  const defaultRunner = {
+    setup() {},
+    preTest() {},
+    postTest() {},
+    teardown() {}
+  };
+  runner = Object.assign({}, defaultRunner, runner);
+
+  let setupPromise = runner.setup();
+  const allTests = structuredCloneBatteryOfTests.map(test => {
+
+    return new Promise(resolve => {
+      promise_test(async _ => {
+        test = await test;
+        await setupPromise;
+        await runner.preTest(test);
+        await test.f(runner)
+        await runner.postTest(test);
+        resolve();
+      }, test.description);
+    }).catch(_ => {});
+  });
+  Promise.all(allTests).then(_ => runner.teardown());
+}
diff --git a/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js b/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js
new file mode 100644 (file)
index 0000000..744f116
--- /dev/null
@@ -0,0 +1,22 @@
+structuredCloneBatteryOfTests.push({
+  description: 'ArrayBuffer',
+  async f(runner) {
+    const buffer = new Uint8Array([1]).buffer;
+    const copy = await runner.structuredClone(buffer, [buffer]);
+    assert_equals(buffer.byteLength, 0);
+    assert_equals(copy.byteLength, 1);
+  }
+});
+
+structuredCloneBatteryOfTests.push({
+  description: 'MessagePort',
+  async f(runner) {
+    const {port1, port2} = new MessageChannel();
+    const copy = await runner.structuredClone(port2, [port2]);
+    const msg = new Promise(resolve => port1.onmessage = resolve);
+    copy.postMessage('ohai');
+    assert_equals((await msg).data, 'ohai');
+  }
+});
+
+// TODO: ImageBitmap
@@ -1,22 +1,23 @@
-function createWorker(msg) {
-  // `type` is defined in the test case itself
-  if (type == 'dedicated')
-    return new Worker('dedicated.js#'+encodeURIComponent(msg));
-  else if (type == 'shared')
-    return (new SharedWorker('shared.js#'+encodeURIComponent(msg))).port;
-  else
-    assert_unreached('invalid or missing `type`');
-}
-
-function check(msg, input, callback, test_obj) {
-  if (!test_obj)
-    test_obj = async_test(msg);
-  test_obj.step(function() {
-    var w = createWorker(msg);
-    if (typeof input === 'function')
-      input = this.step(input);
-    w.postMessage(input);
-    w.onmessage = this.step_func(function(ev) { callback(ev.data, input, this); });
+/* This file is mostly a remix of @zcorpan’s web worker test suite */
+
+structuredCloneBatteryOfTests = [];
+
+function check(description, input, callback) {
+  testObjMock = {
+    done() {},
+    step_func(f) {return _ => f()},
+  };
+
+  structuredCloneBatteryOfTests.push({
+    description,
+    async f(runner) {
+      let newInput = input;
+      if (typeof input === 'function') {
+        newInput = input();
+      }
+      const copy = await runner.structuredClone(newInput);
+      await callback(copy, newInput, testObjMock);
+    }
   });
 }
 
@@ -261,7 +262,7 @@ check('Object RegExp object, RegExp empty', {'x':new RegExp('')}, compare_Object
 check('Object RegExp object, RegExp slash', {'x':new RegExp('/')}, compare_Object(enumerate_props(compare_RegExp('\\/'))));
 check('Object RegExp object, RegExp new line', {'x':new RegExp('\n')}, compare_Object(enumerate_props(compare_RegExp('\\n'))));
 
-function compare_Blob(actual, input, test_obj, expect_File) {
+async function compare_Blob(actual, input, test_obj, expect_File) {
   if (typeof actual === 'string')
     assert_unreached(actual);
   assert_true(actual instanceof Blob, 'instanceof Blob');
@@ -270,31 +271,14 @@ function compare_Blob(actual, input, test_obj, expect_File) {
   assert_equals(actual.size, input.size, 'size');
   assert_equals(actual.type, input.type, 'type');
   assert_not_equals(actual, input);
-  var ev_reader = new FileReader();
-  var input_reader = new FileReader();
-  var read_count = 0;
-  var read_done = test_obj.step_func(function() {
-    read_count++;
-    if (read_count == 2) {
-      var ev_result = ev_reader.result;
-      var input_result = input_reader.result;
-      assert_equals(ev_result.byteLength, input_result.byteLength, 'byteLength');
-      var ev_view = new DataView(ev_result);
-      var input_view = new DataView(input_result);
-      for (var i = 0; i < ev_result.byteLength; ++i) {
-        assert_equals(ev_view.getUint8(i), input_view.getUint8(i), 'getUint8('+i+')');
-      }
-      if (test_obj)
-        test_obj.done();
-    }
-  });
-  var read_error = test_obj.step_func(function() { assert_unreached('FileReader error'); });
-  ev_reader.readAsArrayBuffer(actual);
-  ev_reader.onload = read_done;
-  ev_reader.onabort = ev_reader.onerror = read_error;
-  input_reader.readAsArrayBuffer(input);
-  input_reader.onload = read_done;
-  input_reader.onabort = input_reader.onerror = read_error;
+  const ab1 = new Response(actual).arrayBuffer();
+  const ab2 = new Response(input).arrayBuffer();
+  assert_equals(ab1.btyeLength, ab2.byteLength, 'byteLength');
+  const ta1 = new Uint8Array(ab1);
+  const ta2 = new Uint8Array(ab2);
+  for(let i = 0; i < ta1.size; i++) {
+    assert_equals(ta1[i], ta2[i]);
+  }
 }
 function func_Blob_basic() {
   return new Blob(['foo'], {type:'text/x-bar'});
@@ -338,43 +322,19 @@ function func_Blob_NUL() {
 }
 check('Blob NUL', func_Blob_NUL, compare_Blob);
 
-async_test(function(test_obj) {
-  check(test_obj.name, [test_obj.step(func_Blob_basic)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Array Blob object, Blob basic');
-async_test(function(test_obj) {
-  check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Array Blob object, Blob unpaired high surrogate (invalid utf-8)');
-async_test(function(test_obj) {
-  check(test_obj.name, [test_obj.step(func_Blob_bytes([0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Array Blob object, Blob unpaired low surrogate (invalid utf-8)');
-async_test(function(test_obj) {
-  check(test_obj.name, [test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Array Blob object, Blob paired surrogates (invalid utf-8)');
-async_test(function(test_obj) {
-  check(test_obj.name, [test_obj.step(func_Blob_empty)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Array Blob object, Blob empty');
-async_test(function(test_obj) {
-  check(test_obj.name, [test_obj.step(func_Blob_NUL)], compare_Array(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Array Blob object, Blob NUL');
-
-async_test(function(test_obj) {
-  check(test_obj.name, {'x':test_obj.step(func_Blob_basic)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Object Blob object, Blob basic');
-async_test(function(test_obj) {
-  check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Object Blob object, Blob unpaired high surrogate (invalid utf-8)');
-async_test(function(test_obj) {
-  check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Object Blob object, Blob unpaired low surrogate (invalid utf-8)');
-async_test(function(test_obj) {
-  check(test_obj.name, {'x':test_obj.step(func_Blob_bytes([0xD800, 0xDC00]))}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Object Blob object, Blob paired surrogates (invalid utf-8)');
-async_test(function(test_obj) {
-  check(test_obj.name, {'x':test_obj.step(func_Blob_empty)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Object Blob object, Blob empty');
-async_test(function(test_obj) {
-  check(test_obj.name, {'x':test_obj.step(func_Blob_NUL)}, compare_Object(enumerate_props(compare_Blob, test_obj), true), test_obj);
-}, 'Object Blob object, Blob NUL');
+check('Array Blob object, Blob basic', [func_Blob_basic()], compare_Array(enumerate_props(compare_Blob), true));
+check('Array Blob object, Blob unpaired high surrogate (invalid utf-8)', [func_Blob_bytes([0xD800])()], compare_Array(enumerate_props(compare_Blob), true));
+check('Array Blob object, Blob unpaired low surrogate (invalid utf-8)', [func_Blob_bytes([0xDC00])()], compare_Array(enumerate_props(compare_Blob), true));
+check('Array Blob object, Blob paired surrogates (invalid utf-8)', [func_Blob_bytes([0xD800, 0xDC00])()], compare_Array(enumerate_props(compare_Blob), true));
+check('Array Blob object, Blob empty', [func_Blob_empty()], compare_Array(enumerate_props(compare_Blob), true));
+check('Array Blob object, Blob NUL', [func_Blob_NUL()], compare_Array(enumerate_props(compare_Blob), true));
+
+check('Object Blob object, Blob basic', {'x':func_Blob_basic()}, compare_Object(enumerate_props(compare_Blob), true));
+check('Object Blob object, Blob unpaired high surrogate (invalid utf-8)', {'x':func_Blob_bytes([0xD800])()}, compare_Object(enumerate_props(compare_Blob), true));
+check('Object Blob object, Blob unpaired low surrogate (invalid utf-8)', {'x':func_Blob_bytes([0xDC00])()}, compare_Object(enumerate_props(compare_Blob), true));
+check('Object Blob object, Blob paired surrogates (invalid utf-8)', {'x':func_Blob_bytes([0xD800, 0xDC00])()  }, compare_Object(enumerate_props(compare_Blob), true));
+check('Object Blob object, Blob empty', {'x':func_Blob_empty()}, compare_Object(enumerate_props(compare_Blob), true));
+check('Object Blob object, Blob NUL', {'x':func_Blob_NUL()}, compare_Object(enumerate_props(compare_Blob), true));
 
 function compare_File(actual, input, test_obj) {
   assert_true(actual instanceof File, 'instanceof File');
@@ -404,8 +364,8 @@ function func_FileList_empty() {
   return input.files;
 }
 check('FileList empty', func_FileList_empty, compare_FileList);
-check('Array FileList object, FileList empty', [func_FileList_empty], compare_Array(enumerate_props(compare_FileList)));
-check('Object FileList object, FileList empty', {'x':func_FileList_empty}, compare_Object(enumerate_props(compare_FileList)));
+check('Array FileList object, FileList empty', [func_FileList_empty()], compare_Array(enumerate_props(compare_FileList)));
+check('Object FileList object, FileList empty', {'x':func_FileList_empty()}, compare_Object(enumerate_props(compare_FileList)));
 
 function compare_ArrayBufferView(view) {
   var Type = window[view];
@@ -449,72 +409,11 @@ function func_ImageData_1x1_non_transparent_non_black() {
   return imagedata;
 }
 check('ImageData 1x1 non-transparent non-black', func_ImageData_1x1_non_transparent_non_black, compare_ImageData);
-async_test(function(test_obj) {
-  check(test_obj.name, [test_obj.step(func_ImageData_1x1_transparent_black)], compare_Array(enumerate_props(compare_ImageData)), test_obj);
-}, 'Array ImageData object, ImageData 1x1 transparent black');
-async_test(function(test_obj) {
-  check(test_obj.name, [test_obj.step(func_ImageData_1x1_non_transparent_non_black)], compare_Array(enumerate_props(compare_ImageData)), test_obj);
-}, 'Array ImageData object, ImageData 1x1 non-transparent non-black');
-async_test(function(test_obj) {
-  check(test_obj.name, {'x':test_obj.step(func_ImageData_1x1_transparent_black)}, compare_Object(enumerate_props(compare_ImageData)), test_obj);
-}, 'Object ImageData object, ImageData 1x1 transparent black');
-async_test(function(test_obj) {
-  check(test_obj.name, {'x':test_obj.step(func_ImageData_1x1_non_transparent_non_black)}, compare_Object(enumerate_props(compare_ImageData)), test_obj);
-}, 'Object ImageData object, ImageData 1x1 non-transparent non-black');
-
-function compare_ImageBitmap(actual, input, test_obj) {
-  if (typeof actual === 'string')
-    assert_unreached(actual);
-  assert_equals(actual instanceof ImageBitmap, 'instanceof ImageBitmap');
-  assert_not_equals(actual, input);
-  // XXX paint the ImageBitmap on a canvas and check the data
-  if (test_obj)
-    test_obj.done();
-}
-function get_canvas_1x1_transparent_black() {
-  var canvas = document.createElement('canvas');
-  canvas.width = 1;
-  canvas.height = 1;
-  return canvas;
-}
-async_test(function(test_obj) {
-  var canvas = get_canvas_1x1_transparent_black();
-  createImageBitmap(canvas, function(image) { check(test_obj.name, image, compare_ImageBitmap, test_obj); });
-}, 'ImageBitmap 1x1 transparent black');
-function get_canvas_1x1_non_transparent_non_black() {
-  var canvas = document.createElement('canvas');
-  canvas.width = 1;
-  canvas.height = 1;
-  var ctx = canvas.getContext('2d');
-  var imagedata = ctx.getImageData(0, 0, 1, 1);
-  imagedata.data[0] = 100;
-  imagedata.data[1] = 101;
-  imagedata.data[2] = 102;
-  imagedata.data[3] = 103;
-  return canvas;
-}
-async_test(function(test_obj) {
-  var canvas = get_canvas_1x1_non_transparent_non_black();
-  createImageBitmap(canvas, function(image) { check(test_obj.name, image, compare_ImageBitmap, test_obj); });
-}, 'ImageBitmap 1x1 non-transparent non-black');
-
-async_test(function(test_obj) {
-  var canvas = get_canvas_1x1_transparent_black();
-  createImageBitmap(canvas, function(image) { check(test_obj.name, [image], compare_Array(enumerate_props(compare_ImageBitmap)), test_obj); });
-}, 'Array ImageBitmap object, ImageBitmap 1x1 transparent black');
-async_test(function(test_obj) {
-  var canvas = get_canvas_1x1_non_transparent_non_black();
-  createImageBitmap(canvas, function(image) { check(test_obj.name, [image], compare_Array(enumerate_props(compare_ImageBitmap)), test_obj); });
-}, 'Array ImageBitmap object, ImageBitmap 1x1 non-transparent non-black');
-
-async_test(function(test_obj) {
-  var canvas = get_canvas_1x1_transparent_black();
-  createImageBitmap(canvas, function(image) { check(test_obj.name, {'x':image}, compare_Object(enumerate_props(compare_ImageBitmap)), test_obj); });
-}, 'Object ImageBitmap object, ImageBitmap 1x1 transparent black');
-async_test(function(test_obj) {
-  var canvas = get_canvas_1x1_non_transparent_non_black();
-  createImageBitmap(canvas, function(image) { check(test_obj.name, {'x':image}, compare_Object(enumerate_props(compare_ImageBitmap)), test_obj); });
-}, 'Object ImageBitmap object, ImageBitmap 1x1 non-transparent non-black');
+check('Array ImageData object, ImageData 1x1 transparent black', [func_ImageData_1x1_transparent_black()], compare_Array(enumerate_props(compare_ImageData)));
+check('Array ImageData object, ImageData 1x1 non-transparent non-black', [func_ImageData_1x1_non_transparent_non_black()], compare_Array(enumerate_props(compare_ImageData)));
+check('Object ImageData object, ImageData 1x1 transparent black', {'x':func_ImageData_1x1_transparent_black()}, compare_Object(enumerate_props(compare_ImageData)));
+check('Object ImageData object, ImageData 1x1 non-transparent non-black', {'x':func_ImageData_1x1_non_transparent_non_black()}, compare_Object(enumerate_props(compare_ImageData)));
+
 
 check('Array sparse', new Array(10), compare_Array(enumerate_props(compare_primitive)));
 check('Array with non-index property', function() {
@@ -594,3 +493,94 @@ check('Object with non-configurable property', function() {
   Object.defineProperty(rv, 'foo', {value:'bar', enumerable:true, writable:true, configurable:false});
   return rv;
 }, compare_Object(check_configurable_property('foo')));
+
+/* The tests below are inspired by @zcorpan’s work but got some
+more substantial changed due to their previous async setup */
+
+function get_canvas_1x1_transparent_black() {
+  var canvas = document.createElement('canvas');
+  canvas.width = 1;
+  canvas.height = 1;
+  return canvas;
+}
+
+function get_canvas_1x1_non_transparent_non_black() {
+  var canvas = document.createElement('canvas');
+  canvas.width = 1;
+  canvas.height = 1;
+  var ctx = canvas.getContext('2d');
+  var imagedata = ctx.getImageData(0, 0, 1, 1);
+  imagedata.data[0] = 100;
+  imagedata.data[1] = 101;
+  imagedata.data[2] = 102;
+  imagedata.data[3] = 103;
+  return canvas;
+}
+
+function compare_ImageBitmap(actual, input) {
+  if (typeof actual === 'string')
+    assert_unreached(actual);
+  assert_true(actual instanceof ImageBitmap, 'instanceof ImageBitmap');
+  assert_not_equals(actual, input);
+  // XXX paint the ImageBitmap on a canvas and check the data
+}
+
+structuredCloneBatteryOfTests.push({
+  description: 'ImageBitmap 1x1 transparent black',
+  async f(runner) {
+    var canvas = get_canvas_1x1_transparent_black();
+    const bm = await createImageBitmap(canvas);
+    const copy = await runner.structuredClone(bm);
+    compare_ImageBitmap(bm, copy);
+  }
+});
+
+structuredCloneBatteryOfTests.push({
+  description: 'ImageBitmap 1x1 non-transparent non-black',
+  async f(runner) {
+    var canvas = get_canvas_1x1_non_transparent_non_black();
+    const bm = await createImageBitmap(canvas);
+    const copy = await runner.structuredClone(bm);
+    compare_ImageBitmap(bm, copy);
+  }
+});
+
+structuredCloneBatteryOfTests.push({
+  description: 'Array ImageBitmap object, ImageBitmap 1x1 transparent black',
+  async f(runner) {
+    var canvas = get_canvas_1x1_transparent_black();
+    const bm = [await createImageBitmap(canvas)];
+    const copy = await runner.structuredClone(bm);
+    compare_Array(enumerate_props(compare_ImageBitmap))(bm, copy);
+  }
+});
+
+structuredCloneBatteryOfTests.push({
+  description: 'Array ImageBitmap object, ImageBitmap 1x1 transparent non-black',
+  async f(runner) {
+    var canvas = get_canvas_1x1_non_transparent_non_black();
+    const bm = [await createImageBitmap(canvas)];
+    const copy = await runner.structuredClone(bm);
+    compare_Array(enumerate_props(compare_ImageBitmap))(bm, copy);
+  }
+});
+
+structuredCloneBatteryOfTests.push({
+  description: 'Object ImageBitmap object, ImageBitmap 1x1 transparent black',
+  async f(runner) {
+    var canvas = get_canvas_1x1_transparent_black();
+    const bm = {x: await createImageBitmap(canvas)};
+    const copy = await runner.structuredClone(bm);
+    compare_Object(enumerate_props(compare_ImageBitmap))(bm, copy);
+  }
+});
+
+structuredCloneBatteryOfTests.push({
+  description: 'Object ImageBitmap object, ImageBitmap 1x1 transparent non-black',
+  async f(runner) {
+    var canvas = get_canvas_1x1_non_transparent_non_black();
+    const bm = {x: await createImageBitmap(canvas)};
+    const copy = await runner.structuredClone(bm);
+    compare_Object(enumerate_props(compare_ImageBitmap))(bm, copy);
+  }
+});
diff --git a/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/w3c-import.log
new file mode 100644 (file)
index 0000000..4753241
--- /dev/null
@@ -0,0 +1,19 @@
+The tests in this directory were imported from the W3C repository.
+Do NOT modify these tests directly in WebKit.
+Instead, create a pull request on the WPT github:
+       https://github.com/w3c/web-platform-tests
+
+Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport
+
+Do NOT modify or remove this file.
+
+------------------------------------------------------------------------
+Properties requiring vendor prefixes:
+None
+Property values requiring vendor prefixes:
+None
+------------------------------------------------------------------------
+List of files:
+/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-harness.js
+/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js
+/LayoutTests/imported/w3c/web-platform-tests/html/webappapis/structured-clone/structured-clone-battery-of-tests.js
index cad234d..57b71d4 100644 (file)
@@ -1,6 +1,4 @@
 
-Harness Error (TIMEOUT), message = null
-
 PASS primitive undefined 
 PASS primitive null 
 PASS primitive true 
@@ -52,57 +50,51 @@ PASS Date 8.64e15
 PASS Array Date objects 
 PASS Object Date objects 
 PASS RegExp flags and lastIndex 
-FAIL RegExp sticky flag assert_unreached: FAIL: unknown test Reached unreachable code
-FAIL RegExp unicode flag assert_unreached: FAIL: unknown test Reached unreachable code
+FAIL RegExp sticky flag assert_equals: sticky expected true but got false
+FAIL RegExp unicode flag assert_equals: unicode expected true but got false
 PASS RegExp empty 
 PASS RegExp slash 
 PASS RegExp new line 
 PASS Array RegExp object, RegExp flags and lastIndex 
-FAIL Array RegExp object, RegExp sticky flag assert_unreached: FAIL: unknown test Reached unreachable code
-FAIL Array RegExp object, RegExp unicode flag assert_unreached: FAIL: unknown test Reached unreachable code
+FAIL Array RegExp object, RegExp sticky flag assert_equals: sticky expected true but got false
+FAIL Array RegExp object, RegExp unicode flag assert_equals: unicode expected true but got false
 PASS Array RegExp object, RegExp empty 
 PASS Array RegExp object, RegExp slash 
 PASS Array RegExp object, RegExp new line 
 PASS Object RegExp object, RegExp flags and lastIndex 
-FAIL Object RegExp object, RegExp sticky flag assert_unreached: FAIL: unknown test Reached unreachable code
-FAIL Object RegExp object, RegExp unicode flag assert_unreached: FAIL: unknown test Reached unreachable code
+FAIL Object RegExp object, RegExp sticky flag assert_equals: sticky expected true but got false
+FAIL Object RegExp object, RegExp unicode flag assert_equals: unicode expected true but got false
 PASS Object RegExp object, RegExp empty 
 PASS Object RegExp object, RegExp slash 
 PASS Object RegExp object, RegExp new line 
-FAIL Blob basic assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Blob unpaired high surrogate (invalid utf-8) assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Blob unpaired low surrogate (invalid utf-8) assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Blob paired surrogates (invalid utf-8) assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Blob empty assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Blob NUL assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Array Blob object, Blob basic assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Array Blob object, Blob unpaired high surrogate (invalid utf-8) assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Array Blob object, Blob unpaired low surrogate (invalid utf-8) assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Array Blob object, Blob paired surrogates (invalid utf-8) assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Array Blob object, Blob empty assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Array Blob object, Blob NUL assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Object Blob object, Blob basic assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Object Blob object, Blob unpaired high surrogate (invalid utf-8) assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Object Blob object, Blob unpaired low surrogate (invalid utf-8) assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Object Blob object, Blob paired surrogates (invalid utf-8) assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Object Blob object, Blob empty assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL Object Blob object, Blob NUL assert_unreached: FAIL ReferenceError: Can't find variable: File Reached unreachable code
-FAIL File basic assert_true: instanceof File expected true got false
-FAIL FileList empty assert_unreached: FAIL ReferenceError: Can't find variable: FileList Reached unreachable code
-FAIL Array FileList object, FileList empty The object can not be cloned.
-FAIL Object FileList object, FileList empty The object can not be cloned.
+PASS Blob basic 
+PASS Blob unpaired high surrogate (invalid utf-8) 
+PASS Blob unpaired low surrogate (invalid utf-8) 
+PASS Blob paired surrogates (invalid utf-8) 
+PASS Blob empty 
+PASS Blob NUL 
+PASS Array Blob object, Blob basic 
+PASS Array Blob object, Blob unpaired high surrogate (invalid utf-8) 
+PASS Array Blob object, Blob unpaired low surrogate (invalid utf-8) 
+PASS Array Blob object, Blob paired surrogates (invalid utf-8) 
+PASS Array Blob object, Blob empty 
+PASS Array Blob object, Blob NUL 
+PASS Object Blob object, Blob basic 
+PASS Object Blob object, Blob unpaired high surrogate (invalid utf-8) 
+PASS Object Blob object, Blob unpaired low surrogate (invalid utf-8) 
+PASS Object Blob object, Blob paired surrogates (invalid utf-8) 
+PASS Object Blob object, Blob empty 
+PASS Object Blob object, Blob NUL 
+PASS File basic 
+PASS FileList empty 
+PASS Array FileList object, FileList empty 
+PASS Object FileList object, FileList empty 
 PASS ImageData 1x1 transparent black 
 PASS ImageData 1x1 non-transparent non-black 
 PASS Array ImageData object, ImageData 1x1 transparent black 
 PASS Array ImageData object, ImageData 1x1 non-transparent non-black 
 PASS Object ImageData object, ImageData 1x1 transparent black 
 PASS Object ImageData object, ImageData 1x1 non-transparent non-black 
-TIMEOUT ImageBitmap 1x1 transparent black Test timed out
-TIMEOUT ImageBitmap 1x1 non-transparent non-black Test timed out
-TIMEOUT Array ImageBitmap object, ImageBitmap 1x1 transparent black Test timed out
-TIMEOUT Array ImageBitmap object, ImageBitmap 1x1 non-transparent non-black Test timed out
-TIMEOUT Object ImageBitmap object, ImageBitmap 1x1 transparent black Test timed out
-TIMEOUT Object ImageBitmap object, ImageBitmap 1x1 non-transparent non-black Test timed out
 PASS Array sparse 
 PASS Array with non-index property 
 PASS Object with index property and length 
@@ -114,4 +106,12 @@ PASS Object with property on prototype
 PASS Object with non-enumerable property 
 PASS Object with non-writable property 
 PASS Object with non-configurable property 
+FAIL ImageBitmap 1x1 transparent black promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL ImageBitmap 1x1 non-transparent non-black promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Array ImageBitmap object, ImageBitmap 1x1 transparent black promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Array ImageBitmap object, ImageBitmap 1x1 transparent non-black promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Object ImageBitmap object, ImageBitmap 1x1 transparent black promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Object ImageBitmap object, ImageBitmap 1x1 transparent non-black promise_test: Unhandled rejection with value: object "TypeError: Type error"
+PASS ArrayBuffer 
+PASS MessagePort 
 
index 5dd8c35..2f1732c 100644 (file)
@@ -2,8 +2,31 @@
 <title>structured clone to dedicated worker</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src=/html/webappapis/structured-clone/structured-clone-battery-of-tests.js></script>
+<script src=/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js></script>
+<script src=/html/webappapis/structured-clone/structured-clone-battery-of-tests-harness.js></script>
 <div id=log></div>
 <script>
-var type = 'dedicated';
+  runStructuredCloneBatteryOfTests({
+    setup() {
+      const blob = new Blob([`
+        onmessage = ev => postMessage(ev.data, ev.data.transfer);
+      `], {type: 'text/javascript'});
+      this.blobURL = URL.createObjectURL(blob);
+      this.worker = new Worker(this.blobURL);
+    },
+    structuredClone(data, transfer) {
+      return new Promise(resolve => {
+        this.worker.addEventListener('message', function f(ev) {
+          this.worker.removeEventListener('message', f);
+          resolve(ev.data.data);
+        }.bind(this));
+        this.worker.postMessage({data, transfer}, transfer);
+      });
+    },
+    teardown() {
+      this.worker.terminate();
+      URL.revokeObjectURL(this.blobURL);
+    }
+  });
 </script>
-<script src="common.js"></script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/dedicated.js b/LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/dedicated.js
deleted file mode 100644 (file)
index 4744578..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-importScripts('worker-common.js');
-onmessage = function(ev) {
-  check(ev.data, self);
-};
index 8c6b6c6..93285f8 100644 (file)
@@ -1,117 +1,4 @@
+CONSOLE MESSAGE: line 19: ReferenceError: Can't find variable: SharedWorker
 
-Harness Error (TIMEOUT), message = null
-
-FAIL primitive undefined Can't find variable: SharedWorker
-FAIL primitive null Can't find variable: SharedWorker
-FAIL primitive true Can't find variable: SharedWorker
-FAIL primitive false Can't find variable: SharedWorker
-FAIL primitive string, empty string Can't find variable: SharedWorker
-FAIL primitive string, lone high surrogate Can't find variable: SharedWorker
-FAIL primitive string, lone low surrogate Can't find variable: SharedWorker
-FAIL primitive string, NUL Can't find variable: SharedWorker
-FAIL primitive string, astral character Can't find variable: SharedWorker
-FAIL primitive number, 0.2 Can't find variable: SharedWorker
-FAIL primitive number, 0 Can't find variable: SharedWorker
-FAIL primitive number, -0 Can't find variable: SharedWorker
-FAIL primitive number, NaN Can't find variable: SharedWorker
-FAIL primitive number, Infinity Can't find variable: SharedWorker
-FAIL primitive number, -Infinity Can't find variable: SharedWorker
-FAIL primitive number, 9007199254740992 Can't find variable: SharedWorker
-FAIL primitive number, -9007199254740992 Can't find variable: SharedWorker
-FAIL primitive number, 9007199254740994 Can't find variable: SharedWorker
-FAIL primitive number, -9007199254740994 Can't find variable: SharedWorker
-FAIL Array primitives Can't find variable: SharedWorker
-FAIL Object primitives Can't find variable: SharedWorker
-FAIL Boolean true Can't find variable: SharedWorker
-FAIL Boolean false Can't find variable: SharedWorker
-FAIL Array Boolean objects Can't find variable: SharedWorker
-FAIL Object Boolean objects Can't find variable: SharedWorker
-FAIL String empty string Can't find variable: SharedWorker
-FAIL String lone high surrogate Can't find variable: SharedWorker
-FAIL String lone low surrogate Can't find variable: SharedWorker
-FAIL String NUL Can't find variable: SharedWorker
-FAIL String astral character Can't find variable: SharedWorker
-FAIL Array String objects Can't find variable: SharedWorker
-FAIL Object String objects Can't find variable: SharedWorker
-FAIL Number 0.2 Can't find variable: SharedWorker
-FAIL Number 0 Can't find variable: SharedWorker
-FAIL Number -0 Can't find variable: SharedWorker
-FAIL Number NaN Can't find variable: SharedWorker
-FAIL Number Infinity Can't find variable: SharedWorker
-FAIL Number -Infinity Can't find variable: SharedWorker
-FAIL Number 9007199254740992 Can't find variable: SharedWorker
-FAIL Number -9007199254740992 Can't find variable: SharedWorker
-FAIL Number 9007199254740994 Can't find variable: SharedWorker
-FAIL Number -9007199254740994 Can't find variable: SharedWorker
-FAIL Array Number objects Can't find variable: SharedWorker
-FAIL Object Number objects Can't find variable: SharedWorker
-FAIL Date 0 Can't find variable: SharedWorker
-FAIL Date -0 Can't find variable: SharedWorker
-FAIL Date -8.64e15 Can't find variable: SharedWorker
-FAIL Date 8.64e15 Can't find variable: SharedWorker
-FAIL Array Date objects Can't find variable: SharedWorker
-FAIL Object Date objects Can't find variable: SharedWorker
-FAIL RegExp flags and lastIndex Can't find variable: SharedWorker
-FAIL RegExp sticky flag Can't find variable: SharedWorker
-FAIL RegExp unicode flag Can't find variable: SharedWorker
-FAIL RegExp empty Can't find variable: SharedWorker
-FAIL RegExp slash Can't find variable: SharedWorker
-FAIL RegExp new line Can't find variable: SharedWorker
-FAIL Array RegExp object, RegExp flags and lastIndex Can't find variable: SharedWorker
-FAIL Array RegExp object, RegExp sticky flag Can't find variable: SharedWorker
-FAIL Array RegExp object, RegExp unicode flag Can't find variable: SharedWorker
-FAIL Array RegExp object, RegExp empty Can't find variable: SharedWorker
-FAIL Array RegExp object, RegExp slash Can't find variable: SharedWorker
-FAIL Array RegExp object, RegExp new line Can't find variable: SharedWorker
-FAIL Object RegExp object, RegExp flags and lastIndex Can't find variable: SharedWorker
-FAIL Object RegExp object, RegExp sticky flag Can't find variable: SharedWorker
-FAIL Object RegExp object, RegExp unicode flag Can't find variable: SharedWorker
-FAIL Object RegExp object, RegExp empty Can't find variable: SharedWorker
-FAIL Object RegExp object, RegExp slash Can't find variable: SharedWorker
-FAIL Object RegExp object, RegExp new line Can't find variable: SharedWorker
-FAIL Blob basic Can't find variable: SharedWorker
-FAIL Blob unpaired high surrogate (invalid utf-8) Can't find variable: SharedWorker
-FAIL Blob unpaired low surrogate (invalid utf-8) Can't find variable: SharedWorker
-FAIL Blob paired surrogates (invalid utf-8) Can't find variable: SharedWorker
-FAIL Blob empty Can't find variable: SharedWorker
-FAIL Blob NUL Can't find variable: SharedWorker
-FAIL Array Blob object, Blob basic Can't find variable: SharedWorker
-FAIL Array Blob object, Blob unpaired high surrogate (invalid utf-8) Can't find variable: SharedWorker
-FAIL Array Blob object, Blob unpaired low surrogate (invalid utf-8) Can't find variable: SharedWorker
-FAIL Array Blob object, Blob paired surrogates (invalid utf-8) Can't find variable: SharedWorker
-FAIL Array Blob object, Blob empty Can't find variable: SharedWorker
-FAIL Array Blob object, Blob NUL Can't find variable: SharedWorker
-FAIL Object Blob object, Blob basic Can't find variable: SharedWorker
-FAIL Object Blob object, Blob unpaired high surrogate (invalid utf-8) Can't find variable: SharedWorker
-FAIL Object Blob object, Blob unpaired low surrogate (invalid utf-8) Can't find variable: SharedWorker
-FAIL Object Blob object, Blob paired surrogates (invalid utf-8) Can't find variable: SharedWorker
-FAIL Object Blob object, Blob empty Can't find variable: SharedWorker
-FAIL Object Blob object, Blob NUL Can't find variable: SharedWorker
-FAIL File basic Can't find variable: SharedWorker
-FAIL FileList empty Can't find variable: SharedWorker
-FAIL Array FileList object, FileList empty Can't find variable: SharedWorker
-FAIL Object FileList object, FileList empty Can't find variable: SharedWorker
-FAIL ImageData 1x1 transparent black Can't find variable: SharedWorker
-FAIL ImageData 1x1 non-transparent non-black Can't find variable: SharedWorker
-FAIL Array ImageData object, ImageData 1x1 transparent black Can't find variable: SharedWorker
-FAIL Array ImageData object, ImageData 1x1 non-transparent non-black Can't find variable: SharedWorker
-FAIL Object ImageData object, ImageData 1x1 transparent black Can't find variable: SharedWorker
-FAIL Object ImageData object, ImageData 1x1 non-transparent non-black Can't find variable: SharedWorker
-TIMEOUT ImageBitmap 1x1 transparent black Test timed out
-TIMEOUT ImageBitmap 1x1 non-transparent non-black Test timed out
-TIMEOUT Array ImageBitmap object, ImageBitmap 1x1 transparent black Test timed out
-TIMEOUT Array ImageBitmap object, ImageBitmap 1x1 non-transparent non-black Test timed out
-TIMEOUT Object ImageBitmap object, ImageBitmap 1x1 transparent black Test timed out
-TIMEOUT Object ImageBitmap object, ImageBitmap 1x1 non-transparent non-black Test timed out
-FAIL Array sparse Can't find variable: SharedWorker
-FAIL Array with non-index property Can't find variable: SharedWorker
-FAIL Object with index property and length Can't find variable: SharedWorker
-FAIL Array with circular reference Can't find variable: SharedWorker
-FAIL Object with circular reference Can't find variable: SharedWorker
-FAIL Array with identical property values Can't find variable: SharedWorker
-FAIL Object with identical property values Can't find variable: SharedWorker
-FAIL Object with property on prototype Can't find variable: SharedWorker
-FAIL Object with non-enumerable property Can't find variable: SharedWorker
-FAIL Object with non-writable property Can't find variable: SharedWorker
-FAIL Object with non-configurable property Can't find variable: SharedWorker
+FAIL structured clone to shared worker ReferenceError: Can't find variable: SharedWorker
 
index 6f74354..793da8f 100644 (file)
@@ -2,8 +2,35 @@
 <title>structured clone to shared worker</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
+<script src=/html/webappapis/structured-clone/structured-clone-battery-of-tests.js></script>
+<script src=/html/webappapis/structured-clone/structured-clone-battery-of-tests-with-transferables.js></script>
+<script src=/html/webappapis/structured-clone/structured-clone-battery-of-tests-harness.js></script>
 <div id=log></div>
 <script>
-var type = 'shared';
+  runStructuredCloneBatteryOfTests({
+    setup() {
+      const blob = new Blob([`
+        onconnect = ev => {
+          const port = ev.ports[0];
+          port.onmessage = ev => port.postMessage(ev.data, ev.data.transfer);
+        };
+      `], {type: 'text/javascript'});
+      this.blobURL = URL.createObjectURL(blob);
+      this.worker = new SharedWorker(this.blobURL);
+      this.port = this.worker.port;
+    },
+    structuredClone(data, transfer) {
+      return new Promise(resolve => {
+        this.port.addEventListener('message', function f(ev) {
+          this.port.removeEventListener('message', f);
+          resolve(ev.data.data);
+        }.bind(this));
+        this.port.start();
+        this.port.postMessage({data, transfer}, transfer);
+      });
+    },
+    teardown() {
+      URL.revokeObjectURL(this.blobURL);
+    }
+  });
 </script>
-<script src="common.js"></script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/shared.js b/LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/shared.js
deleted file mode 100644 (file)
index 372a9ec..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-importScripts('worker-common.js');
-onconnect = function(connect_ev) {
-  connect_ev.ports[0].onmessage = function(message_ev) {
-    check(message_ev.data, this);
-  };
-};
index 3bc4f81..f22254e 100644 (file)
@@ -14,9 +14,5 @@ Property values requiring vendor prefixes:
 None
 ------------------------------------------------------------------------
 List of files:
-/LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/common.js
 /LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/dedicated.html
-/LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/dedicated.js
 /LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/shared.html
-/LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/shared.js
-/LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/worker-common.js
diff --git a/LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/worker-common.js b/LayoutTests/imported/w3c/web-platform-tests/workers/semantics/structured-clone/worker-common.js
deleted file mode 100644 (file)
index fd63ff5..0000000
+++ /dev/null
@@ -1,1018 +0,0 @@
-var msg = decodeURIComponent(location.hash.substr(1));
-
-var log = [];
-function check_true(actual, msg) {
-  if (actual !== true) {
-    log.push(msg);
-    return false;
-  }
-  return true;
-}
-
-function check_Blob(msg, input, port, expect_File, orig_input) {
-  expect_File = !!expect_File;
-  orig_input = orig_input || input;
-  try {
-    var expected;
-    switch (msg) {
-      case 'Blob basic':
-      case 'File basic':
-        expected = [0x66, 0x6F, 0x6F];
-        expected.type = 'text/x-bar';
-        if (expect_File) {
-          expected.name = 'bar';
-          expected.lastModified = 42;
-        }
-        break;
-      case 'Blob unpaired high surrogate (invalid utf-8)':
-        expected = [0xED, 0xA0, 0x80];
-        expected.type = '';
-        break;
-      case 'Blob unpaired low surrogate (invalid utf-8)':
-        expected = [0xED, 0xB0, 0x80];
-        expected.type = '';
-        break;
-      case 'Blob paired surrogates (invalid utf-8)':
-        expected = [0xED, 0xA0, 0x80, 0xED, 0xB0, 0x80];
-        expected.type = '';
-        break;
-      case 'Blob empty':
-        expected = [];
-        expected.type = '';
-        break;
-      case 'Blob NUL':
-        var expected = [0x00];
-        expected.type = '';
-        break;
-      default:
-        check_true(false, 'check_Blob: unknown test');
-        return;
-        break;
-    }
-    if (check_true(input instanceof Blob, 'input instanceof Blob') &&
-        check_true((input instanceof File) == expect_File, '(input instanceof File) == expect_File') &&
-        check_true(input.size === expected.length, 'input.size === expected.length') &&
-        check_true(input.type === expected.type, 'input.type === expected.type')) {
-      if (!expect_File || (check_true(input.name === expected.name, 'input.name === expected.name') &&
-                           check_true(input.lastModified === expected.lastModified))) {
-        var reader = new FileReader();
-        var read_done = function() {
-          try {
-            var result = reader.result;
-            check_true(result.byteLength === expected.length, 'result.byteLength === expected.length')
-            var view = new DataView(result);
-            for (var i = 0; i < result.byteLength; ++i) {
-              check_true(view.getUint8(i) === expected[i], 'view.getUint8('+i+') === expected['+i+']')
-            }
-            if (log.length === 0) {
-              port.postMessage(orig_input);
-            } else {
-              port.postMessage('FAIL '+log);
-            }
-            close();
-          } catch(ex) {
-            postMessage('FAIL '+ex);
-            close();
-          }
-        }
-        var read_error = function() { port.postMessage('FAIL (got FileReader error)'); close(); };
-        reader.readAsArrayBuffer(input);
-        reader.onload = read_done;
-        reader.onabort = reader.onerror = read_error;
-      }
-    } else {
-      port.postMessage('FAIL '+log);
-      close();
-    }
-  } catch(ex) {
-    postMessage('FAIL '+ex);
-    close();
-  }
-}
-
-function check_ImageData(input, expected) {
-  if (check_true(input instanceof ImageData, 'input instanceof ImageData') &&
-      check_true(input.width === expected.width, 'input.width === '+expected.width) &&
-      check_true(input.height === expected.height, 'input.height === '+expected.height) &&
-      check_true(input.data instanceof Uint8ClampedArray, 'input.data instanceof Uint8ClampedArray') &&
-      check_true(input.data.length === expected.data.length, 'input.data.length === '+expected.data.length) &&
-      check_true(!('CanvasPixelArray' in self), "!('CanvasPixelArray' in self)")) {
-    for (var i = 0; i < input.length; ++i) {
-      if (!(check_true(input.data[i] === expected.data[i], 'input.data['+i+'] === '+expected.data[i]))) {
-        return false;
-      }
-    }
-    return true;
-  }
-  return false;
-}
-
-function check_ImageBitmap(input, expected) {
-  return check_true(input instanceof ImageBitmap, 'input instanceof ImageBitmap');
-  // XXX paint it on a proxy canvas and check the data
-}
-
-function check_RegExp(msg, input) {
-  // XXX ES6 spec doesn't define exact serialization for `source` (it allows several ways to escape)
-  switch (msg) {
-    case 'RegExp flags and lastIndex':
-      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
-             check_true(input.source === 'foo', "input.source === 'foo'") &&
-             check_true(input.global === true, "input.global === true") &&
-             check_true(input.ignoreCase === true, "input.ignoreCase === true") &&
-             check_true(input.multiline === true, "input.multiline === true") &&
-             check_true(input.lastIndex === 0, "input.lastIndex === 0");
-      break;
-    case 'RegExp sticky flag':
-      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
-             check_true(input.source === 'foo', "input.source === 'foo'") &&
-             check_true(input.global === false, "input.global === false") &&
-             check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
-             check_true(input.multiline === false, "input.multiline === false") &&
-             check_true(input.sticky === true, "input.sticky === true") &&
-             check_true(input.unicode === false, "input.unicode === false") &&
-             check_true(input.lastIndex === 0, "input.lastIndex === 0");
-      break;
-    case 'RegExp unicode flag':
-      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
-             check_true(input.source === 'foo', "input.source === 'foo'") &&
-             check_true(input.global === false, "input.global === false") &&
-             check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
-             check_true(input.multiline === false, "input.multiline === false") &&
-             check_true(input.sticky === false, "input.sticky === false") &&
-             check_true(input.unicode === true, "input.unicode === true") &&
-             check_true(input.lastIndex === 0, "input.lastIndex === 0");
-      break;
-    case 'RegExp empty':
-      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
-             check_true(input.source === '(?:)', "input.source === '(?:)'") &&
-             check_true(input.global === false, "input.global === false") &&
-             check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
-             check_true(input.multiline === false, "input.multiline === false") &&
-             check_true(input.lastIndex === 0, "input.lastIndex === 0");
-      break;
-    case 'RegExp slash':
-      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
-             check_true(input.source === '\\/', "input.source === '\\\\/'") &&
-             check_true(input.global === false, "input.global === false") &&
-             check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
-             check_true(input.multiline === false, "input.multiline === false") &&
-             check_true(input.lastIndex === 0, "input.lastIndex === 0");
-      break;
-    case 'RegExp new line':
-      return check_true(input instanceof RegExp, "input instanceof RegExp") &&
-             check_true(input.source === '\\n', "input.source === '\\\\n'") &&
-             check_true(input.global === false, "input.global === false") &&
-             check_true(input.ignoreCase === false, "input.ignoreCase === false") &&
-             check_true(input.multiline === false, "input.multiline === false") &&
-             check_true(input.lastIndex === 0, "input.lastIndex === 0");
-      break;
-    default:
-      check_true(false, 'check_RegExp: unknown test');
-      return false;
-      break;
-  }
-}
-
-function check_FileList(msg, input) {
-  try {
-    return check_true(input instanceof FileList, 'input instanceof FileList') &&
-           check_true(input.length === 0, 'input.length === 0');
-  } catch(ex) {
-    return check_true(false, ex);
-  }
-}
-
-function check(input, port) {
-  try {
-    switch (msg) {
-      case 'primitive undefined':
-        if (check_true(input === undefined, 'input === undefined')) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive null':
-        if (check_true(input === null, 'input === null')) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive true':
-        if (check_true(input === true, 'input === true')) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive false':
-        if (check_true(input === false, 'input === false')) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive string, empty string':
-        if (check_true(input === '', "input === ''")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive string, lone high surrogate':
-        if (check_true(input === '\uD800', "input === '\uD800'")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive string, lone low surrogate':
-        if (check_true(input === '\uDC00', "input === '\uDC00'")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive string, NUL':
-        if (check_true(input === '\u0000', "input === '\u0000'")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive string, astral character':
-        if (check_true(input === '\uDBFF\uDFFD', "input === '\uDBFF\uDFFD'")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive number, 0.2':
-        if (check_true(input === 0.2, "input === 0.2")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive number, 0':
-        if (check_true(input === 0, "input === 0") &&
-            check_true(1/input === Infinity, "1/input === Infinity")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive number, -0':
-        if (check_true(input === 0, "input === 0") &&
-            check_true(1/input === -Infinity, "1/input === -Infinity")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive number, NaN':
-        if (check_true(input !== input, "input !== input")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive number, Infinity':
-        if (check_true(input === Infinity, "input === Infinity")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive number, -Infinity':
-        if (check_true(input === -Infinity, "input === -Infinity")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive number, 9007199254740992':
-        if (check_true(input === 9007199254740992, "input === 9007199254740992")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive number, -9007199254740992':
-        if (check_true(input === -9007199254740992, "input === -9007199254740992")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive number, 9007199254740994':
-        if (check_true(input === 9007199254740994, "input === 9007199254740994")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'primitive number, -9007199254740994':
-        if (check_true(input === -9007199254740994, "input === -9007199254740994")) {
-          port.postMessage(input);
-          close();
-          break;
-        }
-      case 'Array primitives':
-        if (check_true(input instanceof Array, 'input instanceof Array') &&
-            check_true(input.length === 19, 'input.length === 19') &&
-            check_true(input[0] === undefined, 'input[0] === undefined') &&
-            check_true(input[1] === null, 'input[1] === null') &&
-            check_true(input[2] === true, 'input[2] === true') &&
-            check_true(input[3] === false, 'input[3] === false') &&
-            check_true(input[4] === '', "input[4] === ''") &&
-            check_true(input[5] === '\uD800', "input[5] === '\\uD800'") &&
-            check_true(input[6] === '\uDC00', "input[6] === '\\uDC00'") &&
-            check_true(input[7] === '\u0000', "input[7] === '\\u0000'") &&
-            check_true(input[8] === '\uDBFF\uDFFD', "input[8] === '\\uDBFF\\uDFFD'") &&
-            check_true(input[9] === 0.2, "input[9] === 0.2") &&
-            check_true(1/input[10] === Infinity, "1/input[10] === Infinity") &&
-            check_true(1/input[11] === -Infinity, "1/input[11] === -Infinity") &&
-            check_true(input[12] !== input[11], "input[12] !== input[11]") &&
-            check_true(input[13] === Infinity, "input[13] === Infinity") &&
-            check_true(input[14] === -Infinity, "input[14] === -Infinity") &&
-            check_true(input[15] === 9007199254740992, "input[15] === 9007199254740992") &&
-            check_true(input[16] === -9007199254740992, "input[16] === -9007199254740992") &&
-            check_true(input[17] === 9007199254740994, "input[17] === 9007199254740994") &&
-            check_true(input[18] === -9007199254740994, "input[18] === -9007199254740994")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Object primitives':
-        (function() {
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-              check_true(input['undefined'] === undefined, "input['undefined'] === undefined") &&
-              check_true(input['null'] === null, "input['null'] === null") &&
-              check_true(input['true'] === true, "input['true'] === true") &&
-              check_true(input['false'] === false, "input['false'] === false") &&
-              check_true(input['empty'] === '', "input['empty'] === ''") &&
-              check_true(input['high surrogate'] === '\uD800', "input['high surrogate'] === '\uD800'") &&
-              check_true(input['low surrogate'] === '\uDC00', "input['low surrogate'] === '\uDC00'") &&
-              check_true(input['nul'] === '\u0000', "input['nul'] === '\u0000'") &&
-              check_true(input['astral'] === '\uDBFF\uDFFD', "input['astral'] === '\uDBFF\uDFFD'") &&
-              check_true(input['0.2'] === 0.2, "input['0.2'] === 0.2") &&
-              check_true(1/input['0'] === Infinity, "1/input['0'] === Infinity") &&
-              check_true(1/input['-0'] === -Infinity, "1/input['-0'] === -Infinity") &&
-              check_true(input['NaN'] !== input['NaN'], "input['NaN'] !== input['NaN']") &&
-              check_true(input['Infinity'] === Infinity, "input['Infinity'] === Infinity") &&
-              check_true(input['-Infinity'] === -Infinity, "input['-Infinity'] === -Infinity") &&
-              check_true(input['9007199254740992'] === 9007199254740992, "input['9007199254740992'] === 9007199254740992") &&
-              check_true(input['-9007199254740992'] === -9007199254740992, "input['-9007199254740992'] === -9007199254740992") &&
-              check_true(input['9007199254740994'] === 9007199254740994, "input['9007199254740994'] === 9007199254740994") &&
-              check_true(input['-9007199254740994'] === -9007199254740994, "input['9007199254740994'] === -9007199254740994")) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-            }
-            if (check_true(i === 19, 'i === 19')) {
-              port.postMessage(input);
-              close();
-            }
-          }
-        })();
-        break;
-      case 'Boolean true':
-        if (check_true(input instanceof Boolean, "input instanceof Boolean") &&
-            check_true(String(input) === 'true', "String(input) === 'true'")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Boolean false':
-        if (check_true(input instanceof Boolean, "input instanceof Boolean") &&
-            check_true(String(input) === 'false', "String(input) === 'false'")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array Boolean objects':
-        (function() {
-          if (check_true(input instanceof Array, 'input instanceof Array') &&
-              check_true(input.length === 2, 'input.length === 2') &&
-              check_true(String(input[0]) === 'true', "String(input[0]) === 'true'") &&
-              check_true(String(input[1]) === 'false', "String(input[1]) === 'false'")) {
-            for (var i = 0; i < input.length; ++i) {
-              if (!check_true(input[i] instanceof Boolean, 'input['+i+'] instanceof Boolean'))
-                return;
-            }
-            port.postMessage(input);
-            close();
-          }
-        })();
-        break;
-      case 'Object Boolean objects':
-        (function() {
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-              check_true(String(input['true']) === 'true', "String(input['true']) === 'true'") &&
-              check_true(String(input['false']) === 'false', "String(input['false']) === 'false'")) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-              if (!check_true(input[x] instanceof Boolean, 'input['+x+'] instanceof Boolean'))
-                return;
-            }
-            if (check_true(i === 2, 'i === 2')) {
-              port.postMessage(input);
-              close();
-            }
-          }
-        })();
-        break;
-      case 'String empty string':
-        if (check_true(input instanceof String, "input instanceof String") &&
-            check_true(String(input) === '', "String(input) === ''")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'String lone high surrogate':
-        if (check_true(input instanceof String, "input instanceof String") &&
-            check_true(String(input) === '\uD800', "String(input) === '\\uD800'")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'String lone low surrogate':
-        if (check_true(input instanceof String, "input instanceof String") &&
-            check_true(String(input) === '\uDC00', "String(input) === '\\uDC00'")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'String NUL':
-        if (check_true(input instanceof String, "input instanceof String") &&
-            check_true(String(input) === '\u0000', "String(input) === '\\u0000'")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'String astral character':
-        if (check_true(input instanceof String, "input instanceof String") &&
-            check_true(String(input) === '\uDBFF\uDFFD', "String(input) === '\\uDBFF\\uDFFD'")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array String objects':
-        (function() {
-          if (check_true(input instanceof Array, 'input instanceof Array') &&
-              check_true(input.length === 5, 'input.length === 5') &&
-              check_true(String(input[0]) === '', "String(input[0]) === ''") &&
-              check_true(String(input[1]) === '\uD800', "String(input[1]) === '\\uD800'") &&
-              check_true(String(input[2]) === '\uDC00', "String(input[1]) === '\\uDC00'") &&
-              check_true(String(input[3]) === '\u0000', "String(input[2]) === '\\u0000'") &&
-              check_true(String(input[4]) === '\uDBFF\uDFFD', "String(input[3]) === '\\uDBFF\\uDFFD'")) {
-            for (var i = 0; i < input.length; ++i) {
-              if (!check_true(input[i] instanceof String, 'input['+i+'] instanceof String'))
-                return;
-            }
-            port.postMessage(input);
-            close();
-          }
-        })();
-        break;
-      case 'Object String objects':
-        (function() {
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-              check_true(String(input['empty']) === '', "String(input['empty']) === ''") &&
-              check_true(String(input['high surrogate']) === '\uD800', "String(input['high surrogate']) === '\\uD800'") &&
-              check_true(String(input['low surrogate']) === '\uDC00', "String(input['low surrogate']) === '\\uDC00'") &&
-              check_true(String(input['nul']) === '\u0000', "String(input['nul']) === '\\u0000'") &&
-              check_true(String(input['astral']) === '\uDBFF\uDFFD', "String(input['astral']) === '\\uDBFF\\uDFFD'")) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-              if (!check_true(input[x] instanceof String, 'input['+x+'] instanceof Boolean'))
-                return;
-            }
-            if (check_true(i === 5, 'i === 5')) {
-              port.postMessage(input);
-              close();
-            }
-          }
-        })();
-        break;
-      case 'Number 0.2':
-        if (check_true(input instanceof Number, "input instanceof Number") &&
-            check_true(Number(input) === 0.2, "Number(input) === 0.2")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Number 0':
-        if (check_true(input instanceof Number, "input instanceof Number") &&
-            check_true(1/Number(input) === Infinity, "1/Number(input) === Infinity")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Number -0':
-        if (check_true(input instanceof Number, "input instanceof Number") &&
-            check_true(1/Number(input) === -Infinity, "1/Number(input) === -Infinity")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Number NaN':
-        if (check_true(input instanceof Number, "input instanceof Number") &&
-            check_true(Number(input) !== Number(input), "Number(input) !== Number(input)")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Number Infinity':
-        if (check_true(input instanceof Number, "input instanceof Number") &&
-            check_true(Number(input) === Infinity, "Number(input) === Infinity")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Number -Infinity':
-        if (check_true(input instanceof Number, "input instanceof Number") &&
-            check_true(Number(input) === -Infinity, "Number(input) === -Infinity")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Number 9007199254740992':
-        if (check_true(input instanceof Number) &&
-            check_true(Number(input) === 9007199254740992, "Number(input) === 9007199254740992")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Number -9007199254740992':
-        if (check_true(input instanceof Number, "input instanceof Number") &&
-            check_true(Number(input) === -9007199254740992, "Number(input) === -9007199254740992")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Number 9007199254740994':
-        if (check_true(input instanceof Number, "input instanceof Number") &&
-            check_true(Number(input) === 9007199254740994, "Number(input) === 9007199254740994")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Number -9007199254740994':
-        if (check_true(input instanceof Number, "input instanceof Number") &&
-            check_true(Number(input) === -9007199254740994, "Number(input) === -9007199254740994")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array Number objects':
-        (function() {
-          if (check_true(input instanceof Array, 'input instanceof Array') &&
-              check_true(input.length === 10, 'input.length === 10') &&
-              check_true(Number(input[0]) === 0.2, "Number(input[0]) === 0.2") &&
-              check_true(1/Number(input[1]) === Infinity, "1/Number(input[1]) === Infinity") &&
-              check_true(1/Number(input[2]) === -Infinity, "1/Number(input[2]) === -Infinity") &&
-              check_true(Number(input[3]) !== Number(input[3]), "Number(input[3]) !== Number(input[3])") &&
-              check_true(Number(input[4]) === Infinity, "Number(input[4]) === Infinity") &&
-              check_true(Number(input[5]) === -Infinity, "Number(input[5]) === -Infinity") &&
-              check_true(Number(input[6]) === 9007199254740992, "Number(input[6]) === 9007199254740992") &&
-              check_true(Number(input[7]) === -9007199254740992, "Number(input[7]) === -9007199254740992") &&
-              check_true(Number(input[8]) === 9007199254740994, "Number(input[8]) === 9007199254740994") &&
-              check_true(Number(input[9]) === -9007199254740994, "Number(input[9]) === -9007199254740994")) {
-            for (var i = 0; i < input.length; ++i) {
-              if (!check_true(input[i] instanceof Number, 'input['+i+'] instanceof Number'))
-                return;
-            }
-            port.postMessage(input);
-            close();
-          }
-        })();
-        break;
-      case 'Object Number objects':
-        (function() {
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-              check_true(Number(input['0.2']) === 0.2, "Number(input['0.2']) === 0.2") &&
-              check_true(1/Number(input['0']) === Infinity, "1/Number(input['0']) === Infinity") &&
-              check_true(1/Number(input['-0']) === -Infinity, "1/Number(input['-0']) === -Infinity") &&
-              check_true(Number(input['NaN']) !== Number(input['NaN']), "Number(input['NaN']) !== Number(input['NaN'])") &&
-              check_true(Number(input['Infinity']) === Infinity, "Number(input['Infinity']) === Infinity") &&
-              check_true(Number(input['-Infinity']) === -Infinity, "Number(input['-Infinity']) === -Infinity") &&
-              check_true(Number(input['9007199254740992']) === 9007199254740992, "Number(input['9007199254740992']) === 9007199254740992") &&
-              check_true(Number(input['-9007199254740992']) === -9007199254740992, "Number(input['-9007199254740992']) === -9007199254740992") &&
-              check_true(Number(input['9007199254740994']) === 9007199254740994, "Number(input['9007199254740994']) === 9007199254740994") &&
-              check_true(Number(input['-9007199254740994']) === -9007199254740994, "Number(input['-9007199254740994']) === -9007199254740994")) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-              if (!check_true(input[x] instanceof Number, 'input['+x+'] instanceof Number'))
-                return;
-            }
-            if (check_true(i === 10, 'i === 10')) {
-              port.postMessage(input);
-              close();
-            }
-          }
-        })();
-        break;
-      case 'Date 0':
-        if (check_true(input instanceof Date, "input instanceof Date") &&
-            check_true(1/Number(input) === 1/Number(new Date(0)), "1/Number(input) === 1/Number(new Date(0))")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Date -0':
-        if (check_true(input instanceof Date, "input instanceof Date") &&
-            check_true(1/Number(input) === 1/Number(new Date(-0)), "1/Number(input) === 1/Number(new Date(-0))")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Date -8.64e15':
-        if (check_true(input instanceof Date, "input instanceof Date") &&
-            check_true(Number(input) === -8.64e15, "Number(input) === -8.64e15")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Date 8.64e15':
-        if (check_true(input instanceof Date, "input instanceof Date") &&
-            check_true(Number(input) === 8.64e15, "Number(input) === 8.64e15")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array Date objects':
-        (function() {
-          if (check_true(input instanceof Array, 'input instanceof Array') &&
-              check_true(input.length === 4, 'input.length === 4') &&
-              check_true(1/Number(input[0]) === 1/new Date(0), '1/Number(input[0]) === 1/new Date(0)') &&
-              check_true(1/Number(input[1]) === 1/new Date(-0), '1/Number(input[1]) === 1/new Date(-0)') &&
-              check_true(Number(input[2]) === -8.64e15, 'Number(input[2]) === -8.64e15') &&
-              check_true(Number(input[3]) === 8.64e15, 'Number(input[3]) === 8.64e15')) {
-            for (var i = 0; i < input.length; ++i) {
-              if (!check_true(input[i] instanceof Date, 'input['+i+'] instanceof Date'))
-                return;
-            }
-            port.postMessage(input);
-            close();
-          }
-        })();
-        break;
-      case 'Object Date objects':
-        (function() {
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-              check_true(1/Number(input['0']) === 1/new Date(0), "1/Number(input['0']) === 1/new Date(0)") &&
-              check_true(1/Number(input['-0']) === 1/new Date(-0), "1/Number(input[1]) === 1/new Date(-0)") &&
-              check_true(Number(input['-8.64e15']) === -8.64e15, "Number(input['-8.64e15']) === -8.64e15") &&
-              check_true(Number(input['8.64e15']) === 8.64e15, "Number(input['8.64e15']) === 8.64e15")) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-              if (!check_true(input[x] instanceof Date, 'input['+x+'] instanceof Date'))
-                return;
-            }
-            port.postMessage(input);
-            close();
-          }
-        })();
-        break;
-      case 'RegExp flags and lastIndex':
-      case 'RegExp empty':
-      case 'RegExp slash':
-      case 'RegExp new line':
-        if (check_RegExp(msg, input)) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array RegExp object, RegExp flags and lastIndex':
-      case 'Array RegExp object, RegExp empty':
-      case 'Array RegExp object, RegExp slash':
-      case 'Array RegExp object, RegExp new line':
-        if (check_true(input instanceof Array, 'input instanceof Array') &&
-            check_true(input.length === 1, 'input.length === 1') &&
-            check_RegExp(msg.substr('Array RegExp object, '.length), input[0])) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Object RegExp object, RegExp flags and lastIndex':
-      case 'Object RegExp object, RegExp empty':
-      case 'Object RegExp object, RegExp slash':
-      case 'Object RegExp object, RegExp new line':
-        (function() {
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-              check_RegExp(msg.substr('Object RegExp object, '.length), input['x'])) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-            }
-            if (check_true(i === 1, 'i === 1')) {
-              port.postMessage(input);
-              close();
-            }
-          }
-        })();
-        break;
-      case 'Blob basic':
-      case 'Blob unpaired high surrogate (invalid utf-8)':
-      case 'Blob unpaired low surrogate (invalid utf-8)':
-      case 'Blob paired surrogates (invalid utf-8)':
-      case 'Blob empty':
-      case 'Blob NUL':
-        check_Blob(msg, input, port);
-        // no postMessage or close here, check_Blob takes care of that
-        break;
-      case 'Array Blob object, Blob basic':
-      case 'Array Blob object, Blob unpaired high surrogate (invalid utf-8)':
-      case 'Array Blob object, Blob unpaired low surrogate (invalid utf-8)':
-      case 'Array Blob object, Blob paired surrogates (invalid utf-8)':
-      case 'Array Blob object, Blob empty':
-      case 'Array Blob object, Blob NUL':
-        if (check_true(input instanceof Array, 'input instanceof Array') &&
-            check_true(input.length === 1, 'input.length === 1')) {
-          check_Blob(msg.substr('Array Blob object, '.length), input[0], port, false, input);
-          // no postMessage or close here, check_Blob takes care of that
-        }
-        break;
-      case 'Object Blob object, Blob basic':
-      case 'Object Blob object, Blob unpaired high surrogate (invalid utf-8)':
-      case 'Object Blob object, Blob unpaired low surrogate (invalid utf-8)':
-      case 'Object Blob object, Blob paired surrogates (invalid utf-8)':
-      case 'Object Blob object, Blob empty':
-      case 'Object Blob object, Blob NUL':
-        (function() {
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)')) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-            }
-            if (check_true(i === 1, 'i === 1')) {
-              check_Blob(msg.substr('Object Blob object, '.length), input['x'], port, false, input);
-              // no postMessage or close here, check_Blob takes care of that
-            }
-          }
-        })();
-        break;
-      case 'File basic':
-        check_Blob(msg, input, port, true);
-        // no postMessage or close here, check_Blob takes care of that
-        break;
-      case 'FileList empty':
-        if (check_FileList(msg, input)) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array FileList object, FileList empty':
-        if (check_true(input instanceof Array, 'input instanceof Array') &&
-            check_true(input.length === 1, 'input.length === 1') &&
-            check_FileList(msg.substr('Array FileList object, '.length), input[0])) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Object FileList object, FileList empty':
-        (function() {
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-              check_FileList(msg.substr('Array FileList object, '.length), input['x'])) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-            }
-            if (check_true(i === 1, 'i === 1')) {
-              port.postMessage(input);
-              close();
-            }
-          }
-        })();
-        break;
-      case 'ImageData 1x1 transparent black':
-        if (check_ImageData(input, {width:1, height:1, data:[0,0,0,0]})) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'ImageData 1x1 non-transparent non-black':
-        if (check_ImageData(input, {width:1, height:1, data:[100, 101, 102, 103]})) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array ImageData object, ImageData 1x1 transparent black':
-        if (check_true(input instanceof Array, 'input instanceof Array') &&
-            check_true(input.length === 1, 'input.length === 1') &&
-            check_ImageData(input[0], {width:1, height:1, data:[0,0,0,0]})) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array ImageData object, ImageData 1x1 non-transparent non-black':
-        if (check_true(input instanceof Array, 'input instanceof Array') &&
-            check_true(input.length === 1, 'input.length === 1') &&
-            check_ImageData(input[0], {width:1, height:1, data:[100, 101, 102, 103]})) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Object ImageData object, ImageData 1x1 transparent black':
-        (function(){
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-              check_ImageData(input['x'], {width:1, height:1, data:[0,0,0,0]})) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-            }
-            if (check_true(i === 1, 'i === 1')) {
-              port.postMessage(input);
-              close();
-            }
-          }
-        })();
-        break;
-      case 'Object ImageData object, ImageData 1x1 non-transparent non-black':
-        (function() {
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-              check_ImageData(input['x'], {width:1, height:1, data:[100, 101, 102, 103]})) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-            }
-            if (check_true(i === 1, 'i === 1')) {
-              port.postMessage(input);
-              close();
-            }
-          }
-        })();
-        break;
-      case 'ImageBitmap 1x1 transparent black':
-        if (check_ImageBitmap(input, {width:1, height:1, data:[0, 0, 0, 0]})) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'ImageBitmap 1x1 non-transparent non-black':
-        if (check_ImageBitmap(input, {width:1, height:1, data:[100, 101, 102, 103]})) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array ImageBitmap object, ImageBitmap 1x1 transparent black':
-        if (check_true(input instanceof Array, 'input instanceof Array') &&
-            check_true(input.length === 1, 'input.length === 1') &&
-            check_ImageBitmap(input[0], {width:1, height:1, data:[0, 0, 0, 0]})) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array ImageBitmap object, ImageBitmap 1x1 non-transparent non-black':
-        if (check_true(input instanceof Array, 'input instanceof Array') &&
-            check_true(input.length === 1, 'input.length === 1') &&
-            check_ImageBitmap(input[0], {width:1, height:1, data:[100, 101, 102, 103]})) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Object ImageBitmap object, ImageBitmap 1x1 transparent black':
-        (function() {
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-              check_ImageBitmap(input['x'], {width:1, height:1, data:[0, 0, 0, 0]})) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-            }
-            if (check_true(i === 1, 'i === 1')) {
-              port.postMessage(input);
-              close();
-            }
-          }
-        })();
-        break;
-      case 'Object ImageBitmap object, ImageBitmap 1x1 non-transparent non-black':
-        (function() {
-          if (check_true(input instanceof Object, 'input instanceof Object') &&
-              check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-              check_ImageBitmap(input['x'], {width:1, height:1, data:[100, 101, 102, 103]})) {
-            var i = 0;
-            for (var x in input) {
-              i++;
-            }
-            if (check_true(i === 1, 'i === 1')) {
-              port.postMessage(input);
-              close();
-            }
-          }
-        })();
-        break;
-      case 'Array sparse':
-        (function() {
-          if (check_true(input instanceof Array, 'input instanceof Array') &&
-              check_true(input.length === 10, 'input.length === 10')) {
-            for (var x in input) {
-              check_true(false, 'unexpected enumerable property '+x);
-              return;
-            }
-            port.postMessage(input);
-            close();
-          }
-        })();
-        break;
-      case 'Array with non-index property':
-        if (check_true(input instanceof Array, 'input instanceof Array') &&
-            check_true(input.length === 0, 'input.length === 0') &&
-            check_true(input.foo === 'bar', "input.foo === 'bar'")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Object with index property and length':
-        if (check_true(input instanceof Object, 'input instanceof Object') &&
-            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-            check_true(input[0] === 'foo', "input[0] === 'foo'") &&
-            check_true(input.length === 1, 'input.length === 1')) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array with circular reference':
-        if (check_true(input instanceof Array, 'input instanceof Array') &&
-            check_true(input.length === 1, 'input.length === 1') &&
-            check_true(input[0] === input, "input[0] === input")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Object with circular reference':
-        if (check_true(input instanceof Object, 'input instanceof Object') &&
-            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-            check_true(input['x'] === input, "input['x'] === input")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Array with identical property values':
-        if (check_true(input instanceof Array, 'input instanceof Array') &&
-            check_true(input.length === 2, 'input.length === 2') &&
-            check_true(input[0] === input[1], "input[0] === input[1]")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Object with identical property values':
-        if (check_true(input instanceof Object, 'input instanceof Object') &&
-            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-            check_true(input['x'] === input['y'], "input['x'] === input['y']")) {
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Object with property on prototype':
-      case 'Object with non-enumerable property':
-        if (check_true(input instanceof Object, 'input instanceof Object') &&
-            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-            check_true(!('foo' in input), "!('foo' in input)")) {
-          input = {};
-          Object.defineProperty(input, 'foo', {value:'bar', enumerable:false, writable:true, configurable:true});
-          port.postMessage(input);
-          close();
-        }
-        break;
-      case 'Object with non-writable property':
-        if (check_true(input instanceof Object, 'input instanceof Object') &&
-            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-            check_true(input.foo === 'bar', "input.foo === bar")) {
-          input.foo += ' baz';
-          if (check_true(input.foo === 'bar baz', "input.foo === 'bar baz'")) {
-            input = {};
-            Object.defineProperty(input, 'foo', {value:'bar', enumerable:true, writable:false, configurable:true});
-            port.postMessage(input);
-            close();
-          }
-        }
-        break;
-      case 'Object with non-configurable property':
-        if (check_true(input instanceof Object, 'input instanceof Object') &&
-            check_true(!(input instanceof Array), '!(input instanceof Array)') &&
-            check_true(input.foo === 'bar', "input.foo === bar")) {
-          delete input.foo;
-          if (check_true(!('foo' in input), "!('foo' in input)")) {
-            input = {};
-            Object.defineProperty(input, 'foo', {value:'bar', enumerable:true, writable:true, configurable:false});
-            port.postMessage(input);
-            close();
-          }
-        }
-        break;
-
-      default:
-        port.postMessage('FAIL: unknown test');
-        close();
-    }
-    if (log.length > 0) {
-      port.postMessage('FAIL '+log);
-      close();
-    }
-  } catch (ex) {
-    port.postMessage('FAIL '+ex);
-    close();
-  }
-}
index 0cc7583..6b89d43 100644 (file)
@@ -1,3 +1,23 @@
+2018-05-21  Chris Dumez  <cdumez@apple.com>
+
+        File's structured serialization should serialize lastModified attribute
+        https://bugs.webkit.org/show_bug.cgi?id=185773
+
+        Reviewed by Youenn Fablet.
+
+        Update our implementation for the stuctured serialization of a File to include
+        its lastModified attribute, as per:
+        - https://w3c.github.io/FileAPI/#file-section
+
+        No new tests, rebaselined existing test.
+
+        * bindings/js/SerializedScriptValue.cpp:
+        (WebCore::CloneSerializer::write):
+        (WebCore::CloneDeserializer::readFile):
+        * fileapi/File.cpp:
+        (WebCore::File::File):
+        * fileapi/File.h:
+
 2018-05-21  Zalan Bujtas  <zalan@apple.com>
 
         [LFC] Add FormattingContext::validateGeometryConstraintsAfterLayout
index b018081..11f7664 100644 (file)
@@ -278,8 +278,9 @@ static unsigned countUsages(CryptoKeyUsageBitmap usages)
  * Version 4. added support for serializing non-index properties of arrays.
  * Version 5. added support for Map and Set types.
  * Version 6. added support for 8-bit strings.
+ * Version 7. added support for File's lastModified attribute.
  */
-static const unsigned CurrentVersion = 6;
+static const unsigned CurrentVersion = 7;
 static const unsigned TerminatorTag = 0xFFFFFFFF;
 static const unsigned StringPoolTag = 0xFFFFFFFE;
 static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
@@ -363,7 +364,7 @@ static const unsigned StringDataIs8BitFlag = 0x80000000;
  *    FileTag FileData
  *
  * FileData :-
- *    <path:StringData> <url:StringData> <type:StringData> <name:StringData>
+ *    <path:StringData> <url:StringData> <type:StringData> <name:StringData> <lastModified:double>
  *
  * FileList :-
  *    FileListTag <length:uint32_t>(<file:FileData>){length}
@@ -1236,6 +1237,7 @@ private:
         write(file.url());
         write(file.type());
         write(file.name());
+        write(static_cast<double>(file.lastModifiedOverride().value_or(-1)));
     }
 
 #if ENABLE(SUBTLE_CRYPTO)
@@ -2036,6 +2038,14 @@ private:
         CachedStringRef name;
         if (!readStringData(name))
             return false;
+        std::optional<int64_t> optionalLastModified;
+        if (m_version > 6) {
+            double lastModified;
+            if (!read(lastModified))
+                return false;
+            if (lastModified >= 0)
+                optionalLastModified = lastModified;
+        }
 
         // If the blob URL for this file has an associated blob file path, prefer that one over the "built-in" path.
         String filePath = blobFilePathForBlobURL(url->string());
@@ -2043,7 +2053,7 @@ private:
             filePath = path->string();
 
         if (m_isDOMGlobalObject)
-            file = File::deserialize(filePath, URL(URL(), url->string()), type->string(), name->string());
+            file = File::deserialize(filePath, URL(URL(), url->string()), type->string(), name->string(), optionalLastModified);
         return true;
     }
 
index e695aa5..e7b0d3e 100644 (file)
@@ -63,10 +63,11 @@ File::File(const String& path, const String& nameOverride)
     ThreadableBlobRegistry::registerFileBlobURL(m_internalURL, path, m_type);
 }
 
-File::File(DeserializationContructor, const String& path, const URL& url, const String& type, const String& name)
+File::File(DeserializationContructor, const String& path, const URL& url, const String& type, const String& name, const std::optional<int64_t>& lastModified)
     : Blob(deserializationContructor, url, type, -1, path)
     , m_path(path)
     , m_name(name)
+    , m_lastModifiedDateOverride(lastModified)
 {
 }
 
@@ -80,7 +81,7 @@ static BlobPropertyBag convertPropertyBag(const File::PropertyBag& initialBag)
 File::File(Vector<BlobPartVariant>&& blobPartVariants, const String& filename, const PropertyBag& propertyBag)
     : Blob(WTFMove(blobPartVariants), convertPropertyBag(propertyBag))
     , m_name(filename)
-    , m_overrideLastModifiedDate(propertyBag.lastModified.value_or(WallTime::now().secondsSinceEpoch().milliseconds()))
+    , m_lastModifiedDateOverride(propertyBag.lastModified.value_or(WallTime::now().secondsSinceEpoch().milliseconds()))
 {
 }
 
@@ -96,17 +97,17 @@ File::File(const File& file, const String& name)
     , m_path(file.path())
     , m_relativePath(file.relativePath())
     , m_name(!name.isNull() ? name : file.name())
-    , m_overrideLastModifiedDate(file.m_overrideLastModifiedDate)
+    , m_lastModifiedDateOverride(file.m_lastModifiedDateOverride)
     , m_isDirectory(file.isDirectory())
 {
 }
 
-double File::lastModified() const
+int64_t File::lastModified() const
 {
-    if (m_overrideLastModifiedDate)
-        return m_overrideLastModifiedDate.value();
+    if (m_lastModifiedDateOverride)
+        return m_lastModifiedDateOverride.value();
 
-    double result;
+    int64_t result;
 
     // FIXME: This does sync-i/o on the main thread and also recalculates every time the method is called.
     // The i/o should be performed on a background thread,
index f797c4a..575f0e7 100644 (file)
@@ -38,7 +38,7 @@ class URL;
 class File final : public Blob {
 public:
     struct PropertyBag : BlobPropertyBag {
-        std::optional<long long> lastModified;
+        std::optional<int64_t> lastModified;
     };
 
     static Ref<File> create(const String& path)
@@ -52,9 +52,9 @@ public:
         return adoptRef(*new File(WTFMove(blobPartVariants), filename, propertyBag));
     }
 
-    static Ref<File> deserialize(const String& path, const URL& srcURL, const String& type, const String& name)
+    static Ref<File> deserialize(const String& path, const URL& srcURL, const String& type, const String& name, const std::optional<int64_t>& lastModified = std::nullopt)
     {
-        return adoptRef(*new File(deserializationContructor, path, srcURL, type, name));
+        return adoptRef(*new File(deserializationContructor, path, srcURL, type, name, lastModified));
     }
 
     // Create a file with a name exposed to the author (via File.name and associated DOM properties) that differs from the one provided in the path.
@@ -83,7 +83,8 @@ public:
     const String& relativePath() const { return m_relativePath; }
     void setRelativePath(const String& relativePath) { m_relativePath = relativePath; }
     const String& name() const { return m_name; }
-    WEBCORE_EXPORT double lastModified() const;
+    WEBCORE_EXPORT int64_t lastModified() const; // Number of milliseconds since Epoch.
+    const std::optional<int64_t>& lastModifiedOverride() const { return m_lastModifiedDateOverride; } // Number of milliseconds since Epoch.
 
     static String contentTypeForFile(const String& path);
 
@@ -100,7 +101,7 @@ private:
     File(const Blob&, const String& name);
     File(const File&, const String& name);
 
-    File(DeserializationContructor, const String& path, const URL& srcURL, const String& type, const String& name);
+    File(DeserializationContructor, const String& path, const URL& srcURL, const String& type, const String& name, const std::optional<int64_t>& lastModified);
 
     static void computeNameAndContentType(const String& path, const String& nameOverride, String& effectiveName, String& effectiveContentType);
 #if ENABLE(FILE_REPLACEMENT)
@@ -111,7 +112,7 @@ private:
     String m_relativePath;
     String m_name;
 
-    std::optional<int64_t> m_overrideLastModifiedDate;
+    std::optional<int64_t> m_lastModifiedDateOverride;
     mutable std::optional<bool> m_isDirectory;
 };