aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/wpt/metadata/MANIFEST.json249
-rw-r--r--tests/wpt/metadata/css/CSS2/floats/hit-test-floats-002.html.ini4
-rw-r--r--tests/wpt/metadata/css/CSS2/floats/hit-test-floats-004.html.ini4
-rw-r--r--tests/wpt/metadata/css/CSS2/floats/hit-test-floats-005.html.ini4
-rw-r--r--tests/wpt/metadata/css/css-animations/AnimationEffect-updateTiming.tentative.html.ini16
-rw-r--r--tests/wpt/metadata/css/css-animations/CSSAnimation-effect.tentative.html.ini3
-rw-r--r--tests/wpt/metadata/css/css-animations/CSSAnimation-pausing.tentative.html.ini18
-rw-r--r--tests/wpt/metadata/css/css-animations/KeyframeEffect-getKeyframes.tentative.html.ini3
-rw-r--r--tests/wpt/metadata/css/css-animations/KeyframeEffect-setKeyframes.tentative.html.ini10
-rw-r--r--tests/wpt/metadata/css/css-transitions/no-transition-from-ua-to-blocking-stylesheet.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-values/round-function.html.ini60
-rw-r--r--tests/wpt/metadata/css/cssom-view/CaretPosition-001.html.ini4
-rw-r--r--tests/wpt/metadata/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini3
-rw-r--r--tests/wpt/metadata/fetch/content-type/response.window.js.ini16
-rw-r--r--tests/wpt/metadata/fetch/content-type/script.window.js.ini3
-rw-r--r--tests/wpt/metadata/fetch/nosniff/parsing-nosniff.window.js.ini6
-rw-r--r--tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_1.html.ini4
-rw-r--r--tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_3.html.ini4
-rw-r--r--tests/wpt/metadata/html/interaction/focus/the-autofocus-attribute/skip-document-with-fragment.html.ini4
-rw-r--r--tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-multi-channels.html.ini3
-rw-r--r--tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html.ini6
-rw-r--r--tests/wpt/metadata/webaudio/the-audio-api/the-audioworklet-interface/suspended-context-messageport.https.html.ini10
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/support.js20
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-across-connections.any.js72
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-across-databases.any.js72
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-mixed-scopes.any.js63
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-ordering.any.js40
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-ro-waits-for-rw.any.js26
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-rw-scopes.any.js63
-rw-r--r--tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-within-database.any.js55
-rw-r--r--tests/wpt/web-platform-tests/content-security-policy/nonce-hiding/nonces.html84
-rw-r--r--tests/wpt/web-platform-tests/css/css-animations/AnimationEffect-updateTiming.tentative.html179
-rw-r--r--tests/wpt/web-platform-tests/css/css-animations/CSSAnimation-effect.tentative.html78
-rw-r--r--tests/wpt/web-platform-tests/css/css-animations/CSSAnimation-pausing.tentative.html243
-rw-r--r--tests/wpt/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative.html221
-rw-r--r--tests/wpt/web-platform-tests/css/css-animations/KeyframeEffect-setKeyframes.tentative.html122
-rw-r--r--tests/wpt/web-platform-tests/css/css-animations/support/testcommon.js49
-rw-r--r--tests/wpt/web-platform-tests/css/css-values/round-function.html1
-rw-r--r--tests/wpt/web-platform-tests/css/support/numeric-testcommon.js12
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https.html7
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/universal-worker.js (renamed from tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/dedicated-worker.js)0
-rw-r--r--tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/service-worker-cache-storage.https.html117
-rw-r--r--tests/wpt/web-platform-tests/interfaces/construct-stylesheets.idl2
-rw-r--r--tests/wpt/web-platform-tests/native-file-system/script-tests/FileSystemBaseHandle-IndexedDB.js24
-rw-r--r--tests/wpt/web-platform-tests/resources/chromium/nfc-mock.js15
-rw-r--r--tests/wpt/web-platform-tests/tools/wpt/revlist.py3
-rw-r--r--tests/wpt/web-platform-tests/web-nfc/resources/nfc-helpers.js3
-rw-r--r--tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/suspended-context-messageport.https.html51
-rw-r--r--tests/wpt/web-platform-tests/webauthn/createcredential-badargs-authnrselection.https.html6
-rw-r--r--tests/wpt/web-platform-tests/webauthn/createcredential-badargs-rp.https.html10
-rw-r--r--tests/wpt/web-platform-tests/webauthn/createcredential-excludecredentials.https.html2
-rw-r--r--tests/wpt/web-platform-tests/webauthn/createcredential-extensions.https.html9
-rw-r--r--tests/wpt/web-platform-tests/webauthn/createcredential-pubkeycredparams.https.html4
53 files changed, 1758 insertions, 331 deletions
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index 53229d83310..c51c6d3a49f 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -237342,7 +237342,7 @@
[]
],
"support.js": [
- "d3b2bb7d1212dd6de0379bf2dce0b23e45f7c7cb",
+ "8dbfa6f1e37d7631bf5f69b9da9b906876c5d2cf",
[]
]
},
@@ -279916,7 +279916,7 @@
[]
],
"testcommon.js": [
- "b4fde4b967de2eb67cb3e0819c3a896375e861f9",
+ "7d63d2c49bce5152d765ac62728f749f622bde2a",
[]
]
}
@@ -305255,7 +305255,7 @@
[]
],
"numeric-testcommon.js": [
- "56022d06399df48b48d72ef71169578034a5f86c",
+ "996250d359dc676e001bb1aebfacae98c263e41a",
[]
],
"parsing-testcommon.js": [
@@ -315475,10 +315475,6 @@
"6604450991a122e3e241e40b1b9e0516c525389d",
[]
],
- "dedicated-worker.js": [
- "5d46edcde24c1854c19069d967038c493d7e24f0",
- []
- ],
"iframe.html": [
"a6b74ad924aa108e15603544f7b0a80a3e18940b",
[]
@@ -315538,6 +315534,10 @@
"sw.js": [
"57f0b41ba5b5ff6318e1e4913dfd13bdb1f237a4",
[]
+ ],
+ "universal-worker.js": [
+ "5d46edcde24c1854c19069d967038c493d7e24f0",
+ []
]
},
"sandbox.https.html.headers": [
@@ -324888,7 +324888,7 @@
[]
],
"construct-stylesheets.idl": [
- "fca2a3e2887a192f737b4ce05edc52810b2cd7a9",
+ "35121866f66eaa8b6663480d1a4cb72c1cf8fd1e",
[]
],
"cookie-store.idl": [
@@ -328375,7 +328375,7 @@
},
"script-tests": {
"FileSystemBaseHandle-IndexedDB.js": [
- "d7403ff5ea6d649d2b36870a5add0730f528a1ea",
+ "855e52f04ddf2f4f8641524010216c6e8c7cdda7",
[]
],
"FileSystemBaseHandle-postMessage-BroadcastChannel.js": [
@@ -337717,7 +337717,7 @@
[]
],
"nfc-mock.js": [
- "7832a8231efb01f277960afc91adf01cfe3e3ac6",
+ "14bb8fdada399999efb67576481efa8881af48f3",
[]
],
"sensor.mojom.js": [
@@ -347603,7 +347603,7 @@
[]
],
"revlist.py": [
- "c4cbc2943b7ce02ef2a58f65d34ab717bfb0c981",
+ "1893fdefa8346e8f969e41789df6e3ddd8540629",
[]
],
"run.py": [
@@ -349915,7 +349915,7 @@
],
"resources": {
"nfc-helpers.js": [
- "5bec071dfa7ad65fe4181a897ebe91912ee94476",
+ "b1753ddd1b3c5fb70b5ee4d99500623e3fdbdbfd",
[]
],
"support-iframe.html": [
@@ -365657,6 +365657,181 @@
{}
]
],
+ "transaction-scheduling-across-connections.any.js": [
+ "92d098d29c937c84b7bc9dd1219f126db0b7e585",
+ [
+ "IndexedDB/transaction-scheduling-across-connections.any.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ],
+ [
+ "IndexedDB/transaction-scheduling-across-connections.any.worker.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ]
+ ],
+ "transaction-scheduling-across-databases.any.js": [
+ "064444175867ca528d0d90ea0be40d573561ca88",
+ [
+ "IndexedDB/transaction-scheduling-across-databases.any.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ],
+ [
+ "IndexedDB/transaction-scheduling-across-databases.any.worker.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ]
+ ],
+ "transaction-scheduling-mixed-scopes.any.js": [
+ "5f04a6a288d23c29a7663ccfcdb32c932d573831",
+ [
+ "IndexedDB/transaction-scheduling-mixed-scopes.any.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ],
+ [
+ "IndexedDB/transaction-scheduling-mixed-scopes.any.worker.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ]
+ ],
+ "transaction-scheduling-ordering.any.js": [
+ "9f47e5c58ca3961d83263c7d90da597b83e06ceb",
+ [
+ "IndexedDB/transaction-scheduling-ordering.any.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ],
+ [
+ "IndexedDB/transaction-scheduling-ordering.any.worker.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ]
+ ],
+ "transaction-scheduling-ro-waits-for-rw.any.js": [
+ "dca08b820888f13c00cdb5a8a61badac884fac21",
+ [
+ "IndexedDB/transaction-scheduling-ro-waits-for-rw.any.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ],
+ [
+ "IndexedDB/transaction-scheduling-ro-waits-for-rw.any.worker.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ]
+ ],
+ "transaction-scheduling-rw-scopes.any.js": [
+ "7c6f61614b0689d3090222872379c1269559ec4c",
+ [
+ "IndexedDB/transaction-scheduling-rw-scopes.any.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ],
+ [
+ "IndexedDB/transaction-scheduling-rw-scopes.any.worker.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ]
+ ],
+ "transaction-scheduling-within-database.any.js": [
+ "10dd8b6d7ac5ed9dd4399a04dada2f5e88b827d8",
+ [
+ "IndexedDB/transaction-scheduling-within-database.any.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ],
+ [
+ "IndexedDB/transaction-scheduling-within-database.any.worker.html",
+ {
+ "script_metadata": [
+ [
+ "script",
+ "support.js"
+ ]
+ ]
+ }
+ ]
+ ],
"transaction_bubble-and-capture.htm": [
"bffa9307ccf3c7738639eb243cbf2d3ae984cb5d",
[
@@ -379148,7 +379323,7 @@
},
"nonce-hiding": {
"nonces.html": [
- "b023d060323d9d9f366ffdb53159a6f25ab24065",
+ "7ee10a7b29e5a54918a75037ded0e5bd087f601a",
[
null,
{}
@@ -383914,6 +384089,13 @@
{}
]
],
+ "AnimationEffect-updateTiming.tentative.html": [
+ "de6953c761facd400a37572419e3c97f42b4cfed",
+ [
+ null,
+ {}
+ ]
+ ],
"CSSAnimation-animationName.tentative.html": [
"370d5ef85e27c2e83deb54522a31da9deb8b556c",
[
@@ -383936,7 +384118,7 @@
]
],
"CSSAnimation-effect.tentative.html": [
- "bbf35d5113a9c3d1e4dba7318f649494c88feb4c",
+ "95a904187204286a49a17377d3201f4918128566",
[
null,
{
@@ -383966,7 +384148,7 @@
]
],
"CSSAnimation-pausing.tentative.html": [
- "2b6e6853b4178f90e820a16a74a5d63524123d32",
+ "156a1afa964de12e4a983c032f9b526b5cdf625d",
[
null,
{}
@@ -384015,7 +384197,14 @@
]
],
"KeyframeEffect-getKeyframes.tentative.html": [
- "591cc15a7eda8279ec5e9af529f8e6a06b7caa6c",
+ "f7d767dea8ca15589a53fae7952bb15e383ccd22",
+ [
+ null,
+ {}
+ ]
+ ],
+ "KeyframeEffect-setKeyframes.tentative.html": [
+ "7d8f845413a38daae9bcc9d6ce251e44cda582cb",
[
null,
{}
@@ -402871,7 +403060,7 @@
]
],
"round-function.html": [
- "236b9a9a8a32e691c5b5b0ea6df66995ec1e4a10",
+ "b1e950efe7238fcc08b9423dca88e51383f8f7d3",
[
null,
{}
@@ -431087,7 +431276,7 @@
]
],
"dedicated-worker-cache-storage.https.html": [
- "2559de839a304dce0c2700dc4f8ee0002de04332",
+ "dced705206fd02ede82ef4c3ed29bbd8f5f1ea2c",
[
null,
{}
@@ -431202,6 +431391,13 @@
{}
]
],
+ "service-worker-cache-storage.https.html": [
+ "873f06ce4ffbf83bca2ac4dbdc04e5b5bf92abb6",
+ [
+ null,
+ {}
+ ]
+ ],
"srcdoc.https.html": [
"3fbba961b2736ed8c9fb973d61dfac5e54267c40",
[
@@ -549877,6 +550073,13 @@
null,
{}
]
+ ],
+ "suspended-context-messageport.https.html": [
+ "5f5b10a251f41fd29f694564a717587f8a5a0bad",
+ [
+ null,
+ {}
+ ]
]
},
"the-biquadfilternode-interface": {
@@ -550616,7 +550819,7 @@
]
],
"createcredential-badargs-authnrselection.https.html": [
- "5da0745734ffbfbcd0d1658e4f4c1914d9940611",
+ "9497a001f0f4726ac628178983e8ce2625b25e88",
[
null,
{
@@ -550636,7 +550839,7 @@
]
],
"createcredential-badargs-rp.https.html": [
- "cbd86b8f083e3d1d3b28842b9fa5759047cfac1e",
+ "8886cc15c92e0ae98f0c65d6d1daa92cb93acfb7",
[
null,
{
@@ -550656,7 +550859,7 @@
]
],
"createcredential-excludecredentials.https.html": [
- "3a5af481fcac6cd1f9f0e1e95caab7ba7a7facb4",
+ "2b1eec19b7b3a806150d13c77d8cfd1ea01973a6",
[
null,
{
@@ -550666,7 +550869,7 @@
]
],
"createcredential-extensions.https.html": [
- "036200dbbf949e7d0b274e44cc88e7aef1366cb8",
+ "46cab3051b4924a2cb9cf1d7a2df46046b7b2f23",
[
null,
{
@@ -550686,7 +550889,7 @@
]
],
"createcredential-pubkeycredparams.https.html": [
- "c845a90687576a2d33b7f459c293aa74a15c1fb9",
+ "d1df7952d6766744280b460a18d2e561a5527e5d",
[
null,
{
diff --git a/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-002.html.ini b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-002.html.ini
new file mode 100644
index 00000000000..f64b45fea6b
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-002.html.ini
@@ -0,0 +1,4 @@
+[hit-test-floats-002.html]
+ [Hit test float]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-004.html.ini b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-004.html.ini
new file mode 100644
index 00000000000..4bfb0c2053a
--- /dev/null
+++ b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-004.html.ini
@@ -0,0 +1,4 @@
+[hit-test-floats-004.html]
+ [Miss float below something else]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-005.html.ini b/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-005.html.ini
deleted file mode 100644
index baa9f1a7541..00000000000
--- a/tests/wpt/metadata/css/CSS2/floats/hit-test-floats-005.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[hit-test-floats-005.html]
- [Miss clipped float]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/css/css-animations/AnimationEffect-updateTiming.tentative.html.ini b/tests/wpt/metadata/css/css-animations/AnimationEffect-updateTiming.tentative.html.ini
new file mode 100644
index 00000000000..963b484697e
--- /dev/null
+++ b/tests/wpt/metadata/css/css-animations/AnimationEffect-updateTiming.tentative.html.ini
@@ -0,0 +1,16 @@
+[AnimationEffect-updateTiming.tentative.html]
+ [AnimationEffect.updateTiming({ delay, fill }) causes changes to the animation-delay and animation-fill-mode to be ignored]
+ expected: FAIL
+
+ [AnimationEffect.updateTiming({ duration }) causes changes to the animation-duration to be ignored]
+ expected: FAIL
+
+ [AnimationEffect.updateTiming({ iterations, direction }) causes changes to the animation-iteration-count and animation-direction to be ignored]
+ expected: FAIL
+
+ [AnimationEffect properties that do not map to animation-* properties should not be changed when animation-* style is updated]
+ expected: FAIL
+
+ [AnimationEffect.updateTiming() does override to changes from animation-* properties if there is an error]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/css-animations/CSSAnimation-effect.tentative.html.ini b/tests/wpt/metadata/css/css-animations/CSSAnimation-effect.tentative.html.ini
index 92a8142c0e2..9b844b4399e 100644
--- a/tests/wpt/metadata/css/css-animations/CSSAnimation-effect.tentative.html.ini
+++ b/tests/wpt/metadata/css/css-animations/CSSAnimation-effect.tentative.html.ini
@@ -17,3 +17,6 @@
[Setting a null effect on a running animation fires an animationend event]
expected: FAIL
+ [Replacing the effect of a CSSAnimation causes subsequent changes to corresponding animation-* properties to be ignored]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/css-animations/CSSAnimation-pausing.tentative.html.ini b/tests/wpt/metadata/css/css-animations/CSSAnimation-pausing.tentative.html.ini
index 2682df5da60..0662ba6816b 100644
--- a/tests/wpt/metadata/css/css-animations/CSSAnimation-pausing.tentative.html.ini
+++ b/tests/wpt/metadata/css/css-animations/CSSAnimation-pausing.tentative.html.ini
@@ -17,3 +17,21 @@
[play() is overridden by later setting "animation-play-state: paused"]
expected: FAIL
+ [reverse() overrides animation-play-state when it starts playing the animation]
+ expected: FAIL
+
+ [Setting the startTime to non-null does NOT override the animation-play-state if the animation is already running]
+ expected: FAIL
+
+ [reverse() does NOT override animation-play-state if the animation is already running]
+ expected: FAIL
+
+ [Setting the startTime to null overrides animation-play-state if the animation is already running]
+ expected: FAIL
+
+ [Setting the startTime to non-null overrides animation-play-state if the animation is paused]
+ expected: FAIL
+
+ [play() does NOT override the animation-play-state if there was an error]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/css-animations/KeyframeEffect-getKeyframes.tentative.html.ini b/tests/wpt/metadata/css/css-animations/KeyframeEffect-getKeyframes.tentative.html.ini
index 52c4783152b..08053516bf1 100644
--- a/tests/wpt/metadata/css/css-animations/KeyframeEffect-getKeyframes.tentative.html.ini
+++ b/tests/wpt/metadata/css/css-animations/KeyframeEffect-getKeyframes.tentative.html.ini
@@ -71,3 +71,6 @@
[KeyframeEffect.getKeyframes() returns expected values for animations with CSS variables as keyframe values in a shorthand property]
expected: FAIL
+ [KeyframeEffect.getKeyframes() reflects changes to @keyframes rules]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/css-animations/KeyframeEffect-setKeyframes.tentative.html.ini b/tests/wpt/metadata/css/css-animations/KeyframeEffect-setKeyframes.tentative.html.ini
new file mode 100644
index 00000000000..55cfd751ecb
--- /dev/null
+++ b/tests/wpt/metadata/css/css-animations/KeyframeEffect-setKeyframes.tentative.html.ini
@@ -0,0 +1,10 @@
+[KeyframeEffect-setKeyframes.tentative.html]
+ [KeyframeEffect.setKeyframes() causes subsequent changes to animation-timing-function to be ignored]
+ expected: FAIL
+
+ [KeyframeEffect.setKeyframes() causes subsequent changes to @keyframes rules to be ignored]
+ expected: FAIL
+
+ [KeyframeEffect.setKeyframes() should NOT cause subsequent changes to @keyframes rules to be ignored if it threw]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/css-transitions/no-transition-from-ua-to-blocking-stylesheet.html.ini b/tests/wpt/metadata/css/css-transitions/no-transition-from-ua-to-blocking-stylesheet.html.ini
index 70a00a101f6..e35a452a186 100644
--- a/tests/wpt/metadata/css/css-transitions/no-transition-from-ua-to-blocking-stylesheet.html.ini
+++ b/tests/wpt/metadata/css/css-transitions/no-transition-from-ua-to-blocking-stylesheet.html.ini
@@ -1,2 +1,2 @@
[no-transition-from-ua-to-blocking-stylesheet.html]
- expected: FAIL
+ expected: TIMEOUT
diff --git a/tests/wpt/metadata/css/css-values/round-function.html.ini b/tests/wpt/metadata/css/css-values/round-function.html.ini
index b272ffc2ac6..bde64751406 100644
--- a/tests/wpt/metadata/css/css-values/round-function.html.ini
+++ b/tests/wpt/metadata/css/css-values/round-function.html.ini
@@ -335,3 +335,63 @@
[round(to-zero, -18px, 10px) should be used-value-equivalent to -10px]
expected: FAIL
+ [round(to-zero, 5, infinity) should equal 0⁺.]
+ expected: FAIL
+
+ [round(up, -1, infinity should equal 0⁻.]
+ expected: FAIL
+
+ [round(to-zero, -5, infinity) should equal 0⁻.]
+ expected: FAIL
+
+ [round(up, -1 * 0, infinity should equal 0⁻.]
+ expected: FAIL
+
+ [round(up, 0, infinity) should equal 0⁺.]
+ expected: FAIL
+
+ [round(down, -1, infinity) should equal -Infinity.]
+ expected: FAIL
+
+ [round(down, -1 * 0, infinity) should equal 0⁻.]
+ expected: FAIL
+
+ [round(infinity, 5) should equal +Infinity.]
+ expected: FAIL
+
+ [round(-infinity, 5) should equal -Infinity.]
+ expected: FAIL
+
+ [round(down, 0, infinity) should equal 0⁺.]
+ expected: FAIL
+
+ [round(-infinity, -5) should equal -Infinity.]
+ expected: FAIL
+
+ [round(down, 1, infinity) should equal 0⁺.]
+ expected: FAIL
+
+ [round(5, infinity) should equal 0⁺.]
+ expected: FAIL
+
+ [round(up, 1, infinity) should equal +Infinity.]
+ expected: FAIL
+
+ [round(infinity, -5) should equal +Infinity.]
+ expected: FAIL
+
+ [round(5, -infinity) should equal 0⁺.]
+ expected: FAIL
+
+ [round(to-zero, -5, -infinity) should equal 0⁻.]
+ expected: FAIL
+
+ [round(to-zero, 5, -infinity) should equal 0⁺.]
+ expected: FAIL
+
+ [round(-5, -infinity) should equal 0⁻.]
+ expected: FAIL
+
+ [round(-5, infinity) should equal 0⁻.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/cssom-view/CaretPosition-001.html.ini b/tests/wpt/metadata/css/cssom-view/CaretPosition-001.html.ini
new file mode 100644
index 00000000000..4c79907309b
--- /dev/null
+++ b/tests/wpt/metadata/css/cssom-view/CaretPosition-001.html.ini
@@ -0,0 +1,4 @@
+[CaretPosition-001.html]
+ [Element at (400, 100)]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini b/tests/wpt/metadata/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini
index c884dc82eab..628b1fab770 100644
--- a/tests/wpt/metadata/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini
+++ b/tests/wpt/metadata/css/cssom-view/MediaQueryList-addListener-removeListener.html.ini
@@ -2,6 +2,3 @@
[listeners are called when <iframe> is resized]
expected: FAIL
- [listeners are called correct number of times]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/fetch/content-type/response.window.js.ini b/tests/wpt/metadata/fetch/content-type/response.window.js.ini
index 597ed32e119..b01cf71e9c7 100644
--- a/tests/wpt/metadata/fetch/content-type/response.window.js.ini
+++ b/tests/wpt/metadata/fetch/content-type/response.window.js.ini
@@ -312,18 +312,24 @@
[fetch(): separate response Content-Type: text/plain ]
expected: NOTRUN
- [<iframe>: combined response Content-Type: text/html;" text/plain]
+ [<iframe>: separate response Content-Type: text/plain */*;charset=gbk]
expected: FAIL
- [<iframe>: separate response Content-Type: text/plain */*;charset=gbk]
+ [<iframe>: combined response Content-Type: text/html;x=" text/plain]
expected: FAIL
- [<iframe>: combined response Content-Type: text/html */*]
+ [<iframe>: combined response Content-Type: */* text/html]
expected: FAIL
- [<iframe>: separate response Content-Type: text/html */*;charset=gbk]
+ [<iframe>: combined response Content-Type: text/html;charset=gbk text/plain text/html]
expected: FAIL
- [<iframe>: combined response Content-Type: text/html;x=" text/plain]
+ [<iframe>: separate response Content-Type: text/html;" text/plain]
+ expected: FAIL
+
+ [<iframe>: separate response Content-Type: text/plain */*]
+ expected: FAIL
+
+ [<iframe>: separate response Content-Type: text/html;x=" text/plain]
expected: FAIL
diff --git a/tests/wpt/metadata/fetch/content-type/script.window.js.ini b/tests/wpt/metadata/fetch/content-type/script.window.js.ini
index 279734168dc..d2df9b78483 100644
--- a/tests/wpt/metadata/fetch/content-type/script.window.js.ini
+++ b/tests/wpt/metadata/fetch/content-type/script.window.js.ini
@@ -56,6 +56,3 @@
[separate text/javascript x/x]
expected: FAIL
- [separate text/javascript;charset=windows-1252 text/javascript]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/fetch/nosniff/parsing-nosniff.window.js.ini b/tests/wpt/metadata/fetch/nosniff/parsing-nosniff.window.js.ini
index cc50d2d2e03..30e1b851fd4 100644
--- a/tests/wpt/metadata/fetch/nosniff/parsing-nosniff.window.js.ini
+++ b/tests/wpt/metadata/fetch/nosniff/parsing-nosniff.window.js.ini
@@ -11,9 +11,3 @@
[X-Content-Type-Options%3A%20nosniff%2C%2C%40%23%24%23%25%25%26%5E%26%5E*()()11!]
expected: FAIL
- [X-Content-Type-Options%3A%20%40%23%24%23%25%25%26%5E%26%5E*()()11!%2Cnosniff]
- expected: FAIL
-
- [Content-Type-Options%3A%20nosniff]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_1.html.ini b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_1.html.ini
new file mode 100644
index 00000000000..87b07c3e670
--- /dev/null
+++ b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_1.html.ini
@@ -0,0 +1,4 @@
+[traverse_the_history_1.html]
+ [Multiple history traversals from the same task]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_3.html.ini b/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_3.html.ini
deleted file mode 100644
index 51f8272a6de..00000000000
--- a/tests/wpt/metadata/html/browsers/history/the-history-interface/traverse_the_history_3.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[traverse_the_history_3.html]
- [Multiple history traversals, last would be aborted]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/interaction/focus/the-autofocus-attribute/skip-document-with-fragment.html.ini b/tests/wpt/metadata/html/interaction/focus/the-autofocus-attribute/skip-document-with-fragment.html.ini
index 6852d7663de..c12c0f8ae48 100644
--- a/tests/wpt/metadata/html/interaction/focus/the-autofocus-attribute/skip-document-with-fragment.html.ini
+++ b/tests/wpt/metadata/html/interaction/focus/the-autofocus-attribute/skip-document-with-fragment.html.ini
@@ -1,8 +1,4 @@
[skip-document-with-fragment.html]
- expected: TIMEOUT
[Autofocus elements in iframed documents with URL fragments should be skipped.]
expected: FAIL
- [Autofocus elements in top-level browsing context's documents with URI fragments should be skipped.]
- expected: TIMEOUT
-
diff --git a/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-multi-channels.html.ini b/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-multi-channels.html.ini
index ca40f8b0d74..f606d929563 100644
--- a/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-multi-channels.html.ini
+++ b/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-multi-channels.html.ini
@@ -32,3 +32,6 @@
[X Rendered audio for channel 5 does not equal [0,0.0626220703125,0.125030517578125,0.18695068359375,0.24810791015625,0.308319091796875,0.3673095703125,0.42486572265625,0.480743408203125,0.53472900390625,0.58660888671875,0.636199951171875,0.68328857421875,0.727691650390625,0.76922607421875,0.8077392578125...\] with an element-wise tolerance of {"absoluteThreshold":0.000030517578125,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[1\]\t3.6732959747314453e-1\t6.2622070312500000e-2\t3.0470752716064453e-1\t4.8658168859649127e+0\t3.0517578125000000e-5\n\t[2\]\t6.8329977989196777e-1\t1.2503051757812500e-1\t5.5826926231384277e-1\t4.4650639949963384e+0\t3.0517578125000000e-5\n\t[3\]\t9.0373212099075317e-1\t1.8695068359375000e-1\t7.1678143739700317e-1\t3.8340669508039502e+0\t3.0517578125000000e-5\n\t[4\]\t9.9780619144439697e-1\t2.4810791015625000e-1\t7.4969828128814697e-1\t3.0216621502152523e+0\t3.0517578125000000e-5\n\t[5\]\t9.5236867666244507e-1\t3.0831909179687500e-1\t6.4404958486557007e-1\t2.0889059484187866e+0\t3.0517578125000000e-5\n\t...and 42281 more errors.\n\tMax AbsError of 1.9986916780471802e+0 at index of 17995.\n\t[17995\]\t9.9994289875030518e-1\t-9.9874877929687500e-1\t1.9986916780471802e+0\t2.0011956154322119e+0\t3.0517578125000000e-5\n\tMax RelError of Infinity at index of 12348.\n\t[12348\]\t9.5105654001235962e-1\t0.0000000000000000e+0\t9.5105654001235962e-1\tInfinity\t3.0517578125000000e-5\n]
expected: FAIL
+ [X Rendered audio for channel 5 does not equal [0,0.0626220703125,0.125030517578125,0.18695068359375,0.24810791015625,0.308319091796875,0.3673095703125,0.42486572265625,0.480743408203125,0.53472900390625,0.58660888671875,0.636199951171875,0.68328857421875,0.727691650390625,0.76922607421875,0.8077392578125...\] with an element-wise tolerance of {"absoluteThreshold":0.000030517578125,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[1\]\t3.6732959747314453e-1\t6.2622070312500000e-2\t3.0470752716064453e-1\t4.8658168859649127e+0\t3.0517578125000000e-5\n\t[2\]\t6.8329977989196777e-1\t1.2503051757812500e-1\t5.5826926231384277e-1\t4.4650639949963384e+0\t3.0517578125000000e-5\n\t[3\]\t9.0373212099075317e-1\t1.8695068359375000e-1\t7.1678143739700317e-1\t3.8340669508039502e+0\t3.0517578125000000e-5\n\t[4\]\t9.9780619144439697e-1\t2.4810791015625000e-1\t7.4969828128814697e-1\t3.0216621502152523e+0\t3.0517578125000000e-5\n\t[5\]\t9.5236867666244507e-1\t3.0831909179687500e-1\t6.4404958486557007e-1\t2.0889059484187866e+0\t3.0517578125000000e-5\n\t...and 44043 more errors.\n\tMax AbsError of 1.9962286949157715e+0 at index of 32177.\n\t[32177\]\t9.9879217147827148e-1\t-9.9743652343750000e-1\t1.9962286949157715e+0\t2.0013591321441684e+0\t3.0517578125000000e-5\n\tMax RelError of Infinity at index of 14112.\n\t[14112\]\t-9.5105654001235962e-1\t0.0000000000000000e+0\t9.5105654001235962e-1\tInfinity\t3.0517578125000000e-5\n]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html.ini b/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html.ini
index 9513f7b9674..6537c0f6d97 100644
--- a/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html.ini
+++ b/tests/wpt/metadata/webaudio/the-audio-api/the-audiobuffersourcenode-interface/sub-sample-buffer-stitching.html.ini
@@ -170,3 +170,9 @@
[X SNR (-254.56109005477157 dB) is not greater than or equal to 65.737. Got -254.56109005477157.]
expected: FAIL
+ [X Stitched sine-wave buffers at sample rate 43800 does not equal [0,0.06264832615852356,0.12505052983760834,0.18696144223213196,0.24813786149024963,0.308339387178421,0.36732959747314453,0.4248766601085663,0.480754554271698,0.5347436666488647,0.5866320133209229,0.6362156271934509,0.6832997798919678,0.7276994585990906,0.7692402601242065,0.8077589869499207...\] with an element-wise tolerance of {"absoluteThreshold":0.0038986,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[19030\]\t-1.5346258564356873e+24\t-7.3546999692916870e-1\t1.5346258564356873e+24\t2.0865920606459265e+24\t3.8985999999999999e-3\n\t[19031\]\t-3.6017334461212158e-1\t-6.9157749414443970e-1\t3.3140414953231812e-1\t4.7920030992665957e-1\t3.8985999999999999e-3\n\t[38059\]\t-3.0465973817666023e+24\t-9.8956179618835449e-1\t3.0465973817666023e+24\t3.0787338329972360e+24\t3.8985999999999999e-3\n\t[38060\]\t-8.8409073650836945e-2\t-9.9664616584777832e-1\t9.0823709219694138e-1\t9.1129341918891205e-1\t3.8985999999999999e-3\n\tMax AbsError of 3.0465973817666023e+24 at index of 38059.\n\tMax RelError of 3.0787338329972360e+24 at index of 38059.\n]
+ expected: FAIL
+
+ [X SNR (-447.224261749694 dB) is not greater than or equal to 65.737. Got -447.224261749694.]
+ expected: FAIL
+
diff --git a/tests/wpt/metadata/webaudio/the-audio-api/the-audioworklet-interface/suspended-context-messageport.https.html.ini b/tests/wpt/metadata/webaudio/the-audio-api/the-audioworklet-interface/suspended-context-messageport.https.html.ini
new file mode 100644
index 00000000000..e6fc13c33df
--- /dev/null
+++ b/tests/wpt/metadata/webaudio/the-audio-api/the-audioworklet-interface/suspended-context-messageport.https.html.ini
@@ -0,0 +1,10 @@
+[suspended-context-messageport.https.html]
+ [offline before start]
+ expected: FAIL
+
+ [offline on complete]
+ expected: FAIL
+
+ [realtime suspended]
+ expected: FAIL
+
diff --git a/tests/wpt/web-platform-tests/IndexedDB/support.js b/tests/wpt/web-platform-tests/IndexedDB/support.js
index d3b2bb7d121..8dbfa6f1e37 100644
--- a/tests/wpt/web-platform-tests/IndexedDB/support.js
+++ b/tests/wpt/web-platform-tests/IndexedDB/support.js
@@ -101,6 +101,16 @@ function assert_key_equals(actual, expected, description) {
assert_equals(indexedDB.cmp(actual, expected), 0, description);
}
+// Usage:
+// indexeddb_test(
+// (test_object, db_connection, upgrade_tx, open_request) => {
+// // Database creation logic.
+// },
+// (test_object, db_connection, open_request) => {
+// // Test logic.
+// test_object.done();
+// },
+// 'Test case description');
function indexeddb_test(upgrade_func, open_func, description, options) {
async_test(function(t) {
options = Object.assign({upgrade_will_abort: false}, options);
@@ -189,3 +199,13 @@ function keep_alive(tx, store_name) {
keepSpinning = false;
};
}
+
+// Returns a new function. After it is called |count| times, |func|
+// will be called.
+function barrier_func(count, func) {
+ let n = 0;
+ return () => {
+ if (++n === count)
+ func();
+ };
+}
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-across-connections.any.js b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-across-connections.any.js
new file mode 100644
index 00000000000..92d098d29c9
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-across-connections.any.js
@@ -0,0 +1,72 @@
+// META: script=support.js
+
+indexeddb_test(
+ (t, db) => {
+ const store = db.createObjectStore('store');
+ },
+
+ (t, db1) => {
+ // Open a second connection to the same database.
+ const open_request = indexedDB.open(db1.name);
+ open_request.onerror = t.unreached_func('open() should succeed');
+ open_request.onupgradeneeded =
+ t.unreached_func('second connection should not upgrade');
+ open_request.onsuccess = t.step_func(() => {
+ const db2 = open_request.result;
+ t.add_cleanup(() => { db2.close(); });
+
+ const transaction1 = db1.transaction('store', 'readwrite');
+ transaction1.onabort = t.unreached_func('transaction1 should complete');
+
+ const transaction2 = db2.transaction('store', 'readwrite');
+ transaction2.onabort = t.unreached_func('transaction2 should complete');
+
+ let transaction1PutSuccess = false;
+ let transaction1Complete = false;
+ let transaction2PutSuccess = false;
+
+ // Keep transaction1 alive for a while and ensure transaction2
+ // doesn't start.
+
+ let count = 0;
+ (function doTransaction1Put() {
+ const request = transaction1.objectStore('store').put(1, count++);
+ request.onerror = t.unreached_func('request should succeed');
+ request.onsuccess = t.step_func(evt => {
+ transaction1PutSuccess = true;
+ if (count < 5) {
+ doTransaction1Put();
+ }
+ });
+ }());
+
+ transaction1.oncomplete = t.step_func(evt => {
+ transaction1Complete = true;
+ assert_false(
+ transaction2PutSuccess,
+ 'transaction1 should complete before transaction2 put succeeds');
+ });
+
+ const request = transaction2.objectStore('store').put(2, 0);
+ request.onerror = t.unreached_func('request should succeed');
+ request.onsuccess = t.step_func(evt => {
+ transaction2PutSuccess = true;
+ assert_true(
+ transaction1Complete,
+ 'transaction2 put should not succeed before transaction1 completes');
+ });
+
+ transaction2.oncomplete = t.step_func_done(evt => {
+ assert_true(
+ transaction1PutSuccess,
+ 'transaction1 put should succeed before transaction2 runs');
+ assert_true(
+ transaction1Complete,
+ 'transaction1 should complete before transaction2 runs');
+ assert_true(
+ transaction2PutSuccess,
+ 'transaction2 put should succeed before transaction2 completes');
+ });
+ });
+ },
+ "Check that readwrite transactions with overlapping scopes do not run in parallel.");
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-across-databases.any.js b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-across-databases.any.js
new file mode 100644
index 00000000000..06444417586
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-across-databases.any.js
@@ -0,0 +1,72 @@
+// META: script=support.js
+
+indexeddb_test(
+ (t, db) => {
+ const store = db.createObjectStore('store');
+ },
+
+ (t, db1) => {
+ // Open a second database.
+ const db2name = db1.name + '-2';
+ const delete_request = indexedDB.deleteDatabase(db2name);
+ delete_request.onerror = t.unreached_func('deleteDatabase() should succeed');
+ const open_request = indexedDB.open(db2name, 1);
+ open_request.onerror = t.unreached_func('open() should succeed');
+ open_request.onupgradeneeded = t.step_func(() => {
+ const db2 = open_request.result;
+ const store = db2.createObjectStore('store');
+ });
+ open_request.onsuccess = t.step_func(() => {
+ const db2 = open_request.result;
+ t.add_cleanup(() => {
+ db2.close();
+ indexedDB.deleteDatabase(db2.name);
+ });
+
+ let transaction1PutSuccess = false;
+ let transaction2PutSuccess = false;
+
+ const onTransactionComplete = barrier_func(2, t.step_func_done(() => {
+ assert_true(transaction1PutSuccess,
+ 'transaction1 should have executed at least one request');
+ assert_true(transaction2PutSuccess,
+ 'transaction1 should have executed at least one request');
+ }));
+
+
+ const transaction1 = db1.transaction('store', 'readwrite');
+ transaction1.onabort = t.unreached_func('transaction1 should complete');
+ transaction1.oncomplete = t.step_func(onTransactionComplete);
+
+ const transaction2 = db2.transaction('store', 'readwrite');
+ transaction2.onabort = t.unreached_func('transaction2 should complete');
+ transaction2.oncomplete = t.step_func(onTransactionComplete);
+
+ // Keep both transactions alive until each has reported at least one
+ // successful operation.
+
+ function doTransaction1Put() {
+ const request = transaction1.objectStore('store').put(0, 0);
+ request.onerror = t.unreached_func('put request should succeed');
+ request.onsuccess = t.step_func(() => {
+ transaction1PutSuccess = true;
+ if (!transaction2PutSuccess)
+ doTransaction1Put();
+ });
+ }
+
+ function doTransaction2Put() {
+ const request = transaction2.objectStore('store').put(0, 0);
+ request.onerror = t.unreached_func('put request should succeed');
+ request.onsuccess = t.step_func(() => {
+ transaction2PutSuccess = true;
+ if (!transaction1PutSuccess)
+ doTransaction2Put();
+ });
+ }
+
+ doTransaction1Put();
+ doTransaction2Put();
+ });
+ },
+ "Check that transactions in different databases can run in parallel.");
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-mixed-scopes.any.js b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-mixed-scopes.any.js
new file mode 100644
index 00000000000..5f04a6a288d
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-mixed-scopes.any.js
@@ -0,0 +1,63 @@
+// META: script=support.js
+
+indexeddb_test(
+ (t, db) => {
+ const store = db.createObjectStore('store');
+ db.createObjectStore('a');
+ db.createObjectStore('b');
+ db.createObjectStore('c');
+ },
+
+ (t, db) => {
+ let transaction1Started = false;
+ let transaction1Complete = false;
+ let transaction2Started = false;
+ let transaction2Complete = false;
+ let transaction3Started = false;
+ let transaction3Complete = false;
+
+ const transaction1 = db.transaction(['a'], 'readonly');
+ let request = transaction1.objectStore('a').get(0);
+ request.onerror = t.unreached_func('request should succeed');
+ request.onsuccess = t.step_func(() => {
+ transaction1Started = true;
+ });
+ transaction1.onabort = t.unreached_func('transaction1 should complete');
+ transaction1.oncomplete = t.step_func(() => {
+ transaction1Complete = true;
+ assert_false(transaction2Started);
+ assert_false(transaction3Started);
+ });
+
+
+ // transaction2 overlaps with transaction1, so must wait until transaction1
+ // completes.
+ const transaction2 = db.transaction(['a', 'b'], 'readwrite');
+ request = transaction2.objectStore('a').get(0);
+ request.onerror = t.unreached_func('request should succeed');
+ request.onsuccess = t.step_func(() => {
+ assert_true(transaction1Complete);
+ transaction2Started = true;
+ });
+ transaction2.onabort = t.unreached_func('transaction2 should complete');
+ transaction2.oncomplete = t.step_func(() => {
+ transaction2Complete = true;
+ assert_false(transaction3Started);
+ });
+
+ // transaction3 overlaps with transaction2, so must wait until transaction2
+ // completes even though it does not overlap with transaction1.
+ const transaction3 = db.transaction(['b', 'c'], 'readonly');
+ request = transaction3.objectStore('b').get(0);
+ request.onerror = t.unreached_func('request should succeed');
+ request.onsuccess = t.step_func(() => {
+ assert_true(transaction1Complete);
+ assert_true(transaction2Complete);
+ transaction3Started = true;
+ });
+ transaction3.onabort = t.unreached_func('transaction3 should complete');
+ transaction3.oncomplete = t.step_func_done(() => {
+ transaction3Complete = true;
+ });
+ },
+ "Check that scope restrictions on mixed transactions are enforced.");
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-ordering.any.js b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-ordering.any.js
new file mode 100644
index 00000000000..9f47e5c58ca
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-ordering.any.js
@@ -0,0 +1,40 @@
+// META: script=support.js
+
+indexeddb_test(
+ (t, db) => {
+ const store = db.createObjectStore('store');
+ },
+
+ (t, db) => {
+ // Create in order tx1, tx2.
+ const tx1 = db.transaction('store', 'readwrite');
+ const tx2 = db.transaction('store', 'readwrite');
+
+ // Use in order tx2, tx1.
+ tx2.objectStore('store').get(0);
+ tx1.objectStore('store').get(0);
+
+ const order = [];
+ const done = barrier_func(2, t.step_func_done(() => {
+ // IndexedDB Spec:
+ // https://w3c.github.io/IndexedDB/#transaction-scheduling
+ //
+ // If multiple "readwrite" transactions are attempting to
+ // access the same object store (i.e. if they have overlapping
+ // scope), the transaction that was created first must be the
+ // transaction which gets access to the object store first.
+ //
+ assert_array_equals(order, [1, 2]);
+ }));
+
+ tx1.oncomplete = t.step_func(e => {
+ order.push(1);
+ done();
+ });
+
+ tx2.oncomplete = t.step_func(e => {
+ order.push(2);
+ done();
+ });
+ },
+ "Verify Indexed DB transactions are ordered per spec");
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-ro-waits-for-rw.any.js b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-ro-waits-for-rw.any.js
new file mode 100644
index 00000000000..dca08b82088
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-ro-waits-for-rw.any.js
@@ -0,0 +1,26 @@
+// META: script=support.js
+
+indexeddb_test(
+ (t, db) => {
+ const store = db.createObjectStore('store');
+ store.put('value', 'key');
+ },
+
+ (t, db) => {
+ const transaction1 = db.transaction('store', 'readwrite');
+ transaction1.onabort = t.unreached_func('transaction1 should not abort');
+
+ const transaction2 = db.transaction('store', 'readonly');
+ transaction2.onabort = t.unreached_func('transaction2 should not abort');
+
+ const request = transaction1.objectStore('store').put('new value', 'key');
+ request.onerror = t.unreached_func('request should not fail');
+
+ const request2 = transaction2.objectStore('store').get('key');
+ request2.onerror = t.unreached_func('request2 should not fail');
+ request2.onsuccess = t.step_func_done(evt => {
+ assert_equals(request2.result, 'new value',
+ 'Request should see new value.');
+ });
+ },
+ "readonly transaction should see the result of a previous readwrite transaction");
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-rw-scopes.any.js b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-rw-scopes.any.js
new file mode 100644
index 00000000000..7c6f61614b0
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-rw-scopes.any.js
@@ -0,0 +1,63 @@
+// META: script=support.js
+
+indexeddb_test(
+ (t, db) => {
+ const store = db.createObjectStore('store');
+ db.createObjectStore('a');
+ db.createObjectStore('b');
+ db.createObjectStore('c');
+ },
+
+ (t, db) => {
+ let transaction1Started = false;
+ let transaction1Complete = false;
+ let transaction2Started = false;
+ let transaction2Complete = false;
+ let transaction3Started = false;
+ let transaction3Complete = false;
+
+ const transaction1 = db.transaction(['a'], 'readwrite');
+ let request = transaction1.objectStore('a').get(0);
+ request.onerror = t.unreached_func('request should succeed');
+ request.onsuccess = t.step_func(() => {
+ transaction1Started = true;
+ });
+ transaction1.onabort = t.unreached_func('transaction1 should complete');
+ transaction1.oncomplete = t.step_func(() => {
+ transaction1Complete = true;
+ assert_false(transaction2Started);
+ assert_false(transaction3Started);
+ });
+
+
+ // transaction2 overlaps with transaction1, so must wait until transaction1
+ // completes.
+ const transaction2 = db.transaction(['a', 'b'], 'readwrite');
+ request = transaction2.objectStore('a').get(0);
+ request.onerror = t.unreached_func('request should succeed');
+ request.onsuccess = t.step_func(() => {
+ assert_true(transaction1Complete);
+ transaction2Started = true;
+ });
+ transaction2.onabort = t.unreached_func('transaction2 should complete');
+ transaction2.oncomplete = t.step_func(() => {
+ transaction2Complete = true;
+ assert_false(transaction3Started);
+ });
+
+ // transaction3 overlaps with transaction2, so must wait until transaction2
+ // completes even though it does not overlap with transaction1.
+ const transaction3 = db.transaction(['b', 'c'], 'readwrite');
+ request = transaction3.objectStore('b').get(0);
+ request.onerror = t.unreached_func('request should succeed');
+ request.onsuccess = t.step_func(() => {
+ assert_true(transaction1Complete);
+ assert_true(transaction2Complete);
+ transaction3Started = true;
+ });
+ transaction3.onabort = t.unreached_func('transaction3 should complete');
+ transaction3.oncomplete = t.step_func_done(() => {
+ transaction3Complete = true;
+ });
+ },
+ "Check that scope restrictions on read-write transactions are enforced.");
diff --git a/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-within-database.any.js b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-within-database.any.js
new file mode 100644
index 00000000000..10dd8b6d7ac
--- /dev/null
+++ b/tests/wpt/web-platform-tests/IndexedDB/transaction-scheduling-within-database.any.js
@@ -0,0 +1,55 @@
+// META: script=support.js
+
+indexeddb_test(
+ (t, db) => {
+ const store = db.createObjectStore('store');
+ store.put('value', 'key');
+ },
+
+ (t, db) => {
+ let transaction1GetSuccess = false;
+ let transaction2GetSuccess = false;
+
+ const onTransactionComplete = barrier_func(2, t.step_func_done(() => {
+ assert_true(transaction1GetSuccess,
+ 'transaction1 should have executed at least one request');
+ assert_true(transaction2GetSuccess,
+ 'transaction1 should have executed at least one request');
+ }));
+
+ const transaction1 = db.transaction('store', 'readonly');
+ transaction1.onabort = t.unreached_func('transaction1 should not abort');
+ transaction1.oncomplete = t.step_func(onTransactionComplete);
+
+ const transaction2 = db.transaction('store', 'readonly');
+ transaction2.onabort = t.unreached_func('transaction2 should not abort');
+ transaction2.oncomplete = t.step_func(onTransactionComplete);
+
+ // Keep both transactions alive until each has reported at least one
+ // successful operation
+
+ function doTransaction1Get() {
+ const request = transaction1.objectStore('store').get('key');
+ request.onerror = t.unreached_func('request should not fail');
+ request.onsuccess = t.step_func(() => {
+ transaction1GetSuccess = true;
+ if (!transaction2GetSuccess)
+ doTransaction1Get();
+ });
+ }
+
+ function doTransaction2Get() {
+ // NOTE: No logging since execution order is not deterministic.
+ const request = transaction2.objectStore('store').get('key');
+ request.onerror = t.unreached_func('request should not fail');
+ request.onsuccess = t.step_func(() => {
+ transaction2GetSuccess = true;
+ if (!transaction1GetSuccess)
+ doTransaction2Get();
+ });
+ }
+
+ doTransaction1Get();
+ doTransaction2Get();
+ },
+ 'Check that read-only transactions within a database can run in parallel.');
diff --git a/tests/wpt/web-platform-tests/content-security-policy/nonce-hiding/nonces.html b/tests/wpt/web-platform-tests/content-security-policy/nonce-hiding/nonces.html
index b023d060323..7ee10a7b29e 100644
--- a/tests/wpt/web-platform-tests/content-security-policy/nonce-hiding/nonces.html
+++ b/tests/wpt/web-platform-tests/content-security-policy/nonce-hiding/nonces.html
@@ -3,30 +3,62 @@
<script src="/resources/testharnessreport.js"></script>
<div id=log></div>
<script>
-[["meh", ""],
- ["div", ""],
- ["script", ""],
- ["meh", "http://www.w3.org/2000/svg"],
- ["svg", "http://www.w3.org/2000/svg"],
- ["script", "http://www.w3.org/2000/svg"]].forEach(([localName, namespace]) => {
- test(t => {
- const element = namespace === "" ? document.createElement(localName) : document.createElementNS(namespace, localName);
- t.add_cleanup(() => element.remove());
- assert_equals(element.nonce, "", "Initial IDL attribute value");
- element.setAttribute("nonce", "x");
- assert_equals(element.nonce, "x", "IDL attribute is modified after content attribute set");
- assert_equals(element.getAttribute("nonce"), "x", "Content attribute is modified after content attribute set");
- document.body.appendChild(element);
- assert_equals(element.nonce, "x", "IDL attribute is unchanged after element insertion");
- assert_equals(element.getAttribute("nonce"), "", "Content attribute is changed after element insertion");
- }, `Basic nonce tests for ${localName} in ${namespace === "" ? "HTML" : "SVG"} namespace`);
-
- test(t => {
- const element = namespace === "" ? document.createElement(localName) : document.createElementNS(namespace, localName);
- element.setAttribute("nonce", "x");
- assert_equals(element.nonce, "x", "IDL attribute is modified after content attribute set");
- element.removeAttribute("nonce");
- assert_equals(element.nonce, "", "IDL attribute is empty after content attribute removal");
- }, `Ensure that removal of content attribute does not affect IDL attribute for ${localName} in ${namespace === "" ? "HTML" : "SVG"} namespace`);
-});
+ const namespace_url= {
+ "HTML": "http://www.w3.org/1999/xhtml",
+ "SVG": "http://www.w3.org/2000/svg",
+ }
+ const test_cases = [
+ ["meh" , "HTML"],
+ ["div" , "HTML"],
+ ["script" , "HTML"],
+ ["meh" , "SVG"],
+ ["svg" , "SVG"],
+ ["script" , "SVG"],
+ ];
+
+ test_cases.forEach(([localName, namespace]) => {
+ test(t => {
+ const element = document.createElementNS(namespace_url[namespace], localName);
+ t.add_cleanup(() => element.remove());
+ assert_equals(element.nonce, "", "Initial IDL attribute value");
+ assert_equals(element.getAttribute("nonce"), null, "Initial content attribute");
+
+ element.setAttribute("nonce", "x");
+ assert_equals(element.nonce, "x", "IDL attribute is modified after content attribute set");
+ assert_equals(element.getAttribute("nonce"), "x", "Content attribute is modified after content attribute set");
+
+ document.body.appendChild(element);
+ assert_equals(element.nonce, "x", "IDL attribute is unchanged after element insertion");
+ assert_equals(element.getAttribute("nonce"), "", "Content attribute is changed after element insertion");
+ }, `Basic nonce tests for ${localName} in ${namespace} namespace`);
+
+ test(t => {
+ const element = document.createElementNS(namespace_url[namespace], localName);
+ t.add_cleanup(() => element.remove());
+ element.setAttribute("nonce", "x");
+ assert_equals(element.nonce, "x", "IDL attribute is modified after content attribute set");
+
+ element.removeAttribute("nonce");
+ assert_equals(element.nonce, "", "IDL attribute is empty after content attribute removal");
+ }, `Ensure that removal of content attribute does not affect IDL attribute for ${localName} in ${namespace} namespace`);
+
+ test(t => {
+ const element = document.createElementNS(namespace_url[namespace], localName);
+ t.add_cleanup(() => element.remove());
+ assert_equals(element.nonce, "");
+ assert_equals(element.getAttribute("nonce"), null);
+
+ element.setAttribute("nonce", "");
+ assert_equals(element.nonce, "");
+ assert_equals(element.getAttribute("nonce"), "");
+
+ document.body.appendChild(element);
+ assert_equals(element.nonce, "");
+ assert_equals(element.getAttribute("nonce"), "");
+
+ element.removeAttribute("nonce");
+ assert_equals(element.nonce, "");
+ assert_equals(element.getAttribute("nonce"), null);
+ }, `Test empty nonces for ${localName} in ${namespace} namespace`);
+ });
</script>
diff --git a/tests/wpt/web-platform-tests/css/css-animations/AnimationEffect-updateTiming.tentative.html b/tests/wpt/web-platform-tests/css/css-animations/AnimationEffect-updateTiming.tentative.html
new file mode 100644
index 00000000000..de6953c761f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-animations/AnimationEffect-updateTiming.tentative.html
@@ -0,0 +1,179 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>AnimationEffect.updateTiming() for CSS animations</title>
+<!-- TODO: Add a more specific link for this once it is specified. -->
+<link rel="help" href="https://drafts.csswg.org/css-animations-2/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/testcommon.js"></script>
+<style>
+@keyframes anim-empty { }
+</style>
+<body>
+<div id="log"></div>
+<script>
+"use strict";
+
+test(t => {
+ const div = addDiv(t);
+ div.style.animation = 'anim-empty 100s';
+
+ const animation = div.getAnimations()[0];
+ animation.effect.updateTiming({ duration: 2 * MS_PER_SEC });
+
+ div.style.animationDuration = '4s';
+ div.style.animationDelay = '6s';
+ getComputedStyle(div).animationDuration;
+
+ assert_equals(
+ animation.effect.getTiming().duration,
+ 2 * MS_PER_SEC,
+ 'Duration should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getTiming().delay,
+ 6 * MS_PER_SEC,
+ 'Delay should be the value set by style'
+ );
+}, 'AnimationEffect.updateTiming({ duration }) causes changes to the'
+ + ' animation-duration to be ignored');
+
+// The above test covers duration (with delay as a control). The remaining
+// properties are:
+//
+// iterations - animation-iteration-count
+// direction - animation-direction
+// delay - animation-delay
+// fill - animation-fill-mode
+//
+// Which we test in two batches, overriding two properties each time and using
+// the remaining two properties as control values to check they are NOT
+// overridden.
+
+test(t => {
+ const div = addDiv(t);
+ div.style.animation = 'anim-empty 100s';
+
+ const animation = div.getAnimations()[0];
+ animation.effect.updateTiming({ iterations: 2, direction: 'reverse' });
+
+ div.style.animationIterationCount = '4';
+ div.style.animationDirection = 'alternate';
+ div.style.animationDelay = '6s';
+ div.style.animationFillMode = 'both';
+ getComputedStyle(div).animationIterationCount;
+
+ assert_equals(
+ animation.effect.getTiming().iterations,
+ 2,
+ 'Iterations should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getTiming().direction,
+ 'reverse',
+ 'Direction should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getTiming().delay,
+ 6 * MS_PER_SEC,
+ 'Delay should be the value set by style'
+ );
+ assert_equals(
+ animation.effect.getTiming().fill,
+ 'both',
+ 'Fill should be the value set by style'
+ );
+}, 'AnimationEffect.updateTiming({ iterations, direction }) causes changes to'
+ + ' the animation-iteration-count and animation-direction to be ignored');
+
+test(t => {
+ const div = addDiv(t);
+ div.style.animation = 'anim-empty 100s';
+
+ const animation = div.getAnimations()[0];
+ animation.effect.updateTiming({ delay: 2 * MS_PER_SEC, fill: 'both' });
+
+ div.style.animationDelay = '4s';
+ div.style.animationFillMode = 'forwards';
+ div.style.animationIterationCount = '6';
+ div.style.animationDirection = 'reverse';
+ getComputedStyle(div).animationDelay;
+
+ assert_equals(
+ animation.effect.getTiming().delay,
+ 2 * MS_PER_SEC,
+ 'Delay should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getTiming().fill,
+ 'both',
+ 'Fill should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getTiming().iterations,
+ 6,
+ 'Iterations should be the value set by style'
+ );
+ assert_equals(
+ animation.effect.getTiming().direction,
+ 'reverse',
+ 'Direction should be the value set by style'
+ );
+}, 'AnimationEffect.updateTiming({ delay, fill }) causes changes to'
+ + ' the animation-delay and animation-fill-mode to be ignored');
+
+test(t => {
+ const div = addDiv(t);
+ div.style.animation = 'anim-empty 100s';
+
+ const animation = div.getAnimations()[0];
+ assert_throws_js(TypeError, () => {
+ animation.effect.updateTiming({ duration: 2 * MS_PER_SEC, iterations: -1 });
+ }, 'Negative iteration count should cause an error to be thrown');
+
+ div.style.animationDuration = '4s';
+ getComputedStyle(div).animationDuration;
+
+ assert_equals(
+ animation.effect.getTiming().duration,
+ 4 * MS_PER_SEC,
+ 'Duration should be the value set by style'
+ );
+}, 'AnimationEffect.updateTiming() does override to changes from animation-*'
+ + ' properties if there is an error');
+
+test(t => {
+ const div = addDiv(t);
+ div.style.animation = 'anim-empty 100s';
+
+ const animation = div.getAnimations()[0];
+ animation.effect.updateTiming({
+ easing: 'steps(4)',
+ endDelay: 2 * MS_PER_SEC,
+ iterationStart: 4,
+ });
+
+ div.style.animationDuration = '6s';
+ div.style.animationTimingFunction = 'ease-in';
+ getComputedStyle(div).animationDuration;
+
+ assert_equals(
+ animation.effect.getTiming().easing,
+ 'steps(4)',
+ 'endDelay should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getTiming().endDelay,
+ 2 * MS_PER_SEC,
+ 'endDelay should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getTiming().iterationStart,
+ 4,
+ 'iterationStart should be the value set by style'
+ );
+}, 'AnimationEffect properties that do not map to animation-* properties'
+ + ' should not be changed when animation-* style is updated');
+
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-animations/CSSAnimation-effect.tentative.html b/tests/wpt/web-platform-tests/css/css-animations/CSSAnimation-effect.tentative.html
index bbf35d5113a..95a90418720 100644
--- a/tests/wpt/web-platform-tests/css/css-animations/CSSAnimation-effect.tentative.html
+++ b/tests/wpt/web-platform-tests/css/css-animations/CSSAnimation-effect.tentative.html
@@ -128,4 +128,82 @@ promise_test(async t => {
}, 'After replacing a finished animation\'s effect with a longer one ' +
'it fires an animationstart event');
+test(t => {
+ const div = addDiv(t);
+
+ // Create custom keyframes so we can tweak them
+ const stylesheet = document.styleSheets[0];
+ const keyframes = '@keyframes anim-custom { to { left: 100px } }';
+ const ruleIndex = stylesheet.insertRule(keyframes, 0);
+ const keyframesRule = stylesheet.cssRules[ruleIndex];
+
+ t.add_cleanup(function() {
+ stylesheet.deleteRule(ruleIndex);
+ });
+
+ div.style.animation = 'anim-custom 100s';
+
+ // Replace the effect
+ const animation = div.getAnimations()[0];
+ animation.effect = new KeyframeEffect(
+ div,
+ { left: '200px' },
+ 200 * MS_PER_SEC
+ );
+
+ // Update the timing properties
+ div.style.animationDuration = '4s';
+ div.style.animationIterationCount = '6';
+ div.style.animationDirection = 'reverse';
+ div.style.animationDelay = '8s';
+ div.style.animationFillMode = 'both';
+ div.style.animationPlayState = 'paused';
+ getComputedStyle(div).animationDuration;
+
+ // Update the keyframes
+ keyframesRule.deleteRule(0);
+ keyframesRule.appendRule('to { left: 300px }');
+
+ // Check nothing (except the play state) changed
+ assert_equals(
+ animation.effect.getTiming().duration,
+ 200 * MS_PER_SEC,
+ 'duration should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getTiming().iterations,
+ 1,
+ 'iterations should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getTiming().direction,
+ 'normal',
+ 'direction should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getTiming().delay,
+ 0,
+ 'delay should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getTiming().fill,
+ 'auto',
+ 'fill should be the value set by the API'
+ );
+ assert_equals(
+ animation.effect.getKeyframes()[0].left,
+ '200px',
+ 'keyframes should be the value set by the API'
+ );
+
+ // Unlike the other properties animation-play-state maps to the Animation
+ // not the KeyframeEffect so it should be overridden.
+ assert_equals(
+ animation.playState,
+ 'paused',
+ 'play state should be the value set by style'
+ );
+}, 'Replacing the effect of a CSSAnimation causes subsequent changes to'
+ + ' corresponding animation-* properties to be ignored');
+
</script>
diff --git a/tests/wpt/web-platform-tests/css/css-animations/CSSAnimation-pausing.tentative.html b/tests/wpt/web-platform-tests/css/css-animations/CSSAnimation-pausing.tentative.html
index 2b6e6853b41..156a1afa964 100644
--- a/tests/wpt/web-platform-tests/css/css-animations/CSSAnimation-pausing.tentative.html
+++ b/tests/wpt/web-platform-tests/css/css-animations/CSSAnimation-pausing.tentative.html
@@ -16,129 +16,218 @@
<script>
'use strict';
-const getMarginLeft = cs => parseFloat(cs.marginLeft);
-
promise_test(async t => {
const div = addDiv(t);
- const cs = getComputedStyle(div);
div.style.animation = 'anim 1000s paused';
+
const animation = div.getAnimations()[0];
- assert_equals(getMarginLeft(cs), 0,
- 'Initial value of margin-left is zero');
animation.play();
await animation.ready;
await waitForNextFrame();
- assert_greater_than(getMarginLeft(cs), 0,
- 'Playing value of margin-left is greater than zero');
+ assert_equals(
+ animation.playState,
+ 'running',
+ 'Play state is running after calling play()'
+ );
+
+ // Flip the animation-play-state back and forth to check it has no effect
+
+ div.style.animationPlayState = 'running';
+ getComputedStyle(div).animationPlayState;
+ div.style.animationPlayState = 'paused';
+ getComputedStyle(div).animationPlayState;
+
+ assert_equals(
+ animation.playState,
+ 'running',
+ 'Should still be running even after flipping the animation-play-state'
+ );
}, 'play() overrides animation-play-state');
promise_test(async t => {
const div = addDiv(t);
- const cs = getComputedStyle(div);
- div.style.animation = 'anim 1000s paused';
+ div.style.animation = 'anim 100s infinite paused';
+
const animation = div.getAnimations()[0];
- assert_equals(getMarginLeft(cs), 0,
- 'Initial value of margin-left is zero');
+ animation.playbackRate = -1;
+ animation.currentTime = -1;
+ assert_throws_dom('InvalidStateError', () => {
+ animation.play();
+ }, 'Trying to play a reversed infinite animation should throw');
+
+ assert_equals(
+ animation.playState,
+ 'paused',
+ 'Animation should still be paused'
+ );
+
+ animation.playbackRate = 1;
+ div.style.animationPlayState = 'running';
+
+ assert_equals(
+ animation.playState,
+ 'running',
+ 'Changing the animation-play-state should play the animation'
+ );
+}, 'play() does NOT override the animation-play-state if there was an error');
+
+promise_test(async t => {
+ const div = addDiv(t);
+ div.style.animation = 'anim 1000s paused';
+
+ const animation = div.getAnimations()[0];
animation.pause();
+
div.style.animationPlayState = 'running';
+ getComputedStyle(div).animationPlayState;
await animation.ready;
await waitForNextFrame();
- assert_equals(cs.animationPlayState, 'running',
- 'animation-play-state is running');
- assert_equals(getMarginLeft(cs), 0,
- 'Paused value of margin-left is zero');
+ assert_equals(animation.playState, 'paused', 'playState is paused ');
+
+ // Flip the animation-play-state back and forth to check it has no effect
+
+ div.style.animationPlayState = 'paused';
+ getComputedStyle(div).animationPlayState;
+ div.style.animationPlayState = 'running';
+ getComputedStyle(div).animationPlayState;
+
+ assert_equals(
+ animation.playState,
+ 'paused',
+ 'Should still be paused even after flipping the animation-play-state'
+ );
}, 'pause() overrides animation-play-state');
promise_test(async t => {
const div = addDiv(t);
- const cs = getComputedStyle(div);
- div.style.animation = 'anim 1000s paused';
+ div.style.animation = 'anim 100s paused';
+
const animation = div.getAnimations()[0];
- assert_equals(getMarginLeft(cs), 0,
- 'Initial value of margin-left is zero');
- animation.play();
+ animation.reverse();
- await animation.ready;
+ assert_equals(
+ animation.playState,
+ 'running',
+ 'Play state is running after calling reverse()'
+ );
- div.style.animationPlayState = 'running';
- cs.animationPlayState; // Trigger style resolution
- await waitForNextFrame();
+ // Flip the animation-play-state back and forth to check it has no effect
- assert_equals(cs.animationPlayState, 'running',
- 'animation-play-state is running');
+ div.style.animationPlayState = 'running';
+ getComputedStyle(div).animationPlayState;
div.style.animationPlayState = 'paused';
- await animation.ready;
+ getComputedStyle(div).animationPlayState;
- assert_equals(cs.animationPlayState, 'paused',
- 'animation-play-state is paused');
- const previousAnimVal = getMarginLeft(cs);
- await waitForNextFrame();
-
- assert_equals(getMarginLeft(cs), previousAnimVal,
- 'Animated value of margin-left does not change when'
- + ' paused by style');
-}, 'play() is overridden by later setting "animation-play-state: paused"');
+ assert_equals(
+ animation.playState,
+ 'running',
+ 'Should still be running even after flipping the animation-play-state'
+ );
+}, 'reverse() overrides animation-play-state when it starts playing the'
+ + ' animation');
promise_test(async t => {
const div = addDiv(t);
- const cs = getComputedStyle(div);
- div.style.animation = 'anim 1000s';
+ div.style.animation = 'anim 100s';
+
const animation = div.getAnimations()[0];
- assert_equals(getMarginLeft(cs), 0,
- 'Initial value of margin-left is zero');
+ animation.reverse();
+
+ assert_equals(
+ animation.playState,
+ 'running',
+ 'Play state is running after calling reverse()'
+ );
- // Set the specified style first. If implementations fail to
- // apply the style changes first, they will ignore the redundant
- // call to play() and fail to correctly override the pause style.
div.style.animationPlayState = 'paused';
- animation.play();
- const previousAnimVal = getMarginLeft(cs);
+ getComputedStyle(div).animationPlayState;
- await animation.ready;
- await waitForNextFrame();
+ assert_equals(
+ animation.playState,
+ 'paused',
+ 'Should be paused after changing the animation-play-state'
+ );
+}, 'reverse() does NOT override animation-play-state if the animation is'
+ + ' already running');
+
+promise_test(async t => {
+ const div = addDiv(t);
+ div.style.animation = 'anim 100s';
+
+ const animation = div.getAnimations()[0];
+ animation.startTime = null;
+
+ assert_equals(
+ animation.playState,
+ 'paused',
+ 'Play state is paused after setting the start time to null'
+ );
+
+ // Flip the animation-play-state back and forth to check it has no effect
+
+ div.style.animationPlayState = 'paused';
+ getComputedStyle(div).animationPlayState;
+ div.style.animationPlayState = 'running';
+ getComputedStyle(div).animationPlayState;
- assert_equals(cs.animationPlayState, 'paused',
- 'animation-play-state is paused');
- assert_greater_than(getMarginLeft(cs), previousAnimVal,
- 'Playing value of margin-left is increasing');
-}, 'play() flushes pending changes to animation-play-state first');
+ assert_equals(
+ animation.playState,
+ 'paused',
+ 'Should still be paused even after flipping the animation-play-state'
+ );
+}, 'Setting the startTime to null overrides animation-play-state if the'
+ + ' animation is already running');
promise_test(async t => {
const div = addDiv(t);
- const cs = getComputedStyle(div);
- div.style.animation = 'anim 1000s paused';
+ div.style.animation = 'anim 100s paused';
+
const animation = div.getAnimations()[0];
- assert_equals(getMarginLeft(cs), 0,
- 'Initial value of margin-left is zero');
-
- // Unlike the previous test for play(), since calling pause() is sticky,
- // we'll apply it even if the underlying style also says we're paused.
- //
- // We would like to test that implementations flush styles before running
- // pause() but actually there's no style we can currently set that will
- // change the behavior of pause(). That may change in the future
- // (e.g. if we introduce animation-timeline or animation-playback-rate etc.).
- //
- // For now this just serves as a sanity check that we do the same thing
- // even if we set style before calling the API.
+ animation.startTime = document.timeline.currentTime;
+
+ assert_equals(
+ animation.playState,
+ 'running',
+ 'Play state is running after setting the start time to non-null'
+ );
+
+ // Flip the animation-play-state back and forth to check it has no effect
+
div.style.animationPlayState = 'running';
- animation.pause();
- const previousAnimVal = getMarginLeft(cs);
+ getComputedStyle(div).animationPlayState;
+ div.style.animationPlayState = 'paused';
+ getComputedStyle(div).animationPlayState;
- await animation.ready;
- await waitForNextFrame();
+ assert_equals(
+ animation.playState,
+ 'running',
+ 'Should still be running even after flipping the animation-play-state'
+ );
+}, 'Setting the startTime to non-null overrides animation-play-state if the'
+ + ' animation is paused');
+
+promise_test(async t => {
+ const div = addDiv(t);
+ div.style.animation = 'anim 100s';
+
+ const animation = div.getAnimations()[0];
+ animation.startTime = document.timeline.currentTime;
+
+ div.style.animationPlayState = 'paused';
+ getComputedStyle(div).animationPlayState;
- assert_equals(cs.animationPlayState, 'running',
- 'animation-play-state is running');
- assert_equals(getMarginLeft(cs), previousAnimVal,
- 'Paused value of margin-left does not change');
-}, 'pause() applies pending changes to animation-play-state first');
-// (Note that we can't actually test for this; see comment above, in test-body.)
+ assert_equals(
+ animation.playState,
+ 'paused',
+ 'Should be paused after changing the animation-play-state'
+ );
+}, 'Setting the startTime to non-null does NOT override the'
+ + ' animation-play-state if the animation is already running');
promise_test(async t => {
const div = addDiv(t, { style: 'animation: anim 1000s' });
diff --git a/tests/wpt/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative.html b/tests/wpt/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative.html
index 591cc15a7ed..f7d767dea8c 100644
--- a/tests/wpt/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative.html
+++ b/tests/wpt/web-platform-tests/css/css-animations/KeyframeEffect-getKeyframes.tentative.html
@@ -164,20 +164,6 @@
const getKeyframes = elem => elem.getAnimations()[0].effect.getKeyframes();
-const assert_frames_equal = (a, b, name) => {
- assert_equals(Object.keys(a).sort().toString(),
- Object.keys(b).sort().toString(),
- "properties on " + name);
- for (const p in a) {
- if (p === 'offset' || p === 'computedOffset') {
- assert_approx_equals(a[p], b[p], 0.00001,
- "value for '" + p + "' on " + name);
- } else {
- assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
- }
- }
-};
-
// animation-timing-function values to test with, where the value
// is exactly the same as its serialization, sorted by the order
// getKeyframes() will group frames with the same easing function
@@ -221,11 +207,9 @@ test(t => {
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-simple 100s';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease",
@@ -233,10 +217,7 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease",
color: "rgb(255, 255, 255)", composite: "auto" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for a simple'
+ ' animation');
@@ -292,11 +273,9 @@ test(t => {
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-simple-shorthand 100s';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
@@ -306,21 +285,16 @@ test(t => {
marginBottom: "16px", marginLeft: "16px",
marginRight: "16px", marginTop: "16px" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for a simple'
+ ' animation that specifies a single shorthand property');
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-omit-to 100s';
div.style.color = 'rgb(255, 255, 255)';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
@@ -328,21 +302,16 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
color: "rgb(255, 255, 255)" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
'animation with a 0% keyframe and no 100% keyframe');
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-omit-from 100s';
div.style.color = 'rgb(255, 255, 255)';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
@@ -350,21 +319,16 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
color: "rgb(0, 0, 255)" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
'animation with a 100% keyframe and no 0% keyframe');
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-omit-from-to 100s';
div.style.color = 'rgb(255, 255, 255)';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 3, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
@@ -374,21 +338,16 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
color: "rgb(255, 255, 255)" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
'animation with no 0% or 100% keyframe but with a 50% keyframe');
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-partially-omit-to 100s';
div.style.marginTop = '250px';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
@@ -396,21 +355,16 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
marginTop: '250px', marginBottom: '200px' },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
'animation with a partially complete 100% keyframe (because the ' +
'!important rule is ignored)');
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-different-props 100s';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 4, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
@@ -422,21 +376,16 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
color: "rgb(255, 255, 255)", marginTop: "16px" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
'animation with different properties on different keyframes, all ' +
'with the same easing function');
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-different-props-and-easing 100s';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 4, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "linear", composite: "auto",
@@ -448,21 +397,16 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
color: "rgb(255, 255, 255)", marginTop: "16px" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
'animation with different properties on different keyframes, with ' +
'a different easing function on each');
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-merge-offset 100s';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
@@ -470,21 +414,16 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
color: "rgb(255, 255, 255)", marginTop: "16px" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
'animation with multiple keyframes for the same time, and all with ' +
'the same easing function');
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-merge-offset-and-easing 100s';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 3, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "steps(1)", composite: "auto",
@@ -495,21 +434,16 @@ test(t => {
color: "rgb(255, 255, 255)", fontSize: "32px", marginTop: "16px",
paddingLeft: "4px" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
'animation with multiple keyframes for the same time and with ' +
'different easing functions');
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-no-merge-equiv-easing 100s';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 3, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "steps(1)", composite: "auto",
@@ -519,21 +453,16 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
marginTop: "20px", marginRight: "20px", marginBottom: "20px" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for an ' +
'animation with multiple keyframes for the same time and with ' +
'different but equivalent easing functions');
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-overriding 100s';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 6, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
@@ -549,10 +478,7 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
paddingTop: "70px" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected frames for ' +
'overlapping keyframes');
@@ -561,11 +487,9 @@ test(t => {
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-filter 100s';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
@@ -573,20 +497,15 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
filter: "blur(5px) sepia(60%) saturate(30%)" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected values for ' +
'animations with filter properties and missing keyframes');
test(t => {
const div = addDiv(t);
-
div.style.animation = 'anim-filter-drop-shadow 100s';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
@@ -594,10 +513,7 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
filter: "drop-shadow(rgb(255, 0, 0) 50px 30px 10px)" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected values for ' +
'animation with drop-shadow of filter property');
@@ -607,14 +523,12 @@ test(t => {
test(t => {
const div = addDiv(t);
-
div.style.textShadow = '1px 1px 2px rgb(0, 0, 0), ' +
'0 0 16px rgb(0, 0, 255), ' +
'0 0 3.2px rgb(0, 0, 255)';
div.style.animation = 'anim-text-shadow 100s';
- const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
+ const frames = getKeyframes(div);
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
@@ -624,10 +538,7 @@ test(t => {
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
textShadow: "none" },
];
-
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected values for ' +
'animations with text-shadow properties and missing keyframes');
@@ -673,17 +584,13 @@ test(t => {
const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
-
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
transform: "none" },
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
transform: "translate(100px)" },
];
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected values for ' +
'animations with CSS variables as keyframe values');
@@ -693,8 +600,6 @@ test(t => {
const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
-
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
marginBottom: "0px",
@@ -707,9 +612,7 @@ test(t => {
marginRight: "100px",
marginTop: "100px" },
];
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected values for ' +
'animations with CSS variables as keyframe values in a shorthand property');
@@ -719,17 +622,13 @@ test(t => {
const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
-
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
color: "rgb(0, 0, 0)" },
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
color: "rgb(0, 255, 0)" },
];
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected values for ' +
'animations with a CSS variable which is overriden by the value in keyframe');
@@ -739,19 +638,63 @@ test(t => {
const frames = getKeyframes(div);
- assert_equals(frames.length, 2, "number of frames");
-
const expected = [
{ offset: 0, computedOffset: 0, easing: "ease", composite: "auto",
transform: "translate(100px)" },
{ offset: 1, computedOffset: 1, easing: "ease", composite: "auto",
transform: "none" },
];
- for (let i = 0; i < frames.length; i++) {
- assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
- }
+ assert_frame_lists_equal(frames, expected);
}, 'KeyframeEffect.getKeyframes() returns expected values for ' +
'animations with only custom property in a keyframe');
+test(t => {
+ const div = addDiv(t);
+
+ // Add custom @keyframes rule
+ const stylesheet = document.styleSheets[0];
+ const keyframes = '@keyframes anim-custom { to { left: 100px } }';
+ const ruleIndex = stylesheet.insertRule(keyframes, 0);
+ const keyframesRule = stylesheet.cssRules[ruleIndex];
+
+ t.add_cleanup(function() {
+ stylesheet.deleteRule(ruleIndex);
+ });
+
+ div.style.animation = 'anim-custom 100s';
+
+ // Sanity check the initial result
+ let frames = getKeyframes(div);
+ assert_frames_equal(
+ frames[frames.length - 1],
+ {
+ offset: 1,
+ computedOffset: 1,
+ easing: 'ease',
+ composite: 'auto',
+ left: '100px',
+ },
+ 'Keyframes reflect the initial @keyframes rule'
+ );
+
+ // Update the @keyframes rule
+ keyframesRule.deleteRule(0);
+ keyframesRule.appendRule('to { left: 200px }');
+
+ // Check the result from getKeyframes() is updated
+ frames = getKeyframes(div);
+ assert_frames_equal(
+ frames[frames.length - 1],
+ {
+ offset: 1,
+ computedOffset: 1,
+ easing: 'ease',
+ composite: 'auto',
+ left: '200px',
+ },
+ 'Keyframes reflects the updated @keyframes rule'
+ );
+}, 'KeyframeEffect.getKeyframes() reflects changes to @keyframes rules');
+
</script>
</body>
diff --git a/tests/wpt/web-platform-tests/css/css-animations/KeyframeEffect-setKeyframes.tentative.html b/tests/wpt/web-platform-tests/css/css-animations/KeyframeEffect-setKeyframes.tentative.html
new file mode 100644
index 00000000000..7d8f845413a
--- /dev/null
+++ b/tests/wpt/web-platform-tests/css/css-animations/KeyframeEffect-setKeyframes.tentative.html
@@ -0,0 +1,122 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>KeyframeEffect.setKeyframes() for CSS animations</title>
+<!-- TODO: Add a more specific link for this once it is specified. -->
+<link rel="help" href="https://drafts.csswg.org/css-animations-2/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/testcommon.js"></script>
+<style>
+@keyframes anim-simple {
+ from { left: 0px }
+ to { left: 100px }
+}
+</style>
+<body>
+<div id="log"></div>
+<script>
+"use strict";
+
+// Note that the sanity check that getKeyframes() normally DOES return the
+// updated keyframes is contained in KeyframeEffect-getKeyframes.html.
+test(t => {
+ const div = addDiv(t);
+
+ // Add custom @keyframes rule
+ const stylesheet = document.styleSheets[0];
+ const keyframes = '@keyframes anim-custom { to { left: 100px } }';
+ const ruleIndex = stylesheet.insertRule(keyframes, 0);
+ const keyframesRule = stylesheet.cssRules[ruleIndex];
+
+ t.add_cleanup(function() {
+ stylesheet.deleteRule(ruleIndex);
+ });
+
+ div.style.animation = 'anim-custom 100s';
+
+ // Update the keyframes via the API
+ const animation = div.getAnimations()[0];
+ animation.effect.setKeyframes({ left: '200px' });
+
+ // Then update them via style
+ keyframesRule.deleteRule(0);
+ keyframesRule.appendRule('to { left: 300px }');
+
+ // The result should be the keyframes as set by the API, not via style.
+ const frames = animation.effect.getKeyframes();
+ assert_frames_equal(
+ frames[frames.length - 1],
+ {
+ offset: null,
+ computedOffset: 1,
+ easing: 'linear',
+ composite: 'auto',
+ left: '200px',
+ },
+ 'Keyframes reflect the value set via setKeyframes'
+ );
+}, 'KeyframeEffect.setKeyframes() causes subsequent changes to @keyframes'
+ + ' rules to be ignored');
+
+test(t => {
+ const div = addDiv(t);
+ div.style.animation = 'anim-simple 100s';
+
+ const animation = div.getAnimations()[0];
+ assert_equals(animation.effect.getKeyframes()[0].easing, 'ease');
+
+ animation.effect.setKeyframes({ left: ['200px', '300px'] });
+ assert_equals(animation.effect.getKeyframes()[0].easing, 'linear');
+
+ div.style.animationTimingFunction = 'ease-in';
+ getComputedStyle(div).animationTimingFunction;
+
+ assert_equals(
+ animation.effect.getKeyframes()[0].easing,
+ 'linear',
+ 'Easing should be the easing set by the API'
+ );
+}, 'KeyframeEffect.setKeyframes() causes subsequent changes to'
+ + ' animation-timing-function to be ignored');
+
+test(t => {
+ const div = addDiv(t);
+
+ const stylesheet = document.styleSheets[0];
+ const keyframes = '@keyframes anim-custom { to { left: 100px } }';
+ const ruleIndex = stylesheet.insertRule(keyframes, 0);
+ const keyframesRule = stylesheet.cssRules[ruleIndex];
+
+ t.add_cleanup(function() {
+ stylesheet.deleteRule(ruleIndex);
+ });
+
+ div.style.animation = 'anim-custom 100s';
+
+ // Try updating in a way that throws an error
+ const animation = div.getAnimations()[0];
+ assert_throws_js(TypeError, () => {
+ animation.effect.setKeyframes({ left: '200px', offset: 'yer' });
+ });
+
+ keyframesRule.deleteRule(0);
+ keyframesRule.appendRule('to { left: 300px }');
+
+ // The result should be the keyframes as set via style.
+ const frames = animation.effect.getKeyframes();
+ assert_frames_equal(
+ frames[frames.length - 1],
+ {
+ offset: 1,
+ computedOffset: 1,
+ easing: 'ease',
+ composite: 'auto',
+ left: '300px',
+ },
+ 'Keyframes reflect the value set via style'
+ );
+}, 'KeyframeEffect.setKeyframes() should NOT cause subsequent changes to'
+ + ' @keyframes rules to be ignored if it threw');
+
+</script>
+</body>
diff --git a/tests/wpt/web-platform-tests/css/css-animations/support/testcommon.js b/tests/wpt/web-platform-tests/css/css-animations/support/testcommon.js
index b4fde4b967d..7d63d2c49bc 100644
--- a/tests/wpt/web-platform-tests/css/css-animations/support/testcommon.js
+++ b/tests/wpt/web-platform-tests/css/css-animations/support/testcommon.js
@@ -36,6 +36,55 @@ function assert_time_equals_literal(actual, expected, description) {
assert_approx_equals(actual, expected, TIME_PRECISION, description);
}
+/*
+ * Compare two keyframes
+ */
+function assert_frames_equal(actual, expected, name) {
+ // TODO: Make this skip the 'composite' member when it is not specified in
+ // `expected` or when the implementation does not support it.
+ assert_array_equals(
+ Object.keys(actual).sort(),
+ Object.keys(expected).sort(),
+ `properties on ${name} should match`
+ );
+
+ for (const prop in actual) {
+ if (
+ // 'offset' can be null
+ (prop === 'offset' && typeof actual[prop] === 'number') ||
+ prop === 'computedOffset'
+ ) {
+ assert_approx_equals(
+ actual[prop],
+ expected[prop],
+ 0.00001,
+ "value for '" + prop + "' on " + name
+ );
+ } else {
+ assert_equals(
+ actual[prop],
+ expected[prop],
+ `value for '${prop}' on ${name} should match`
+ );
+ }
+ }
+}
+
+/*
+ * Compare two lists of keyframes
+ */
+function assert_frame_lists_equal(actual, expected) {
+ assert_equals(
+ actual.length,
+ expected.length,
+ 'Number of keyframes should match'
+ );
+
+ for (let i = 0; i < actual.length; i++) {
+ assert_frames_equal(actual[i], expected[i], `Keyframe #${i}`);
+ }
+}
+
/**
* Appends a div to the document body.
*
diff --git a/tests/wpt/web-platform-tests/css/css-values/round-function.html b/tests/wpt/web-platform-tests/css/css-values/round-function.html
index 236b9a9a8a3..b1e950efe72 100644
--- a/tests/wpt/web-platform-tests/css/css-values/round-function.html
+++ b/tests/wpt/web-platform-tests/css/css-values/round-function.html
@@ -1,5 +1,6 @@
<!doctype html>
<title>round() function</title>
+<meta charset=utf-8>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../support/numeric-testcommon.js"></script>
diff --git a/tests/wpt/web-platform-tests/css/support/numeric-testcommon.js b/tests/wpt/web-platform-tests/css/support/numeric-testcommon.js
index 56022d06399..996250d359d 100644
--- a/tests/wpt/web-platform-tests/css/support/numeric-testcommon.js
+++ b/tests/wpt/web-platform-tests/css/support/numeric-testcommon.js
@@ -35,16 +35,20 @@ function test_math_used(testString, expectedString, {base="123px", msg, prop="le
All of these expect the testString to evaluate to a <number>.
*/
function test_plus_infinity(testString) {
- test_math_used(`calc(1px * ${testString})`, "calc(infinity * 1px)");
+ test_math_used(`calc(1px * ${testString})`, "calc(infinity * 1px)",
+ {msg:`${testString} should equal +Infinity.`});
}
function test_minus_infinity(testString) {
- test_math_used(`calc(1px * ${testString})`, "calc(-infinity * 1px)");
+ test_math_used(`calc(1px * ${testString})`, "calc(-infinity * 1px)",
+ {msg:`${testString} should equal -Infinity.`});
}
function test_plus_zero(testString) {
- test_math_used(`calc(1px / ${testString})`, "calc(infinity * 1px)");
+ test_math_used(`calc(1px / ${testString})`, "calc(infinity * 1px)",
+ {msg:`${testString} should equal 0⁺.`});
}
function test_minus_zero(testString) {
- test_math_used(`calc(1px / ${testString})`, "calc(-infinity * 1px)");
+ test_math_used(`calc(1px / ${testString})`, "calc(-infinity * 1px)",
+ {msg:`${testString} should equal 0⁻.`});
}
function test_nan(testString) {
// Make sure that it's NaN, not an infinity,
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https.html
index 2559de839a3..dced705206f 100644
--- a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https.html
+++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/dedicated-worker-cache-storage.https.html
@@ -5,6 +5,7 @@
<script src="/resources/testharnessreport.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script>
+// See also: ./shared-worker-cache-storage.https.html
function remote(path) {
const REMOTE_ORIGIN = get_host_info().HTTPS_REMOTE_ORIGIN;
@@ -12,11 +13,11 @@ function remote(path) {
}
const iframe_path = "./resources/iframe.html?pipe=";
-const dedicated_worker_path = "./dedicated-worker.js?pipe=";
+const dedicated_worker_path = "./universal-worker.js?pipe=";
const ressource_path = "/images/blue.png?pipe=";
const coep_header= {
- "coep-none" : "|header(Cross-Origin-Embedder-Policy,none)",
+ "coep-none" : "",
"coep-require-corp" : "|header(Cross-Origin-Embedder-Policy,require-corp)",
}
@@ -107,7 +108,7 @@ function check(
iframe.contentWindow.postMessage(iframe_eval);
const {data} = await iframe_response;
- assert_equals(data == "success", loaded);
+ assert_equals(data === "success", loaded);
}, `${iframe_coep} ${worker_coep} ${response_corp}`)
}
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/dedicated-worker.js b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/universal-worker.js
index 5d46edcde24..5d46edcde24 100644
--- a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/dedicated-worker.js
+++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/resources/universal-worker.js
diff --git a/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/service-worker-cache-storage.https.html b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/service-worker-cache-storage.https.html
new file mode 100644
index 00000000000..873f06ce4ff
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/cross-origin-embedder-policy/service-worker-cache-storage.https.html
@@ -0,0 +1,117 @@
+<!doctype html>
+<html>
+<title> Check enforcement of COEP in a ServiceWorker using CacheStorage. </title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+<script>
+// See also: ./dedicated-worker-cache-storage.https.html
+
+function remote(path) {
+ const REMOTE_ORIGIN = get_host_info().HTTPS_REMOTE_ORIGIN;
+ return new URL(path, REMOTE_ORIGIN);
+}
+
+const iframe_path = "./resources/iframe.html?pipe=";
+const service_worker_path = "./resources/universal-worker.js?pipe=";
+const ressource_path = "/images/blue.png?pipe=";
+
+const coep_header= {
+ "coep-none" : "",
+ "coep-require-corp" : "|header(Cross-Origin-Embedder-Policy,require-corp)",
+}
+
+const corp_header = {
+ "corp-undefined" : "",
+ "corp-cross-origin" : "|header(Cross-Origin-Resource-Policy,cross-origin)",
+}
+
+// Send a message to the |worker| and wait for its response.
+function executeCommandInServiceWorker(worker, command) {
+ const channel = new MessageChannel();
+ const response = new Promise(resolve => channel.port1.onmessage = resolve);
+ worker.postMessage(command, [ channel.port2 ]);
+ return response;
+}
+
+// Check enforcement of COEP in a ServiceWorker using CacheStorage.
+//
+// 1) Fetch a response from a document with COEP:none. Store it in the
+// CacheStorage. The response is cross-origin without any CORS header.
+// 2) From a ServiceWorker, retrieve the response from the CacheStorage.
+//
+// Test parameters:
+// - |worker_coep| the COEP header of the ServiceWorker's script response.
+// - |response_corp| the CORP header of the response.
+//
+// Test expectations:
+// |loaded| is true whenever the worker is able to fetch the response from
+// the CacheStorage. According to the specification:
+// https://mikewest.github.io/corpp/#initialize-embedder-policy-for-global
+// it must be false when:
+// - |worker_coep| is 'coep-require-corp' and
+// - |response-corp| is 'corp-undefined'.
+function check(
+ // Test parameters:
+ worker_coep,
+ response_corp,
+
+ // Test expectations:
+ loaded) {
+
+ promise_test(async (t) => {
+ // 1) Fetch a response from a document with COEP:none. Store it in the
+ // CacheStorage. The response is cross-origin without any CORS header.
+ const resource_path = ressource_path + corp_header[response_corp];
+ const resource_url = remote(resource_path);
+ const fetch_request = new Request(resource_url, {mode: 'no-cors'});
+ const cache = await caches.open('v1');
+ const fetch_response = await fetch(fetch_request);
+ await cache.put(fetch_request, fetch_response);
+
+ // 2) Start a ServiceWorker.
+ const SCOPE= new URL(location.href).pathname;
+ const service_worker_allowed = `|header(service-worker-allowed,${SCOPE})`;
+ const SCRIPT =
+ service_worker_path +
+ coep_header[worker_coep] +
+ service_worker_allowed;
+
+ const reg = await service_worker_unregister_and_register(t, SCRIPT, SCOPE);
+ add_completion_callback(() => reg.unregister());
+
+ // Start talking to the ServiceWorker, no matter its state.
+ const worker = reg.installing || reg.waiting || reg.active;
+
+ // 3) From the service worker, try to retrieve the response from the
+ // CacheStorage.
+ const response = executeCommandInServiceWorker(worker, `
+ (async function() {
+ const cache = await caches.open('v1');
+ const request = new Request('${resource_url}', {
+ mode: 'no-cors'
+ });
+ try {
+ const response = await cache.match(request);
+ message.ports[0].postMessage('success');
+ } catch(error) {
+ message.ports[0].postMessage('error');
+ }
+ })()
+ `);
+ const {data} = await response;
+ assert_equals(data === "success", loaded);
+ }, `A ServiceWorker with ${worker_coep} use CacheStorage to get a ${response_corp} response.`)
+}
+
+// ------------------------------------------------------
+// worker_coep , response_corp , loaded
+// ------------------------------------------------------
+check("coep-none" , "corp-undefined" , true);
+check("coep-none" , "corp-cross-origin" , true);
+check("coep-require-corp" , "corp-undefined" , false);
+check("coep-require-corp" , "corp-cross-origin" , true);
+
+</script>
+</html>
diff --git a/tests/wpt/web-platform-tests/interfaces/construct-stylesheets.idl b/tests/wpt/web-platform-tests/interfaces/construct-stylesheets.idl
index fca2a3e2887..35121866f66 100644
--- a/tests/wpt/web-platform-tests/interfaces/construct-stylesheets.idl
+++ b/tests/wpt/web-platform-tests/interfaces/construct-stylesheets.idl
@@ -16,6 +16,6 @@ dictionary CSSStyleSheetInit {
boolean disabled = false;
};
-partial interface DocumentOrShadowRoot {
+partial interface mixin DocumentOrShadowRoot {
attribute FrozenArray<CSSStyleSheet> adoptedStyleSheets;
};
diff --git a/tests/wpt/web-platform-tests/native-file-system/script-tests/FileSystemBaseHandle-IndexedDB.js b/tests/wpt/web-platform-tests/native-file-system/script-tests/FileSystemBaseHandle-IndexedDB.js
index d7403ff5ea6..855e52f04dd 100644
--- a/tests/wpt/web-platform-tests/native-file-system/script-tests/FileSystemBaseHandle-IndexedDB.js
+++ b/tests/wpt/web-platform-tests/native-file-system/script-tests/FileSystemBaseHandle-IndexedDB.js
@@ -100,3 +100,27 @@ directory_test(async (t, root_dir) => {
assert_equals(result.length, value.length);
await assert_equals_cloned_handles(result, value);
}, 'Store handle in IndexedDB and read using a cursor.');
+
+directory_test(async (t, root_dir) => {
+ const handles = await create_file_system_handles(t, root_dir);
+
+ const db = await createDatabase(t, db => {
+ const store = db.createObjectStore('store', {keyPath: 'key'});
+ });
+ t.add_cleanup(() => deleteAllDatabases(t));
+
+ const value = handles;
+ let tx = db.transaction('store', 'readwrite');
+ let store = tx.objectStore('store');
+ await promiseForRequest(t, store.put({key: 'key', value}));
+ await promiseForTransaction(t, tx);
+
+ tx = db.transaction('store', 'readonly');
+ store = tx.objectStore('store');
+ const result = await promiseForRequest(t, store.get('key'));
+ await promiseForTransaction(t, tx);
+
+ assert_true(Array.isArray(result.value), 'Result should be an array');
+ assert_equals(result.value.length, value.length);
+ await assert_equals_cloned_handles(result.value, value);
+}, 'Store handle in IndexedDB using inline keys.');
diff --git a/tests/wpt/web-platform-tests/resources/chromium/nfc-mock.js b/tests/wpt/web-platform-tests/resources/chromium/nfc-mock.js
index 7832a8231ef..14bb8fdada3 100644
--- a/tests/wpt/web-platform-tests/resources/chromium/nfc-mock.js
+++ b/tests/wpt/web-platform-tests/resources/chromium/nfc-mock.js
@@ -26,6 +26,10 @@ function toMojoNDEFRecord(record) {
nfcRecord.recordType = record.recordType;
nfcRecord.mediaType = record.mediaType;
nfcRecord.id = record.id;
+ if (record.recordType == 'text') {
+ nfcRecord.encoding = record.encoding == null? 'utf-8': record.encoding;
+ nfcRecord.lang = record.lang == null? 'en': record.lang;
+ }
nfcRecord.data = toByteArray(record.data);
if (record.data != null && record.data.records !== undefined) {
// |record.data| may be an NDEFMessageInit, i.e. the payload is a message.
@@ -72,6 +76,17 @@ function compareNDEFRecords(providedRecord, receivedRecord) {
assert_not_equals(providedRecord.recordType, 'empty');
+ if (providedRecord.recordType == 'text') {
+ assert_equals(
+ providedRecord.encoding == null? 'utf-8': providedRecord.encoding,
+ receivedRecord.encoding);
+ assert_equals(providedRecord.lang == null? 'en': providedRecord.lang,
+ receivedRecord.lang);
+ } else {
+ assert_equals(null, receivedRecord.encoding);
+ assert_equals(null, receivedRecord.lang);
+ }
+
assert_array_equals(toByteArray(providedRecord.data),
new Uint8Array(receivedRecord.data));
}
diff --git a/tests/wpt/web-platform-tests/tools/wpt/revlist.py b/tests/wpt/web-platform-tests/tools/wpt/revlist.py
index c4cbc2943b7..1893fdefa83 100644
--- a/tests/wpt/web-platform-tests/tools/wpt/revlist.py
+++ b/tests/wpt/web-platform-tests/tools/wpt/revlist.py
@@ -106,11 +106,14 @@ def get_parser():
type=int,
help="maximum number of revisions to be returned by "
"the command")
+ parser.add_argument("--verbose", action="store_true", help="debug logging")
return parser
def run_rev_list(**kwargs):
# type: (**Any) -> None
+ if kwargs.get('verbose'):
+ logger.setLevel(logging.DEBUG)
# "epoch_threshold" is a safety margin. After this time it is fine to
# assume that any tags are created and pushed.
epoch_threshold = 600
diff --git a/tests/wpt/web-platform-tests/web-nfc/resources/nfc-helpers.js b/tests/wpt/web-platform-tests/web-nfc/resources/nfc-helpers.js
index 5bec071dfa7..b1753ddd1b3 100644
--- a/tests/wpt/web-platform-tests/web-nfc/resources/nfc-helpers.js
+++ b/tests/wpt/web-platform-tests/web-nfc/resources/nfc-helpers.js
@@ -192,7 +192,8 @@ function assertWebNDEFMessagesEqual(message, expectedMessage) {
assert_equals(record.recordType, expectedRecord.recordType);
assert_equals(record.mediaType, expectedRecord.mediaType);
assert_equals(record.id, expectedRecord.id);
-
+ assert_equals(record.encoding, expectedRecord.encoding);
+ assert_equals(record.lang, expectedRecord.lang);
// Compares record data
assert_array_equals(new Uint8Array(record.data),
new Uint8Array(expectedRecord.data));
diff --git a/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/suspended-context-messageport.https.html b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/suspended-context-messageport.https.html
new file mode 100644
index 00000000000..5f5b10a251f
--- /dev/null
+++ b/tests/wpt/web-platform-tests/webaudio/the-audio-api/the-audioworklet-interface/suspended-context-messageport.https.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<title>Test MessagePort while AudioContext is not running</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+const get_node_and_message = async (context) => {
+ const node = new AudioWorkletNode(context, 'port-processor');
+ return new Promise((resolve) => {
+ node.port.onmessage = (event) => resolve({node: node, event: event});
+ });
+};
+const ping_for_message = async (node) => {
+ return new Promise((resolve) => {
+ node.port.onmessage = resolve;
+ node.port.postMessage('ping');
+ });
+};
+const modulePath = 'processors/port-processor.js';
+
+promise_test(async () => {
+ const realtime = new AudioContext();
+ await realtime.audioWorklet.addModule(modulePath);
+ await realtime.suspend();
+ const currentTime = realtime.currentTime;
+ let {node, event} = await get_node_and_message(realtime);
+ assert_equals(event.data.timeStamp, currentTime, 'created message time');
+ event = await ping_for_message(node);
+ assert_equals(event.data.timeStamp, currentTime, 'pong time');
+}, 'realtime suspended');
+
+let offline;
+promise_test(async () => {
+ offline = new OfflineAudioContext({length: 128 + 1, sampleRate: 16384});
+ await offline.audioWorklet.addModule(modulePath);
+ assert_equals(offline.currentTime, 0, 'time before start');
+ let {node, event} = await get_node_and_message(offline);
+ assert_equals(event.data.timeStamp, 0, 'created time before start');
+ event = await ping_for_message(node);
+ assert_equals(event.data.timeStamp, 0, 'pong time before start');
+}, 'offline before start');
+
+promise_test(async () => {
+ await offline.startRendering();
+ const expected = 2 * 128 / offline.sampleRate;
+ assert_equals(offline.currentTime, expected, 'time on complete');
+ let {node, event} = await get_node_and_message(offline);
+ assert_equals(event.data.timeStamp, expected, "created time on complete");
+ event = await ping_for_message(node);
+ assert_equals(event.data.timeStamp, expected, "pong time on complete");
+}, 'offline on complete');
+</script>
diff --git a/tests/wpt/web-platform-tests/webauthn/createcredential-badargs-authnrselection.https.html b/tests/wpt/web-platform-tests/webauthn/createcredential-badargs-authnrselection.https.html
index 5da0745734f..9497a001f0f 100644
--- a/tests/wpt/web-platform-tests/webauthn/createcredential-badargs-authnrselection.https.html
+++ b/tests/wpt/web-platform-tests/webauthn/createcredential-badargs-authnrselection.https.html
@@ -46,8 +46,6 @@ standardSetup(function() {
authnrSelBadUvNull.userVerification = null;
// authenticatorSelection bad values
- new CreateCredentialsTest("options.publicKey.authenticatorSelection", []).runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection is empty array", TypeError);
- new CreateCredentialsTest("options.publicKey.authenticatorSelection", null).runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection is null", TypeError);
new CreateCredentialsTest("options.publicKey.authenticatorSelection", "").runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection is empty string", TypeError);
new CreateCredentialsTest("options.publicKey.authenticatorSelection", "none").runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection is string", TypeError);
@@ -65,10 +63,6 @@ standardSetup(function() {
new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelRkTrue)
.modify("options.publicKey.timeout", 300)
.runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection residentKey true", "NotAllowedError");
- new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelRkBadString)
- .modify("options.publicKey.timeout", 300)
- .runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection residentKey is string", TypeError);
- // TODO: not sure if rk is "boolean" or "truthy"; add test cases if it should only accept boolean values
// authenticatorSelection bad userVerification values
new CreateCredentialsTest("options.publicKey.authenticatorSelection", authnrSelBadUvEmptyStr).runTest("Bad AuthenticatorSelectionCriteria: authenticatorSelection userVerification empty string", TypeError);
diff --git a/tests/wpt/web-platform-tests/webauthn/createcredential-badargs-rp.https.html b/tests/wpt/web-platform-tests/webauthn/createcredential-badargs-rp.https.html
index cbd86b8f083..8886cc15c92 100644
--- a/tests/wpt/web-platform-tests/webauthn/createcredential-badargs-rp.https.html
+++ b/tests/wpt/web-platform-tests/webauthn/createcredential-badargs-rp.https.html
@@ -21,7 +21,6 @@ standardSetup(function() {
new CreateCredentialsTest("options.publicKey.rp", {}).runTest("Bad rp: rp is empty object", TypeError);
// // rp.id
- new CreateCredentialsTest("options.publicKey.rp.id", {}).runTest("Bad rp: id is object", TypeError);
new CreateCredentialsTest("options.publicKey.rp.id", null).runTest("Bad rp: id is null", "SecurityError");
new CreateCredentialsTest("options.publicKey.rp.id", "").runTest("Bad rp: id is empty String", "SecurityError");
new CreateCredentialsTest("options.publicKey.rp.id", "invalid domain.com").runTest("Bad rp: id is invalid domain (has space)", "SecurityError");
@@ -30,17 +29,10 @@ standardSetup(function() {
// // rp.name
new CreateCredentialsTest({path: "options.publicKey.rp.name", value: undefined}).runTest("rp missing name", TypeError);
- new CreateCredentialsTest("options.publicKey.rp.name", {}).runTest("Bad rp: name is object", TypeError);
- new CreateCredentialsTest("options.publicKey.rp.name", null).runTest("Bad rp: name is null", TypeError);
- new CreateCredentialsTest("options.publicKey.rp.name", "").runTest("Bad rp: name is empty String", TypeError);
- // // rp.icon
- new CreateCredentialsTest("options.publicKey.rp.icon", {}).runTest("Bad rp: icon is object", TypeError);
- new CreateCredentialsTest("options.publicKey.rp.icon", null).runTest("Bad rp: icon is null", TypeError);
- new CreateCredentialsTest("options.publicKey.rp.icon", "").runTest("Bad rp: icon is empty String", TypeError);
+ // rp.icon
new CreateCredentialsTest("options.publicKey.rp.icon", "http://fidoalliance.co.nz/testimages/catimage.png")
.runTest("Bad rp: icon is insecure", "SecurityError");
- // // TODO: unicode tests for icon URL (see also: USVString)
});
/* JSHINT */
diff --git a/tests/wpt/web-platform-tests/webauthn/createcredential-excludecredentials.https.html b/tests/wpt/web-platform-tests/webauthn/createcredential-excludecredentials.https.html
index 3a5af481fca..2b1eec19b7b 100644
--- a/tests/wpt/web-platform-tests/webauthn/createcredential-excludecredentials.https.html
+++ b/tests/wpt/web-platform-tests/webauthn/createcredential-excludecredentials.https.html
@@ -45,7 +45,7 @@ standardSetup(function() {
}
};
var p = createCredential(args);
- return promise_rejects_dom(t, "NotAllowedError", p, "expected to fail on excluded credenetial");
+ return promise_rejects_dom(t, "InvalidStateError", p, "expected to fail on excluded credential");
});
}, "exclude existing credential");
diff --git a/tests/wpt/web-platform-tests/webauthn/createcredential-extensions.https.html b/tests/wpt/web-platform-tests/webauthn/createcredential-extensions.https.html
index 036200dbbf9..46cab3051b4 100644
--- a/tests/wpt/web-platform-tests/webauthn/createcredential-extensions.https.html
+++ b/tests/wpt/web-platform-tests/webauthn/createcredential-extensions.https.html
@@ -21,15 +21,6 @@ standardSetup(function() {
// bad extension values
new CreateCredentialsTest("options.publicKey.extensions", "hi mom").runTest("Bad extensions: extensions is string", TypeError);
- new CreateCredentialsTest("options.publicKey.extensions", null).runTest("Bad extensions: extensions is null", TypeError);
- new CreateCredentialsTest("options.publicKey.extensions", []).runTest("Bad extensions: extensions is empty Array", TypeError);
- new CreateCredentialsTest("options.publicKey.extensions", new ArrayBuffer(0)).runTest("Bad extensions: extensions is empty ArrayBuffer", TypeError);
- var badJson = '{"foo": true, "bar: "yup"}'; // missing quote after "bar"
- new CreateCredentialsTest("options.publicKey.extensions", {foo: badJson}).runTest("Bad extensions: malformatted JSON", TypeError);
- new CreateCredentialsTest("options.publicKey.extensions", {foo: dummyExtension}).runTest("Bad extensions: JavaScript object", TypeError);
- var badExtId = {};
- badExtId[createRandomString(65)] = dummyExtension;
- new CreateCredentialsTest("options.publicKey.extensions", {badExtId: dummyExtension}).runTest("Bad extensions: extension ID too long", TypeError);
// phony extensions
// TODO: not sure if this should pass or fail
diff --git a/tests/wpt/web-platform-tests/webauthn/createcredential-pubkeycredparams.https.html b/tests/wpt/web-platform-tests/webauthn/createcredential-pubkeycredparams.https.html
index c845a906875..d1df7952d67 100644
--- a/tests/wpt/web-platform-tests/webauthn/createcredential-pubkeycredparams.https.html
+++ b/tests/wpt/web-platform-tests/webauthn/createcredential-pubkeycredparams.https.html
@@ -42,10 +42,10 @@ standardSetup(function() {
new CreateCredentialsTest("options.publicKey.pubKeyCredParams", [badTypeEmptyObj]).runTest("Bad pubKeyCredParams: first param has bad type (empty object)", TypeError);
new CreateCredentialsTest("options.publicKey.pubKeyCredParams", [badAlg])
.modify("options.publicKey.timeout", 300)
- .runTest("Bad pubKeyCredParams: first param has bad alg (42)", "NotSupportedError");
+ .runTest("Bad pubKeyCredParams: first param has bad alg (42)", "NotAllowedError");
new CreateCredentialsTest("options.publicKey.pubKeyCredParams", [badAlgZero])
.modify("options.publicKey.timeout", 300)
- .runTest("Bad pubKeyCredParams: first param has bad alg (0)", "NotSupportedError");
+ .runTest("Bad pubKeyCredParams: first param has bad alg (0)", "NotAllowedError");
// TODO: come back to this when mock authenticators support multiple cryptos so that we can test the preference ranking
// function verifyEC256(res) {