Merge inbound to mozilla-central. a=merge
authorCsoregi Natalia <ncsoregi@mozilla.com>
Sun, 11 Aug 2019 00:28:20 +0300
changeset 551095 c53f789ffabb03c04b1b20252aea9331301bfa02
parent 551022 462d2d4ba0516adc69de20372b16931cef20de9e (current diff)
parent 551094 e8362711bb3202097cdbb363681bb88931a85141 (diff)
child 551114 1f67a34dfe693ec3d903c66d1a99507d355de228
child 551128 5cd7526ffbc364d716e0ffc8c506793481f24526
push id2165
push userffxbld-merge
push dateMon, 14 Oct 2019 16:30:58 +0000
treeherdermozilla-release@0eae18af659f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone70.0a1
first release with
nightly linux32
c53f789ffabb / 70.0a1 / 20190810213107 / files
nightly linux64
c53f789ffabb / 70.0a1 / 20190810213107 / files
nightly mac
c53f789ffabb / 70.0a1 / 20190810213107 / files
nightly win32
c53f789ffabb / 70.0a1 / 20190810213107 / files
nightly win64
c53f789ffabb / 70.0a1 / 20190810213107 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
testing/web-platform/meta/cookies/http-state/comma-tests.html.ini
testing/web-platform/meta/css/css-fonts/parsing/font-size-computed.html.ini
testing/web-platform/meta/css/css-fonts/parsing/font-size-valid.html.ini
testing/web-platform/meta/css/css-layout-api/fallback-layout-invalid-fragment-request.https.html.ini
testing/web-platform/meta/css/css-lists/list-and-margin-collapse-003.html.ini
testing/web-platform/meta/geolocation-API/__dir__.ini
testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html.ini
testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.html.ini
testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.any.js.ini
testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.html.ini
testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.html.ini
testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html.ini
testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-iframe-messagechannel-success.html.ini
testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.html.ini
testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.html.ini
testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html.ini
testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html.ini
testing/web-platform/meta/webrtc/RTCPeerConnection-onicecandidateerror.html.ini
testing/web-platform/tests/css/css-layout-api/fallback-layout-invalid-fragment-request.https.html
testing/web-platform/tests/css/css-lists/list-and-margin-collapse-003.html
testing/web-platform/tests/css/css-lists/list-and-margin-collapse-004.html
testing/web-platform/tests/docs/appendix/github-intro.md
testing/web-platform/tests/docs/appendix/index.md
testing/web-platform/tests/docs/appendix/reverting.md
testing/web-platform/tests/docs/appendix/test-templates.md
testing/web-platform/tests/fonts/math/fraction-denominatordisplaystyleshiftdown6000-rulethickness1000.woff
testing/web-platform/tests/fonts/math/fraction-denominatorshiftdown3000-rulethickness1000.woff
testing/web-platform/tests/fonts/math/fraction-numeratordisplaystyleshiftup2000-rulethickness1000.woff
testing/web-platform/tests/fonts/math/fraction-numeratorshiftup11000-rulethickness1000.woff
testing/web-platform/tests/fonts/math/stack-axisheight7000.woff
testing/web-platform/tests/fonts/math/stack-bottomdisplaystyleshiftdown5000.woff
testing/web-platform/tests/fonts/math/stack-bottomshiftdown6000.woff
testing/web-platform/tests/fonts/math/stack-topdisplaystyleshiftup3000.woff
testing/web-platform/tests/fonts/math/stack-topshiftup9000.woff
testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html
testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.html
testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.any.js
testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.html
testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.html
testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html
testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-iframe-messagechannel-success.html
testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.html
testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.html
testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html
testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html
testing/web-platform/tests/webrtc/RTCPeerConnection-onicecandidateerror.html
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -6294,17 +6294,18 @@ exports.CSS_PROPERTIES = {
       "titling-caps",
       "ultra-condensed",
       "ultra-expanded",
       "unicase",
       "unset",
       "x-large",
       "x-small",
       "xx-large",
-      "xx-small"
+      "xx-small",
+      "xxx-large"
     ]
   },
   "font-family": {
     "isInherited": true,
     "subproperties": [
       "font-family"
     ],
     "supports": [],
@@ -6388,17 +6389,18 @@ exports.CSS_PROPERTIES = {
       "medium",
       "revert",
       "small",
       "smaller",
       "unset",
       "x-large",
       "x-small",
       "xx-large",
-      "xx-small"
+      "xx-small",
+      "xxx-large"
     ]
   },
   "font-size-adjust": {
     "isInherited": true,
     "subproperties": [
       "font-size-adjust"
     ],
     "supports": [],
--- a/docshell/test/navigation/mochitest.ini
+++ b/docshell/test/navigation/mochitest.ini
@@ -79,17 +79,19 @@ skip-if = fission && (debug || asan) # C
 [test_not-opener.html]
 fail-if = fission
 skip-if = fission && debug # Times out
 [test_opener.html]
 skip-if = fission && debug # Times out
 [test_popup-navigates-children.html]
 fail-if = fission
 [test_reserved.html]
-skip-if = (toolkit == 'android') || (debug && e10s) || (os == 'mac' && os_version == '10.14') || (fission && !debug) #Bug 1570953 #too slow on Android 4.3 aws only; bug 1030403; bug 1263213 for debug e10s, macosx1014 due to 1548821
+skip-if = 
+  (toolkit == 'android') || (debug && e10s) || (os == 'mac' && os_version == '10.14') || #too slow on Android 4.3 aws only; bug 1030403; bug 1263213 for debug e10s, macosx1014 due to 1548821
+  (fission && !debug) #Bug 1570953
 [test_performance_navigation.html]
 [test_sessionhistory.html]
 skip-if =
   toolkit == 'android' || # RANDOM on android
   (fission && debug) # Intermittent timeouts
 support-files = file_bug1379762-1.html
 [test_sibling-matching-parent.html]
 fail-if = fission
--- a/layout/style/test/property_database.js
+++ b/layout/style/test/property_database.js
@@ -5692,16 +5692,17 @@ var gCSSProperties = {
       "calc(1rem)",
       "calc(0.75rem + 200% - 125% + 0.25rem - 75%)",
     ],
     other_values: [
       "large",
       "2em",
       "50%",
       "xx-small",
+      "xxx-large",
       "36pt",
       "8px",
       "larger",
       "smaller",
       "0px",
       "0%",
       "calc(2em)",
       "calc(36pt + 75% + (30% + 2em + 2px))",
--- a/servo/components/style/values/generics/font.rs
+++ b/servo/components/style/values/generics/font.rs
@@ -250,17 +250,17 @@ pub enum KeywordSize {
     Small,
     Medium,
     Large,
     XLarge,
     #[css(keyword = "xx-large")]
     XXLarge,
     // This is not a real font keyword and will not parse
     // HTML font-size 7 corresponds to this value
-    #[css(skip)]
+    #[css(keyword = "xxx-large")]
     XXXLarge,
 }
 
 impl KeywordSize {
     /// Convert to an HTML <font size> value
     #[inline]
     pub fn html_size(self) -> u8 {
         self as u8
--- a/testing/web-platform/meta/FileAPI/url/url-in-tags.window.js.ini
+++ b/testing/web-platform/meta/FileAPI/url/url-in-tags.window.js.ini
@@ -1,4 +1,5 @@
 [url-in-tags.window.html]
+  max-asserts: 3
   [Blob URL fragment is implemented.]
     expected: FAIL
 
deleted file mode 100644
--- a/testing/web-platform/meta/cookies/http-state/comma-tests.html.ini
+++ /dev/null
@@ -1,7 +0,0 @@
-[comma-tests.html]
-  [comma0006 - comma0006]
-    expected: FAIL
-
-  [comma0007 - comma0007]
-    expected: FAIL
-
--- a/testing/web-platform/meta/cookies/http-state/general-tests.html.ini
+++ b/testing/web-platform/meta/cookies/http-state/general-tests.html.ini
@@ -1,12 +1,9 @@
 [general-tests.html]
-  [0002 - Set cookie with future expiration.]
-    expected: FAIL
-
   [0021 - Ignore cookie without key in all 'Set-Cookie'.]
     expected: FAIL
 
   [0023 - Ignore cookies without '=' in all 'Set-Cookie'.]
     expected: FAIL
 
   [0026 - Ignore malformed cookies in all 'Set-Cookie' v2.]
     expected: FAIL
@@ -14,8 +11,9 @@
   [0027 - Ignore malformed cookies in all 'Set-Cookie' v3.]
     expected: FAIL
 
   [0028 - [INVALID EXPECTATION\] Ignore malformed cookies in all 'Set-Cookie' v4.]
     expected: FAIL
 
   [0004 - Ignore cookie without key.]
     expected: FAIL
+
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-fonts/parsing/font-size-computed.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[font-size-computed.html]
-  [<font size="7"> is font-size: xxx-large]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-fonts/parsing/font-size-valid.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[font-size-valid.html]
-  [e.style['font-size'\] = "xxx-large" should set the property value]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-layout-api/fallback-layout-invalid-fragment-request.https.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[fallback-layout-invalid-fragment-request.https.html]
-  expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-layout-api/fallback-layout-no-promise.https.html.ini
@@ -0,0 +1,2 @@
+[fallback-layout-no-promise.https.html]
+  expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-layout-api/fallback-layout-unresolved-promise.https.html.ini
@@ -0,0 +1,2 @@
+[fallback-layout-unresolved-promise.https.html]
+  expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-layout-api/sync-layout-microtasks.https.html.ini
@@ -0,0 +1,4 @@
+[sync-layout-microtasks.https.html]
+  [sync-layout-microtasks]
+    expected: FAIL
+
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-lists/list-and-margin-collapse-003.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[list-and-margin-collapse-003.html]
-  [list and margin collapse]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-paint-api/background-repeat-x.https.html.ini
@@ -0,0 +1,2 @@
+[background-repeat-x.https.html]
+  expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/custom-elements/form-associated/ElementInternals-accessibility.html.ini
@@ -0,0 +1,4 @@
+[ElementInternals-accessibility.html]
+  [ElementInternals-accessibility]
+    expected: FAIL
+
--- a/testing/web-platform/meta/fetch/sec-metadata/redirect/redirect-http-upgrade.tentative.sub.html.ini
+++ b/testing/web-platform/meta/fetch/sec-metadata/redirect/redirect-http-upgrade.tentative.sub.html.ini
@@ -30,13 +30,15 @@
   [Http upgrade prefetch => No headers]
     disabled:
       if (os == "win") and debug and webrender: wpt-sync Bug 1565002
       if (os == "linux") and (processor == "x86_64") and not debug and webrender: wpt-sync Bug 1565002
       if (os == "linux") and (processor == "x86_64") and not debug and not webrender: wpt-sync Bug 1565002
       if (os == "linux") and (processor == "x86_64") and debug and webrender: wpt-sync Bug 1565002
       if (os == "linux") and (processor == "x86_64") and debug and not webrender and not sw-e10s: wpt-sync Bug 1565002
       if (os == "linux") and (processor == "x86_64") and debug and not webrender and sw-e10s: wpt-sync Bug 1565002
-    expected: FAIL
+    expected:
+      if os == "linux": [FAIL, TIMEOUT]
+      FAIL
 
   [Http upgrade fetch() api => No headers]
     expected: FAIL
 
--- a/testing/web-platform/meta/fetch/sec-metadata/redirect/redirect-https-downgrade.tentative.sub.html.ini
+++ b/testing/web-platform/meta/fetch/sec-metadata/redirect/redirect-https-downgrade.tentative.sub.html.ini
@@ -4,17 +4,22 @@
     expected: NOTRUN
 
   [Https downgrade font => No headers]
     expected: NOTRUN
 
   [Https downgrade prefetch => No headers]
     bug: [https://bugzilla.mozilla.org/show_bug.cgi?id=1568717, https://bugzilla.mozilla.org/show_bug.cgi?id=1569098]
     expected:
-      if os == "android": PASS
-      [FAIL, TIMEOUT, PASS]
+      if (os == "linux") and not sw-e10s and debug and not webrender: [PASS, TIMEOUT, FAIL]
+      if (os == "linux") and sw-e10s: [FAIL, PASS, TIMEOUT]
+      if (os == "linux") and not debug and not webrender and (processor == "x86_64"): [FAIL, PASS, TIMEOUT]
+      if (os == "linux") and debug and webrender: [FAIL, PASS]
+      if (os == "android") and debug: [PASS, FAIL]
+      if (os == "android") and not debug: PASS
+      FAIL
 
   [Https downgrade stylesheet => No headers]
     expected: TIMEOUT
 
   [Https downgrade image => No headers]
     expected: NOTRUN
 
deleted file mode 100644
--- a/testing/web-platform/meta/html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html.ini
+++ b/testing/web-platform/meta/html/cross-origin-opener/new_window_same_origin_unsafe_allow_outgoing.tentative.html.ini
@@ -1,16 +1,17 @@
 [new_window_same_origin_unsafe_allow_outgoing.tentative.html]
   [same-origin_unsafe-allow-outgoing document opening popup to http://not-web-platform.test:8000 with COOP: "same-origin"]
     expected:
       if os == "android": FAIL
 
   [same-origin_unsafe-allow-outgoing document opening popup to http://www1.web-platform.test:8000 with COOP: "same-origin unsafe-allow-outgoing"]
     expected:
       if os == "android": FAIL
+      if (os == "mac") and debug: PASS
 
   [same-origin_unsafe-allow-outgoing document opening popup to http://www1.web-platform.test:8000 with COOP: "same-site unsafe-allow-outgoing"]
     expected:
       if os == "android": FAIL
 
   [same-origin_unsafe-allow-outgoing document opening popup to http://www1.web-platform.test:8000 with COOP: "same-origin"]
     expected:
       if os == "android": FAIL
--- a/testing/web-platform/meta/html/cross-origin-opener/new_window_same_site.tentative.html.ini
+++ b/testing/web-platform/meta/html/cross-origin-opener/new_window_same_site.tentative.html.ini
@@ -33,16 +33,17 @@
 
   [same-site document opening popup to http://not-web-platform.test:8000 with COOP: ""]
     expected:
       if os == "android": FAIL
 
   [same-site document opening popup to http://not-web-platform.test:8000 with COOP: "same-site"]
     expected:
       if os == "android": FAIL
+      if (os == "mac") and debug: PASS
 
   [same-site document opening popup to http://www1.web-platform.test:8000 with COOP: "same-origin unsafe-allow-outgoing"]
     expected:
       if os == "android": FAIL
 
   [same-site document opening popup to http://web-platform.test:8000 with COOP: "same-origin unsafe-allow-outgoing"]
     expected:
       if os == "android": FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[broadcastchannel-success-and-failure.html]
-  [SharedArrayBuffer cannot cross agent clusters, BroadcastChannel edition]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.https.html.ini
@@ -0,0 +1,4 @@
+[broadcastchannel-success-and-failure.https.html]
+  [SharedArrayBuffer cannot cross agent clusters, BroadcastChannel edition]
+    expected: FAIL
+
deleted file mode 100644
--- a/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[identity-not-preserved.html]
-  [postMessaging to this window does not give back the same SharedArrayBuffer (but does use the same backing block)]
-    expected: FAIL
-
-  [postMessaging to a worker and back does not give back the same SharedArrayBuffer]
-    expected: FAIL
-
-  [postMessaging to an iframe and back does not give back the same SharedArrayBuffer]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.https.html.ini
@@ -0,0 +1,10 @@
+[identity-not-preserved.https.html]
+  [postMessaging to an iframe and back does not give back the same SharedArrayBuffer]
+    expected: FAIL
+
+  [postMessaging to this window does not give back the same SharedArrayBuffer (but does use the same backing block)]
+    expected: FAIL
+
+  [postMessaging to a worker and back does not give back the same SharedArrayBuffer]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-sharedworker-success.https.html.ini
@@ -0,0 +1,4 @@
+[nested-sharedworker-success.https.html]
+  [postMessaging to a dedicated sub-worker allows them to see each others' modifications]
+    expected: FAIL
+
deleted file mode 100644
--- a/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.any.js.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-[nested-worker-success.any.worker.html]
-  [postMessaging to a dedicated sub-worker allows them to see each others' modifications]
-    expected: FAIL
-
-
-[nested-worker-success.any.sharedworker.html]
-  [postMessaging to a dedicated sub-worker allows them to see each others' modifications]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.https.html.ini
@@ -0,0 +1,4 @@
+[nested-worker-success.https.html]
+  [postMessaging to a dedicated sub-worker allows them to see each others' modifications]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-coop-coep.https.any.js.ini
@@ -0,0 +1,18 @@
+[no-coop-coep.https.any.worker.html]
+  [SharedArrayBuffer over MessageChannel without COOP+COEP]
+    expected: FAIL
+
+  [SharedArrayBuffer over BroadcastChannel without COOP+COEP]
+    expected: FAIL
+
+
+[no-coop-coep.https.any.html]
+  [SharedArrayBuffer over MessageChannel without COOP+COEP]
+    expected: FAIL
+
+  [SharedArrayBuffer over postMessage() without COOP+COEP]
+    expected: FAIL
+
+  [SharedArrayBuffer over BroadcastChannel without COOP+COEP]
+    expected: FAIL
+
deleted file mode 100644
--- a/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.html.ini
+++ /dev/null
@@ -1,10 +0,0 @@
-[no-transferring.html]
-  [Trying to transfer a SharedArrayBuffer to this window throws]
-    expected: FAIL
-
-  [Trying to transfer a SharedArrayBuffer to a worker throws]
-    expected: FAIL
-
-  [Trying to transfer a SharedArrayBuffer through a MessagePort throws]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.https.html.ini
@@ -0,0 +1,10 @@
+[no-transferring.https.html]
+  [Trying to transfer a SharedArrayBuffer to a worker throws]
+    expected: FAIL
+
+  [Trying to transfer a SharedArrayBuffer through a MessagePort throws]
+    expected: FAIL
+
+  [Trying to transfer a SharedArrayBuffer to this window throws]
+    expected: FAIL
+
deleted file mode 100644
--- a/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.html.ini
+++ /dev/null
@@ -1,13 +0,0 @@
-[serialization-via-history.html]
-  [history.pushState(): simple case]
-    expected: FAIL
-
-  [history.pushState(): is interleaved correctly]
-    expected: FAIL
-
-  [history.replaceState(): simple case]
-    expected: FAIL
-
-  [history.replaceState(): is interleaved correctly]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.https.html.ini
@@ -0,0 +1,13 @@
+[serialization-via-history.https.html]
+  [history.pushState(): simple case]
+    expected: FAIL
+
+  [history.pushState(): is interleaved correctly]
+    expected: FAIL
+
+  [history.replaceState(): is interleaved correctly]
+    expected: FAIL
+
+  [history.replaceState(): simple case]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.https.sub.html.ini
@@ -0,0 +1,4 @@
+[window-domain-success.https.sub.html]
+  [postMessaging to a same-origin-domain (but not same-origin) iframe allows them to see each others' modifications]
+    expected: FAIL
+
deleted file mode 100644
--- a/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[window-domain-success.sub.html]
-  [postMessaging to a same-origin-domain (but not same-origin) iframe allows them to see each others' modifications]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-iframe-messagechannel-success.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[window-iframe-messagechannel-success.html]
-  [postMessaging to a same-origin iframe via MessageChannel allows them to see each others' modifications]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-iframe-messagechannel-success.https.html.ini
@@ -0,0 +1,4 @@
+[window-iframe-messagechannel-success.https.html]
+  [postMessaging to a same-origin iframe via MessageChannel allows them to see each others' modifications]
+    expected: FAIL
+
deleted file mode 100644
--- a/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[window-messagechannel-success.html]
-  [postMessaging to a dedicated worker via MessageChannel allows them to see each others' modifications]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.https.html.ini
@@ -0,0 +1,4 @@
+[window-messagechannel-success.https.html]
+  [postMessaging to a dedicated worker via MessageChannel allows them to see each others' modifications]
+    expected: FAIL
+
deleted file mode 100644
--- a/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[window-sharedworker-failure.html]
-  [SharedArrayBuffer cannot cross agent clusters, shared worker edition]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.https.html.ini
@@ -0,0 +1,4 @@
+[window-sharedworker-failure.https.html]
+  [SharedArrayBuffer cannot cross agent clusters, shared worker edition]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.https.sub.html.ini
@@ -0,0 +1,4 @@
+[window-similar-but-cross-origin-success.https.sub.html]
+  [postMessaging to a not same-origin-domain, but similar origin, iframe allows them to see each others' modifications]
+    expected: FAIL
+
deleted file mode 100644
--- a/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[window-similar-but-cross-origin-success.sub.html]
-  [postMessaging to a not same-origin-domain, but similar origin, iframe allows them to see each others' modifications]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html.ini
+++ /dev/null
@@ -1,40 +0,0 @@
-[window-simple-success.html]
-  [postMessaging to a dedicated worker allows them to see each others' modifications with DataView]
-    expected: FAIL
-
-  [postMessaging to a dedicated worker allows them to see each others' modifications with Int8Array]
-    expected: FAIL
-
-  [postMessaging to a dedicated worker allows them to see each others' modifications with Uint8Array]
-    expected: FAIL
-
-  [postMessaging to a dedicated worker allows them to see each others' modifications with Uint8ClampedArray]
-    expected: FAIL
-
-  [postMessaging to a dedicated worker allows them to see each others' modifications with Int16Array]
-    expected: FAIL
-
-  [postMessaging to a dedicated worker allows them to see each others' modifications with Uint16Array]
-    expected: FAIL
-
-  [postMessaging to a dedicated worker allows them to see each others' modifications with Int32Array]
-    expected: FAIL
-
-  [postMessaging to a dedicated worker allows them to see each others' modifications with Uint32Array]
-    expected: FAIL
-
-  [postMessaging to a dedicated worker allows them to see each others' modifications with Float32Array]
-    expected: FAIL
-
-  [postMessaging to a dedicated worker allows them to see each others' modifications with Float64Array]
-    expected: FAIL
-
-  [postMessaging to a same-origin iframe allows them to see each others' modifications]
-    expected: FAIL
-
-  [postMessaging to a same-origin deeply-nested iframe allows them to see each others' modifications]
-    expected: FAIL
-
-  [postMessaging to a same-origin opened window allows them to see each others' modifications]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.https.html.ini
@@ -0,0 +1,40 @@
+[window-simple-success.https.html]
+  [postMessaging to a dedicated worker allows them to see each others' modifications with Uint16Array]
+    expected: FAIL
+
+  [postMessaging to a dedicated worker allows them to see each others' modifications with Uint8ClampedArray]
+    expected: FAIL
+
+  [postMessaging to a dedicated worker allows them to see each others' modifications with Uint8Array]
+    expected: FAIL
+
+  [postMessaging to a dedicated worker allows them to see each others' modifications with Int16Array]
+    expected: FAIL
+
+  [postMessaging to a dedicated worker allows them to see each others' modifications with Int8Array]
+    expected: FAIL
+
+  [postMessaging to a dedicated worker allows them to see each others' modifications with DataView]
+    expected: FAIL
+
+  [postMessaging to a dedicated worker allows them to see each others' modifications with Int32Array]
+    expected: FAIL
+
+  [postMessaging to a dedicated worker allows them to see each others' modifications with Uint32Array]
+    expected: FAIL
+
+  [postMessaging to a dedicated worker allows them to see each others' modifications with Float64Array]
+    expected: FAIL
+
+  [postMessaging to a same-origin iframe allows them to see each others' modifications]
+    expected: FAIL
+
+  [postMessaging to a same-origin opened window allows them to see each others' modifications]
+    expected: FAIL
+
+  [postMessaging to a same-origin deeply-nested iframe allows them to see each others' modifications]
+    expected: FAIL
+
+  [postMessaging to a dedicated worker allows them to see each others' modifications with Float32Array]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mathml/presentation-markup/fractions/frac-parameters-2.html.ini
@@ -0,0 +1,13 @@
+[frac-parameters-2.html]
+  [TopDisplayStyleShiftUp]
+    expected: FAIL
+
+  [BottomDisplayStyleShiftDown]
+    expected: FAIL
+
+  [BottomShiftDown]
+    expected: FAIL
+
+  [ToShiftUp]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mathml/relations/css-styling/not-participating-to-parent-layout.html.ini
@@ -0,0 +1,121 @@
+[not-participating-to-parent-layout.html]
+  [menclose layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [mtable layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mover layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [merror layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [munder layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mo layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [menclose layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mi layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mroot layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [msqrt layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mtext layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [munderover layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [msub layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mn layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mphantom layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mmultiscripts layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mfrac layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [msqrt layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [mstyle layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mfrac layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [munderover layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [merror layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [mrow layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mpadded layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [munder layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [msub layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [mstyle layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [msubsup layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [mtable layout is not affected by children with "display: none" style]
+    expected: FAIL
+
+  [mroot layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [mmultiscripts layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [mtable layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [mphantom layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [msubsup layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [ms layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mrow layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
+  [mpadded layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [msup layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [mover layout is not affected by children with "position: absolute" style]
+    expected: FAIL
+
+  [msup layout is not affected by children with "position: fixed" style]
+    expected: FAIL
+
--- a/testing/web-platform/meta/mathml/relations/css-styling/writing-mode/writing-mode-001.tentative.html.ini
+++ b/testing/web-platform/meta/mathml/relations/css-styling/writing-mode/writing-mode-001.tentative.html.ini
@@ -1,19 +1,13 @@
 [writing-mode-001.tentative.html]
   [Inheritance of CSS writing-mode and direction (id='vertical-lr_rtl')]
     expected: FAIL
 
   [Inheritance of CSS writing-mode and direction (id='vertical-rl_ltr')]
     expected: FAIL
 
-  [Layout of mrow (id='vertical-lr_ltr')]
-    expected: FAIL
-
   [Inheritance of CSS writing-mode and direction (id='vertical-lr_ltr')]
     expected: FAIL
 
   [Inheritance of CSS writing-mode and direction (id='vertical-rl_rtl')]
     expected: FAIL
 
-  [Layout of mrow (id='vertical-rl_ltr')]
-    expected: FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mathml/relations/html5-tree/clipboard-event-handlers.tentative.html.ini
@@ -0,0 +1,10 @@
+[clipboard-event-handlers.tentative.html]
+  [oncut: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [oncopy: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onpaste: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mathml/relations/html5-tree/css-inline-style-interface.tentative.html.ini
@@ -0,0 +1,97 @@
+[css-inline-style-interface.tentative.html]
+  [The mtext's style property should be present and be functional.]
+    expected: FAIL
+
+  [The msubsup's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mo's style property should be present and be functional.]
+    expected: FAIL
+
+  [The semantics's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mrow's style property should be present and be functional.]
+    expected: FAIL
+
+  [The <math> element style property should be present and be functional.]
+    expected: FAIL
+
+  [The mn's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mstyle's style property should be present and be functional.]
+    expected: FAIL
+
+  [The munderover's style property should be present and be functional.]
+    expected: FAIL
+
+  [The menclose's style property should be present and be functional.]
+    expected: FAIL
+
+  [The merror's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mprescripts's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mover's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mtd's style property should be present and be functional.]
+    expected: FAIL
+
+  [The msqrt's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mtr's style property should be present and be functional.]
+    expected: FAIL
+
+  [The annotation's style property should be present and be functional.]
+    expected: FAIL
+
+  [The none's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mmultiscripts's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mroot's style property should be present and be functional.]
+    expected: FAIL
+
+  [The msub's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mpadded's style property should be present and be functional.]
+    expected: FAIL
+
+  [The munder's style property should be present and be functional.]
+    expected: FAIL
+
+  [The annotation-xml's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mphantom's style property should be present and be functional.]
+    expected: FAIL
+
+  [The maction's style property should be present and be functional.]
+    expected: FAIL
+
+  [The ms's style property should be present and be functional.]
+    expected: FAIL
+
+  [The msup's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mi's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mspace's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mfrac's style property should be present and be functional.]
+    expected: FAIL
+
+  [The mtable's style property should be present and be functional.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mathml/relations/html5-tree/html-or-foreign-element-interfaces.tentative.html.ini
@@ -0,0 +1,16 @@
+[html-or-foreign-element-interfaces.tentative.html]
+  [The dataset property should be present and be functional.]
+    expected: FAIL
+
+  [MathML elements should work with blur predictably]
+    expected: FAIL
+
+  [MathML elements should have a .dataset]
+    expected: FAIL
+
+  [MathML elements should work with focus predictably]
+    expected: FAIL
+
+  [MathML elements should have a tabIndex property]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mathml/relations/html5-tree/math-global-event-handlers.tentative.html.ini
@@ -0,0 +1,559 @@
+[math-global-event-handlers.tentative.html]
+  [onkeyup: the default value must be null]
+    expected: FAIL
+
+  [oncuechange: the default value must be null]
+    expected: FAIL
+
+  [oncuechange: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onloadedmetadata: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onscroll: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onwaiting: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ondblclick: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ontoggle: the default value must be null]
+    expected: FAIL
+
+  [onplaying: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onmouseenter: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [oncancel: the default value must be null]
+    expected: FAIL
+
+  [onloadedmetadata: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onwheel: the default value must be null]
+    expected: FAIL
+
+  [onseeked: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [oncanplaythrough: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondragstart: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [oncancel: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onseeked: the default value must be null]
+    expected: FAIL
+
+  [onplaying: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onloadstart: the default value must be null]
+    expected: FAIL
+
+  [onstalled: the default value must be null]
+    expected: FAIL
+
+  [onratechange: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onsubmit: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onloadstart: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onkeyup: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onmousemove: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ontimeupdate: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [oninvalid: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onmouseleave: the default value must be null]
+    expected: FAIL
+
+  [onloadend: the default value must be null]
+    expected: FAIL
+
+  [onmousemove: the default value must be null]
+    expected: FAIL
+
+  [onfocus: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondrag: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ontimeupdate: the default value must be null]
+    expected: FAIL
+
+  [onmouseleave: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondurationchange: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [oninvalid: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onwaiting: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondragstart: the default value must be null]
+    expected: FAIL
+
+  [onplay: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onfocus: the default value must be null]
+    expected: FAIL
+
+  [ondrag: the default value must be null]
+    expected: FAIL
+
+  [onsuspend: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onpause: the default value must be null]
+    expected: FAIL
+
+  [onresize: the default value must be null]
+    expected: FAIL
+
+  [onclick: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onmouseout: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onauxclick: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onmouseout: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onvolumechange: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [oncanplay: the default value must be null]
+    expected: FAIL
+
+  [onmouseout: the default value must be null]
+    expected: FAIL
+
+  [onsubmit: the default value must be null]
+    expected: FAIL
+
+  [ondragover: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onstalled: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onmousedown: the default value must be null]
+    expected: FAIL
+
+  [onmousedown: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onmouseup: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onprogress: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onclick: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onended: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [oncontextmenu: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [oncontextmenu: the default value must be null]
+    expected: FAIL
+
+  [onclick: the default value must be null]
+    expected: FAIL
+
+  [ondragenter: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [oninput: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ondragenter: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onloadeddata: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onkeypress: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onprogress: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onpause: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondurationchange: the default value must be null]
+    expected: FAIL
+
+  [onloadeddata: the default value must be null]
+    expected: FAIL
+
+  [onmouseenter: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onkeypress: the default value must be null]
+    expected: FAIL
+
+  [onabort: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onkeydown: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onmousemove: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onloadend: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onpause: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onmouseover: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onkeydown: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onseeking: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ondragleave: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondragleave: the default value must be null]
+    expected: FAIL
+
+  [onselect: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onload: the default value must be null]
+    expected: FAIL
+
+  [onloadstart: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondurationchange: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [oncanplaythrough: the default value must be null]
+    expected: FAIL
+
+  [onmousedown: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ondragover: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ondragleave: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onseeked: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondragover: the default value must be null]
+    expected: FAIL
+
+  [onkeyup: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [oninput: the default value must be null]
+    expected: FAIL
+
+  [onvolumechange: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ondragend: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onreset: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onauxclick: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ondrop: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onplay: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onseeking: the default value must be null]
+    expected: FAIL
+
+  [onvolumechange: the default value must be null]
+    expected: FAIL
+
+  [onauxclick: the default value must be null]
+    expected: FAIL
+
+  [onresize: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondragexit: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onmouseover: the default value must be null]
+    expected: FAIL
+
+  [onwheel: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [oninput: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onscroll: the default value must be null]
+    expected: FAIL
+
+  [onclose: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onkeydown: the default value must be null]
+    expected: FAIL
+
+  [onmouseup: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onblur: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onloadedmetadata: the default value must be null]
+    expected: FAIL
+
+  [onmouseup: the default value must be null]
+    expected: FAIL
+
+  [onclose: the default value must be null]
+    expected: FAIL
+
+  [ondragstart: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onblur: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ontoggle: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondragend: the default value must be null]
+    expected: FAIL
+
+  [onemptied: the default value must be null]
+    expected: FAIL
+
+  [oninvalid: the default value must be null]
+    expected: FAIL
+
+  [onclose: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onended: the default value must be null]
+    expected: FAIL
+
+  [onselect: the default value must be null]
+    expected: FAIL
+
+  [onemptied: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onchange: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onloadeddata: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [oncancel: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondrop: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onsuspend: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onload: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onstalled: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onseeking: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onmouseenter: the default value must be null]
+    expected: FAIL
+
+  [onreset: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onemptied: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onended: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onkeypress: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onabort: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ondrag: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onfocus: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onloadend: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onratechange: the default value must be null]
+    expected: FAIL
+
+  [onprogress: the default value must be null]
+    expected: FAIL
+
+  [ontoggle: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ondragenter: the default value must be null]
+    expected: FAIL
+
+  [oncanplay: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onwaiting: the default value must be null]
+    expected: FAIL
+
+  [oncanplaythrough: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [oncuechange: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onsecuritypolicyviolation: the default value must be null]
+    expected: FAIL
+
+  [onsecuritypolicyviolation: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onmouseleave: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onwheel: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onchange: the default value must be null]
+    expected: FAIL
+
+  [onsuspend: the default value must be null]
+    expected: FAIL
+
+  [onreset: the default value must be null]
+    expected: FAIL
+
+  [onsecuritypolicyviolation: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onselect: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onmouseover: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondrop: the default value must be null]
+    expected: FAIL
+
+  [ondragexit: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [oncanplay: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onformdata: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onload: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onresize: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onscroll: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onblur: the default value must be null]
+    expected: FAIL
+
+  [onchange: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onratechange: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [onsubmit: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondblclick: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ontimeupdate: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onformdata: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [onabort: the default value must be null]
+    expected: FAIL
+
+  [onplay: the default value must be null]
+    expected: FAIL
+
+  [onplaying: the default value must be null]
+    expected: FAIL
+
+  [ondragend: the content attribute must be compiled into a function as the corresponding property]
+    expected: FAIL
+
+  [ondragexit: the default value must be null]
+    expected: FAIL
+
+  [oncontextmenu: must be on the appropriate locations for GlobalEventHandlers]
+    expected: FAIL
+
+  [ondblclick: the default value must be null]
+    expected: FAIL
+
+  [onformdata: the default value must be null]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/mediasession/positionstate.html.ini
@@ -0,0 +1,22 @@
+[positionstate.html]
+  [Test setPositionState with a null value]
+    expected: FAIL
+
+  [Test setPositionState with a valid value for reverse playback]
+    expected: FAIL
+
+  [Test setPositionState with a valid value for forward playback]
+    expected: FAIL
+
+  [Test setPositionState with optional position]
+    expected: FAIL
+
+  [Test setPositionState with optional playback rate]
+    expected: FAIL
+
+  [Test setPositionState with zero duration]
+    expected: FAIL
+
+  [Test setPositionState with only duration]
+    expected: FAIL
+
--- a/testing/web-platform/meta/mozilla-sync
+++ b/testing/web-platform/meta/mozilla-sync
@@ -1,2 +1,2 @@
-local: 9bab8526091e9973c2ca8ea79473c0eb9c7b10fd
-upstream: ee257bdb4ecd061513b43dfb9582f700a32b93cd
+local: 595a3618185726dbeb45e6862ad8082434a7a73d
+upstream: 5c61f2493fe744dc9f3d08e1f5a80165f574cfa3
--- a/testing/web-platform/meta/pointerevents/pointerlock/pointerevent_movementxy_with_pointerlock.html.ini
+++ b/testing/web-platform/meta/pointerevents/pointerlock/pointerevent_movementxy_with_pointerlock.html.ini
@@ -1,5 +1,5 @@
 [pointerevent_movementxy_with_pointerlock.html]
   [mouse pointerevent movementX/Y with pointerlock test]
     expected:
       if (os == "android") and not e10s: FAIL
-      [PASS, FAIL]
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/resize-observer/observe.html.ini
@@ -0,0 +1,11 @@
+[observe.html]
+  expected:
+    if webrender and debug and (os == "linux"): TIMEOUT
+  [guard]
+    expected:
+      if webrender and debug and (os == "linux"): NOTRUN
+
+  [test6: iframe notifications]
+    expected:
+      if webrender and debug and (os == "linux"): FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/animations/discard-on-discard.html.ini
@@ -0,0 +1,4 @@
+[discard-on-discard.html]
+  [Test the behavior of one discard applied on another discard]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/animations/repeatn-remove-add-animation.html.ini
@@ -0,0 +1,4 @@
+[repeatn-remove-add-animation.html]
+  [This removes and adds an animation element while the animation is repeating]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/animations/svgboolean-animation-1.html.ini
@@ -0,0 +1,4 @@
+[svgboolean-animation-1.html]
+  [Test 'to' animation of SVGBoolean.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/animations/svglength-additive-by-7.html.ini
@@ -0,0 +1,4 @@
+[svglength-additive-by-7.html]
+  [This tests by-animations adding to previous underlying values]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/animations/svglength-additive-by-8.html.ini
@@ -0,0 +1,4 @@
+[svglength-additive-by-8.html]
+  [This tests by-animations adding to previous underlying values]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/animations/svglength-animation-invalid-value-1.html.ini
@@ -0,0 +1,4 @@
+[svglength-animation-invalid-value-1.html]
+  [Test SVGLength animation with invalid value: No spaces between number and unit.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/animations/svglength-animation-invalid-value-2.html.ini
@@ -0,0 +1,4 @@
+[svglength-animation-invalid-value-2.html]
+  [Test SVGLength animation with invalid value: No spaces before value.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/animations/svglength-animation-invalid-value-3.html.ini
@@ -0,0 +1,4 @@
+[svglength-animation-invalid-value-3.html]
+  [Test SVGLength animation with invalid value: No spaces after number and unit.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/animations/svglength-animation-px-to-ems.html.ini
@@ -0,0 +1,4 @@
+[svglength-animation-px-to-ems.html]
+  [Test SVGLength animation from px to ems.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/animations/svglength-animation-unitType.html.ini
@@ -0,0 +1,4 @@
+[svglength-animation-unitType.html]
+  [Test change of unit type for SVGLength animation.]
+    expected: FAIL
+
--- a/testing/web-platform/meta/svg/types/scripted/SVGGeometryElement.isPointInStroke-01.svg.ini
+++ b/testing/web-platform/meta/svg/types/scripted/SVGGeometryElement.isPointInStroke-01.svg.ini
@@ -2,9 +2,10 @@
   disabled:
     if (os == "android") and not debug: https://bugzilla.mozilla.org/show_bug.cgi?id=1560275
   [SVGGeometryElement.prototype.isPointInStroke, non-finite argument.]
     expected: FAIL
 
   [SVGGeometryElement.prototype.isPointInStroke, 'vector-effect'.]
     expected:
       if (os == "android") and not debug: FAIL
+      if os == "android": PASS
 
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/upgrade-insecure-requests/shared-worker-redirect-upgrade.https.html.ini
@@ -0,0 +1,10 @@
+[shared-worker-redirect-upgrade.https.html]
+  [secure/same-origin => insecure/same-origin shared-worker]
+    expected: FAIL
+
+  [insecure/same-origin => insecure/same-origin shared-worker]
+    expected: FAIL
+
+  [insecure/same-origin => secure/same-origin shared-worker]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/upgrade-insecure-requests/shared-worker-upgrade.https.html.ini
@@ -0,0 +1,4 @@
+[shared-worker-upgrade.https.html]
+  [insecure/same-origin shared-worker]
+    expected: FAIL
+
--- a/testing/web-platform/meta/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-copy-channel.html.ini
+++ b/testing/web-platform/meta/webaudio/the-audio-api/the-audiobuffer-interface/audiobuffer-copy-channel.html.ini
@@ -1,9 +1,10 @@
 [audiobuffer-copy-channel.html]
+  expected: ERROR
   [X 4: buffer.copyToChannel(x, 0, -1) incorrectly threw IndexSizeError: "Index or size is negative or greater than the allowed amount".]
     expected: FAIL
 
   [# AUDIT TASK RUNNER FINISHED: 2 out of 5 tasks were failed.]
     expected: FAIL
 
   [X 5: buffer.copyFromChannel(x, 0, -1) incorrectly threw IndexSizeError: "Index or size is negative or greater than the allowed amount".]
     expected: FAIL
--- a/testing/web-platform/meta/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html.ini
+++ b/testing/web-platform/meta/webaudio/the-audio-api/the-audioworklet-interface/audioworklet-postmessage-sharedarraybuffer.https.html.ini
@@ -1,4 +1,6 @@
 [audioworklet-postmessage-sharedarraybuffer.https.html]
+  expected: ERROR
   [\n      Test passing SharedArrayBuffer to an AudioWorklet\n    ]
     expected:
-        if release_or_beta: FAIL
+      if release_or_beta: FAIL
+
--- a/testing/web-platform/meta/webdriver/tests/new_session/timeouts.py.ini
+++ b/testing/web-platform/meta/webdriver/tests/new_session/timeouts.py.ini
@@ -1,3 +1,3 @@
 [timeouts.py]
-    disabled:
-      if ccov and (os == "win") and (bits == 64) and (version == "10.0.17134"): https://bugzilla.mozilla.org/show_bug.cgi?id=1495002
+  disabled:
+    if ccov and (os == "win") and (bits == 64) and (version == "10.0.17134"): https://bugzilla.mozilla.org/show_bug.cgi?id=1495002
deleted file mode 100644
--- a/testing/web-platform/meta/webrtc/RTCPeerConnection-onicecandidateerror.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[RTCPeerConnection-onicecandidateerror.html]
-  disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1561441
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/webrtc/RTCPeerConnection-onicecandidateerror.https.html.ini
@@ -0,0 +1,5 @@
+[RTCPeerConnection-onicecandidateerror.https.html]
+  expected: TIMEOUT
+  [Surfacing onicecandidateerror]
+    expected: TIMEOUT
+
--- a/testing/web-platform/meta/workers/SharedWorker-exception-propagation.html.ini
+++ b/testing/web-platform/meta/workers/SharedWorker-exception-propagation.html.ini
@@ -1,5 +1,6 @@
 [SharedWorker-exception-propagation.html]
   [Uncaught error in shared worker should not propagate to window]
     expected:
       if (os == "android") and e10s: [PASS, FAIL]
       FAIL
+
--- a/testing/web-platform/tests/README.md
+++ b/testing/web-platform/tests/README.md
@@ -84,16 +84,21 @@ port definitions of your choice e.g.:
 }
 ```
 
 After your `hosts` file is configured, the servers will be locally accessible at:
 
 http://web-platform.test:8000/<br>
 https://web-platform.test:8443/ *
 
+To use the web-based runner point your browser to:
+
+http://web-platform.test:8000/tools/runner/index.html <br>
+https://web-platform.test:8443/tools/runner/index.html *
+
 \**See [Trusting Root CA](#trusting-root-ca)*
 
 Running Tests Automatically
 ---------------------------
 
 Tests can be run automatically in a browser using the `run` command of
 the `wpt` script in the root of the checkout. This requires the hosts
 file setup documented above, but you must *not* have the
@@ -170,86 +175,16 @@ Alternatively, you may also use
 [Bash on Ubuntu on Windows](https://msdn.microsoft.com/en-us/commandline/wsl/about)
 in the Windows 10 Anniversary Update build, then access your windows
 partition from there to launch `wpt` commands.
 
 Please make sure git and your text editor do not automatically convert
 line endings, as it will cause lint errors. For git, please set
 `git config core.autocrlf false` in your working tree.
 
-Certificates
-============
-
-By default pre-generated certificates for the web-platform.test domain
-are provided in [`tools/certs`](tools/certs). If you wish to generate new
-certificates for any reason it's possible to use OpenSSL when starting
-the server, or starting a test run, by providing the
-`--ssl-type=openssl` argument to the `wpt serve` or `wpt run`
-commands.
-
-If you installed OpenSSL in such a way that running `openssl` at a
-command line doesn't work, you also need to adjust the path to the
-OpenSSL binary. This can be done by adding a section to `config.json`
-like:
-
-```
-"ssl": {"openssl": {"binary": "/path/to/openssl"}}
-```
-
-On Windows using OpenSSL typically requires installing an OpenSSL distribution.
-[Shining Light](https://slproweb.com/products/Win32OpenSSL.html)
-provide a convenient installer that is known to work, but requires a
-little extra setup, i.e.:
-
-Run the installer for Win32_OpenSSL_v1.1.0b (30MB). During installation,
-change the default location for where to Copy OpenSSL Dlls from the
-System directory to the /bin directory.
-
-After installation, ensure that the path to OpenSSL (typically,
-this will be `C:\OpenSSL-Win32\bin`) is in your `%Path%`
-[Environment Variable](http://www.computerhope.com/issues/ch000549.htm).
-If you forget to do this part, you will most likely see a 'File Not Found'
-error when you start wptserve.
-
-Finally, set the path value in the server configuration file to the
-default OpenSSL configuration file location. To do this create a file
-called `config.json`.  Then add the OpenSSL configuration below,
-ensuring that the key `ssl/openssl/base_conf_path` has a value that is
-the path to the OpenSSL config file (typically this will be
-`C:\\OpenSSL-Win32\\bin\\openssl.cfg`):
-
-```
-{
-  "ssl": {
-    "type": "openssl",
-    "encrypt_after_connect": false,
-    "openssl": {
-      "openssl_binary": "openssl",
-      "base_path: "_certs",
-      "force_regenerate": false,
-      "base_conf_path": "C:\\OpenSSL-Win32\\bin\\openssl.cfg"
-    },
-  },
-}
-```
-
-### Trusting Root CA
-
-To prevent browser SSL warnings when running HTTPS tests locally, the
-web-platform-tests Root CA file `cacert.pem` in [tools/certs](tools/certs)
-must be added as a trusted certificate in your OS/browser.
-
-**NOTE**: The CA should not be installed in any browser profile used
-outside of tests, since it may be used to generate fake
-certificates. For browsers that use the OS certificate store, tests
-should therefore not be run manually outside a dedicated OS instance
-(e.g. a VM). To avoid this problem when running tests in Chrome or
-Firefox use `wpt run`, which disables certificate checks and therefore
-doesn't require the root CA to be trusted.
-
 Publication
 ===========
 
 The master branch is automatically synced to http://w3c-test.org/.
 
 Pull requests are
 [automatically mirrored](http://w3c-test.org/submissions/) except those
 that modify sensitive resources (such as `.py`). The latter require
@@ -329,46 +264,16 @@ In the unusual case of error reports for
 certain test or that for other exceptional reasons shouldn't prevent
 a merge of a test, update and commit the `lint.whitelist` file in the
 web-platform-tests root directory to suppress the error reports.
 
 For more details, see the [lint-tool documentation][lint-tool].
 
 [lint-tool]: https://web-platform-tests.org/writing-tests/lint-tool.html
 
-Adding command-line scripts ("tools" subdirs)
----------------------------------------------
-
-Sometimes you may want to add a script to the repository that's meant
-to be used from the command line, not from a browser (e.g., a script
-for generating test files). If you want to ensure (e.g., for security
-reasons) that such scripts won't be handled by the HTTP server, but
-will instead only be usable from the command line, then place them in
-either:
-
-* the `tools` subdir at the root of the repository, or
-
-* the `tools` subdir at the root of any top-level directory in the
-  repository which contains the tests the script is meant to be used
-  with
-
-Any files in those `tools` directories won't be handled by the HTTP
-server; instead the server will return a 404 if a user navigates to
-the URL for a file within them.
-
-If you want to add a script for use with a particular set of tests but
-there isn't yet any `tools` subdir at the root of a top-level
-directory in the repository containing those tests, you can create a
-`tools` subdir at the root of that top-level directory and place your
-scripts there.
-
-For example, if you wanted to add a script for use with tests in the
-`notifications` directory, create the `notifications/tools` subdir and
-put your script there.
-
 Test Review
 ===========
 
 We can sometimes take a little while to go through pull requests
 because we have to go through all the tests and ensure that they match
 the specification correctly. But we look at all of them, and take
 everything that we can.
 
--- a/testing/web-platform/tests/common/security-features/resources/common.js
+++ b/testing/web-platform/tests/common/security-features/resources/common.js
@@ -1099,17 +1099,17 @@ self.invokeRequest = invokeRequest;
     Otherwise, the script is loaded from same-origin.
   @param {object} workerOptions
     The `options` argument for Worker constructor.
 
   Other parameters and return values are the same as those of invokeRequest().
 */
 function invokeFromWorker(isDataUrl, workerOptions,
                           subresource, sourceContextList) {
-  const currentSourceContext = sourceContextList.shift();
+  const currentSourceContext = sourceContextList[0];
   let workerUrl =
     "/common/security-features/scope/worker.py?policyDeliveries=" +
     encodeURIComponent(JSON.stringify(
         currentSourceContext.policyDeliveries || []));
   if (workerOptions.type === 'module') {
     workerUrl += "&type=module";
   }
 
@@ -1123,28 +1123,28 @@ function invokeFromWorker(isDataUrl, wor
   } else {
     promise = Promise.resolve(workerUrl);
   }
 
   return promise
     .then(url => {
       const worker = new Worker(url, workerOptions);
       worker.postMessage({subresource: subresource,
-                          sourceContextList: sourceContextList});
+                          sourceContextList: sourceContextList.slice(1)});
       return bindEvents2(worker, "message", worker, "error", window, "error");
     })
     .then(event => {
         if (event.data.error)
           return Promise.reject(event.data.error);
         return event.data;
       });
 }
 
 function invokeFromIframe(subresource, sourceContextList) {
-  const currentSourceContext = sourceContextList.shift();
+  const currentSourceContext = sourceContextList[0];
   const frameUrl =
     "/common/security-features/scope/document.py?policyDeliveries=" +
     encodeURIComponent(JSON.stringify(
         currentSourceContext.policyDeliveries || []));
 
   let promise;
   if (currentSourceContext.sourceContextType === 'srcdoc') {
     promise = fetch(frameUrl)
@@ -1160,17 +1160,17 @@ function invokeFromIframe(subresource, s
   return promise
     .then(iframe => {
         return iframe.eventPromise
           .then(() => {
               const promise = bindEvents2(
                   window, "message", iframe, "error", window, "error");
               iframe.contentWindow.postMessage(
                   {subresource: subresource,
-                   sourceContextList: sourceContextList},
+                   sourceContextList: sourceContextList.slice(1)},
                   "*");
               return promise;
             })
           .then(event => {
               if (event.data.error)
                 return Promise.reject(event.data.error);
               return event.data;
             });
--- a/testing/web-platform/tests/cookie-store/serviceworker_cookieStore_subscriptions.js
+++ b/testing/web-platform/tests/cookie-store/serviceworker_cookieStore_subscriptions.js
@@ -6,17 +6,17 @@ importScripts("/resources/testharness.js
 
 self.addEventListener('install', (event) => {
   event.waitUntil((async () => {
     // The subscribeToChanges calls are not done in parallel on purpose. Having
     // multiple in-flight requests introduces failure modes aside from the
     // cookie change logic that this test aims to cover.
     try {
       await cookieStore.subscribeToChanges([
-        { name: 'cookie-name1', matchType: 'equals', url: '/scope/path1' }]);
+        { name: 'cookie-name1', matchType: 'equals', url: '/cookie-store/path1' }]);
       await cookieStore.subscribeToChanges([
         { },  // Test the default values for subscription properties.
         { name: 'cookie-prefix', matchType: 'starts-with' },
       ]);
 
       // If the worker enters the "redundant" state, the UA may terminate it
       // before all tests have been reported to the client. Stifle errors in
       // order to avoid this and ensure all tests are consistently reported.
--- a/testing/web-platform/tests/cookie-store/serviceworker_cookieStore_subscriptions.tentative.https.html
+++ b/testing/web-platform/tests/cookie-store/serviceworker_cookieStore_subscriptions.tentative.https.html
@@ -4,19 +4,20 @@
 <link rel="help" href="https://github.com/WICG/cookie-store">
 <link rel="author" href="pwnall@chromium.org" title="Victor Costan">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
 'use strict';
 
 (async () => {
-  const scope = 'scope';
+  // Not using an explicit scope here in order for script URL to be in scope,
+  // to cover implicit subscription URL construction.
 
-  let registration = await navigator.serviceWorker.getRegistration(scope);
+  let registration = await navigator.serviceWorker.getRegistration();
   if (registration)
     await registration.unregister();
   registration = await navigator.serviceWorker.register(
-      'serviceworker_cookieStore_subscriptions.js', {scope});
+      'serviceworker_cookieStore_subscriptions.js');
 
   fetch_tests_from_worker(registration.installing);
 })();
 </script>
--- a/testing/web-platform/tests/cookie-store/serviceworker_cookieStore_subscriptions_basic.js
+++ b/testing/web-platform/tests/cookie-store/serviceworker_cookieStore_subscriptions_basic.js
@@ -3,17 +3,18 @@ self.GLOBAL = {
   isWorker: function() { return true; },
 };
 importScripts("/resources/testharness.js");
 
 self.addEventListener('install', (event) => {
   event.waitUntil((async () => {
     try {
       await cookieStore.subscribeToChanges([
-        { name: 'cookie-name', matchType: 'equals', url: '/scope/path' }]);
+        { name: 'cookie-name', matchType: 'equals',
+          url: '/cookie-store/scope/path' }]);
 
       // If the worker enters the "redundant" state, the UA may terminate it
       // before all tests have been reported to the client. Stifle errors in
       // order to avoid this and ensure all tests are consistently reported.
     } catch (err) {}
   })());
 });
 
--- a/testing/web-platform/tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.js
+++ b/testing/web-platform/tests/cookie-store/serviceworker_cookieStore_subscriptions_eventhandler_attribute.js
@@ -3,17 +3,18 @@ self.GLOBAL = {
   isWorker: function() { return true; },
 };
 importScripts("/resources/testharness.js");
 
 self.addEventListener('install', (event) => {
   event.waitUntil((async () => {
     try {
       await cookieStore.subscribeToChanges([
-        { name: 'cookie-name', matchType: 'equals', url: '/scope/path' }]);
+        { name: 'cookie-name', matchType: 'equals',
+          url: '/cookie-store/scope/path' }]);
 
       // If the worker enters the "redundant" state, the UA may terminate it
       // before all tests have been reported to the client. Stifle errors in
       // order to avoid this and ensure all tests are consistently reported.
     } catch (err) {}
   })());
 });
 
--- a/testing/web-platform/tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.js
+++ b/testing/web-platform/tests/cookie-store/serviceworker_cookieStore_subscriptions_mismatch.js
@@ -3,17 +3,18 @@ self.GLOBAL = {
   isWorker: function() { return true; },
 };
 importScripts("/resources/testharness.js");
 
 self.addEventListener('install', (event) => {
   event.waitUntil((async () => {
     try {
       await cookieStore.subscribeToChanges([
-        { name: 'cookie-name', matchType: 'equals', url: '/scope/path' }]);
+        { name: 'cookie-name', matchType: 'equals',
+          url: '/cookie-store/scope/path' }]);
 
       // If the worker enters the "redundant" state, the UA may terminate it
       // before all tests have been reported to the client. Stifle errors in
       // order to avoid this and ensure all tests are consistently reported.
     } catch (err) {}
   })());
 });
 
--- a/testing/web-platform/tests/cookies/http-state/resources/test-files/0002-test
+++ b/testing/web-platform/tests/cookies/http-state/resources/test-files/0002-test
@@ -1,1 +1,1 @@
-Set-Cookie: foo=bar; Expires=Fri, 07 Aug 2019 08:04:19 GMT
+Set-Cookie: foo=bar; Expires=Fri, 01 Jan 2038 00:00:00 GMT
--- a/testing/web-platform/tests/cookies/http-state/resources/test-files/comma0006-test
+++ b/testing/web-platform/tests/cookies/http-state/resources/test-files/comma0006-test
@@ -1,1 +1,1 @@
-Set-Cookie: foo=bar; Expires=Fri, 07 Aug 2019 08:04:19 GMT
+Set-Cookie: foo=bar; Expires=Fri, 01 Jan 2038 00:00:00 GMT
--- a/testing/web-platform/tests/cookies/http-state/resources/test-files/comma0007-test
+++ b/testing/web-platform/tests/cookies/http-state/resources/test-files/comma0007-test
@@ -1,1 +1,1 @@
-Set-Cookie: foo=bar; Expires=Fri 07 Aug 2019 08:04:19 GMT, baz=qux
+Set-Cookie: foo=bar; Expires=Fri 01 Jan 2038 00:00:00 GMT, baz=qux
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/CSS2/floats-clear/adjoining-float-new-fc-crash.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=987004">
+<meta name="assert" content="The renderer should not crash.">
+<div style="width: 100px; overflow: hidden;">
+  <div style="float: left; width: 100%; height: 20px; background: hotpink;"></div>
+  <div style="clear: both;">
+    <span style="position: absolute; width: 10px; height: 10px; background: orange;"></span>
+    <div style="height: 10px; background: green; overflow: hidden;"></div>
+  </div>
+</div>
+<script>
+test(() => {
+}, 'Test passes if the renderer does not crash.');
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-animations/parsing/animation-name-computed.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Animations: getComputedStyle().animationName</title>
+<link rel="help" href="https://drafts.csswg.org/css-animations/#propdef-animation-name">
+<meta name="assert" content="animation-name computed value is as specified.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+</head>
+<body>
+<div id="target"></div>
+<script>
+test_computed_value("animation-name", 'none');
+
+test_computed_value("animation-name", 'foo');
+test_computed_value("animation-name", 'Both');
+test_computed_value("animation-name", 'ease-in');
+test_computed_value("animation-name", 'infinite');
+test_computed_value("animation-name", 'paused');
+test_computed_value("animation-name", 'first, second, third');
+
+// TODO: Test strings, after https://github.com/w3c/csswg-drafts/issues/2435
+// is resolved.
+// Examples that need testing either here or in animation-name-invalid.html :
+// '"Initial"', '"initial"', '"None"', '"Default"', '" x "', "1", '" "', '""',
+// '"multi word string"', '"---\\22---"'
+</script>
+</body>
+</html>
--- a/testing/web-platform/tests/css/css-box/inheritance.html
+++ b/testing/web-platform/tests/css/css-box/inheritance.html
@@ -1,25 +1,29 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta charset="utf-8">
 <title>Inheritance of CSS Box Model properties</title>
 <link rel="help" href="https://drafts.csswg.org/css-box-3/#property-index">
+<link rel="help" href="https://www.w3.org/TR/CSS2/">
 <meta name="assert" content="Properties do not inherit.">
 <meta name="assert" content="length-percentage properties have initial value 0.">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/inheritance-testcommon.js"></script>
 </head>
 <body>
 <div id="container">
   <div id="target"></div>
 </div>
 <script>
+assert_not_inherited('clear', 'none', 'right');
+assert_not_inherited('float', 'none', 'right');
+
 assert_not_inherited('margin-bottom', '0px', '10px');
 assert_not_inherited('margin-left', '0px', '10px');
 assert_not_inherited('margin-right', '0px', '10px');
 assert_not_inherited('margin-top', '0px', '10px');
 assert_not_inherited('margin-trim', 'none', 'all');
 assert_not_inherited('padding-bottom', '0px', '10px');
 assert_not_inherited('padding-left', '0px', '10px');
 assert_not_inherited('padding-right', '0px', '10px');
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-contain/contain-size-replaced-004-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Containment Reference: Size containment replaced elements intrinsic size</title>
+<style>
+  body > div, video, audio, img, canvas, svg, iframe {
+    border: 3px solid orange;
+    contain: size;
+    margin-bottom: 15px;
+    width: 0px;
+    height: 0px;
+    float: left;
+    clear: both;
+  }
+</style>
+<div>abc</div>
+<video></video><br>
+<video controls></video><br>
+<img src="../support/60x60-green.png"><br>
+<picture>
+<source srcset="../support/60x60-green.png">
+    <img>
+</picture><br>
+<canvas></canvas><br>
+<svg></svg><br>
+<iframe></iframe>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-contain/contain-size-replaced-004.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Containment Test: Size containment replaced elements intrinsic size</title>
+<link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size">
+<link rel="match" href="contain-size-replaced-004-ref.html">
+<meta name=assert content="This test checks that intrinsic size of replaced elements with 'contain: size' is zero.">
+<style>
+  body > div, video, audio, img, canvas, svg, iframe {
+    border: 3px solid orange;
+    contain: size;
+    margin-bottom: 15px;
+    width: min-content;
+    height: min-content;
+    float: left;
+    clear: both;
+  }
+</style>
+<div>abc</div>
+<video></video><br>
+<video controls></video><br>
+<img src="../support/60x60-green.png"><br>
+<picture>
+<source srcset="../support/60x60-green.png">
+    <img>
+</picture><br>
+<canvas></canvas><br>
+<svg></svg><br>
+<iframe></iframe>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-contain/contain-size-replaced-005-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Containment Reference: Size containment replaced elements intrinsic size</title>
+<style>
+  body > div, video, audio, img, canvas, svg, iframe {
+    position: absolute;
+    border: 3px solid orange;
+    contain: size;
+    margin-bottom: 15px;
+    width: 0px;
+    height: 0px;
+    float: left;
+    clear: both;
+  }
+</style>
+<div>abc</div>
+<video></video><br>
+<video controls></video><br>
+<img src="../support/60x60-green.png"><br>
+<picture>
+<source srcset="../support/60x60-green.png">
+    <img>
+</picture><br>
+<canvas></canvas><br>
+<svg></svg><br>
+<iframe></iframe>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-contain/contain-size-replaced-005.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Containment Test: Size containment replaced elements intrinsic size</title>
+<link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size">
+<link rel="match" href="contain-size-replaced-005-ref.html">
+<meta name=assert content="This test checks that intrinsic size of out-of-flow replaced elements with 'contain: size' is zero.">
+<style>
+  body > div, video, audio, img, canvas, svg, iframe {
+    position: absolute;
+    border: 3px solid orange;
+    contain: size;
+    margin-bottom: 15px;
+    width: min-content;
+    height: min-content;
+    float: left;
+    clear: both;
+  }
+</style>
+<div>abc</div>
+<video></video><br>
+<video controls></video><br>
+<img src="../support/60x60-green.png"><br>
+<picture>
+<source srcset="../support/60x60-green.png">
+    <img>
+</picture><br>
+<canvas></canvas><br>
+<svg></svg><br>
+<iframe></iframe>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-contain/contain-size-replaced-006-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Containment Reference: Size containment replaced elements intrinsic size</title>
+<style>
+  body > div, video, audio, img, canvas, svg, iframe {
+    border: 3px solid orange;
+    contain: size;
+    margin-bottom: 15px;
+    width: 25px;
+    height: 35px;
+    float: left;
+    clear: both;
+  }
+</style>
+<div>abc</div>
+<video></video><br>
+<video controls></video><br>
+<img src="../support/60x60-green.png"><br>
+<picture>
+<source srcset="../support/60x60-green.png">
+    <img>
+</picture><br>
+<canvas></canvas><br>
+<svg></svg><br>
+<iframe></iframe>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-contain/contain-size-replaced-006.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Containment Test: Size containment replaced elements intrinsic size</title>
+<link rel="help" href="https://drafts.csswg.org/css-contain-1/#containment-size">
+<link rel="match" href="contain-size-replaced-006-ref.html">
+<meta name=assert content="This test checks that min-width/min-height of replaced elements with 'contain: size' works.">
+<style>
+  body > div, video, audio, img, canvas, svg, iframe {
+    border: 3px solid orange;
+    contain: size;
+    margin-bottom: 15px;
+    min-width: 25px;
+    min-height: 35px;
+    width: min-content;
+    height: min-content;
+    float: left;
+    clear: both;
+  }
+</style>
+<div>abc</div>
+<video></video><br>
+<video controls></video><br>
+<img src="../support/60x60-green.png"><br>
+<picture>
+<source srcset="../support/60x60-green.png">
+    <img>
+</picture><br>
+<canvas></canvas><br>
+<svg></svg><br>
+<iframe></iframe>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-flexbox/fit-content-item-001.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#flex-base-size">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#algo-cross-item">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<meta name="flags" content="" />
+<meta name="assert" content="A column flex container shrink wraps items both when determining their flex base sizes and when laying them out after their flexed size has been determined." />
+
+<style>
+
+x-flexbox {
+  display: flex;
+  flex-direction: column;
+}
+
+x-item {
+  display: block;
+  background: red;
+  /* Override default alignment of "stretch" because items don't shrink to fit
+     when they are stretched. */
+  align-self: start;
+}
+
+#mainSizeDependsOnCrossSize {
+  padding-bottom: 50%;
+  background: green;
+}
+
+#widthSetter {
+  width: 100px;
+  height: 50px;
+  background: green;
+}
+
+</style>
+
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+
+<x-flexbox>
+  <x-item> <!-- If fit-content is skipped when determining flex base size, this item gets a main size of 50px + 100vw / 2. -->
+    <div id=widthSetter></div>
+    <div id=mainSizeDependsOnCrossSize></div>
+  </x-item>
+</x-flexbox>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-flexbox/percentage-heights-006.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<title>Definite cross sizes</title>
+<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#definite-sizes">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht" />
+<meta name="flags" content="" />
+<meta name="assert" content="In a column flexbox, the height of a fully inflexible item with fixed flex-basis is definite, and percent children resolve against the flex basis, not the specified height." />
+
+<style>
+x-flexbox {
+  display: flex;
+  flex-direction: column;
+}
+
+x-item {
+  height: 0px;
+  flex: 0 0 100px;
+}
+
+x-item>div {
+  width: 100px;
+  height: 100%;
+  background: green;
+}
+
+#reference-overlapped-red {
+  position: absolute;
+  background-color: red;
+  width: 100px;
+  height: 100px;
+  z-index: -1;
+}
+</style>
+
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+
+<div id="reference-overlapped-red"></div>
+
+<x-flexbox>
+  <x-item>
+    <div></div>
+  </x-item>
+</x-flexbox>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-fonts/font-weight-xxx-large-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-size: xxx-large; size equivalence</title>
+<link rel="author" title="Joel Olsson" href="joel_1st@hotmail.com">
+<body>
+<p>Test passes if the line below is identical, with matching font size.</p>
+<font size=7>Foo</font>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-fonts/font-weight-xxx-large.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+<title>CSS Test:  font-size: xxx-large; size equivalence</title>
+<link rel="author" title="Joel Olsson" href="joel_1st@hotmail.com">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-4/#font-size-prop">
+<link rel="help" href="https://www.w3.org/TR/css-fonts-4/#absolute-size-mapping">
+<link rel="match" href="font-weight-xxx-large-ref.html">
+<body>
+<p>Test passes if the line below is identical, with matching font size.</p>
+<span style="font-size: xxx-large">Foo</span>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-grid/chrome-crash-001.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=991446">
+<meta name="assert" content="The renderer should not crash.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body style="display: inline-grid; align-items: end;">
+  <div style="border-top-color: inherit;"></div>
+  text
+</body>
+<script>
+test(() => {
+  document.body.offsetTop;
+  document.body.style.alignItems = '';
+  document.body.offsetTop;
+}, 'The renderer should not crash.');
+</script>
--- a/testing/web-platform/tests/css/css-layout-api/auto-block-size-absolute.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/auto-block-size-absolute.https.html
@@ -55,18 +55,18 @@
 
 <!-- 100px x 100px, top, auto-size is ignored. -->
 <div class="container">
   <div class="test height-100" style="left: 0px; right: 0px;"></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('block-size-100', class {
-  *intrinsicSizes() {}
-  *layout() {
+  async intrinsicSizes() {}
+  async layout() {
     return {autoBlockSize: 100};
   }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
--- a/testing/web-platform/tests/css/css-layout-api/auto-block-size-flex.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/auto-block-size-flex.https.html
@@ -37,24 +37,24 @@
 <!-- Tests that floats using an auto block size get positioned correctly. -->
 <div class="flex">
   <div class="custom custom-100"></div>
   <div class="custom custom-50"></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('block-size-100', class {
-  *intrinsicSizes() {}
-  *layout() {
+  async intrinsicSizes() {}
+  async layout() {
     return {autoBlockSize: 100};
   }
 });
 registerLayout('block-size-50', class {
-  *intrinsicSizes() {}
-  *layout() {
+  async intrinsicSizes() {}
+  async layout() {
     return {autoBlockSize: 50};
   }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
--- a/testing/web-platform/tests/css/css-layout-api/auto-block-size-floats.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/auto-block-size-floats.https.html
@@ -39,18 +39,18 @@
 <!-- Tests that floats using an auto block size get positioned correctly. -->
 <div class="container">
   <div class="left test"></div>
   <div class="right test"></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('block-size-100', class {
-  *intrinsicSizes() {}
-  *layout() {
+  async intrinsicSizes() {}
+  async layout() {
     return {autoBlockSize: 100};
   }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
--- a/testing/web-platform/tests/css/css-layout-api/auto-block-size-inflow.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/auto-block-size-inflow.https.html
@@ -45,18 +45,18 @@
 <!-- 150px x 100px -->
 <div class="test height-100" style="min-width: 150px"></div>
 
 <!-- 50px x 100px -->
 <div class="test height-100" style="max-width: 50px"></div>
 
 <script id="code" type="text/worklet">
 registerLayout('block-size-100', class {
-  *intrinsicSizes() {}
-  *layout() {
+  async intrinsicSizes() {}
+  async layout() {
     return {autoBlockSize: 100};
   }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
--- a/testing/web-platform/tests/css/css-layout-api/auto-block-size-negative.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/auto-block-size-negative.https.html
@@ -33,18 +33,18 @@
 <script src="/common/reftest-wait.js"></script>
 <script src="/common/worklet-reftest.js"></script>
 
 <div class="test width-100"></div>
 <div class="test height-100"></div>
 
 <script id="code" type="text/worklet">
 registerLayout('block-size-negative', class {
-  *intrinsicSizes() {}
-  *layout() {
+  async intrinsicSizes() {}
+  async layout() {
     return {autoBlockSize: -100};
   }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
--- a/testing/web-platform/tests/css/css-layout-api/box-tree-registered.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/box-tree-registered.https.html
@@ -50,17 +50,17 @@
     <div class="inflow pink">
       <div style="margin-top: 50px;"></div>
     </div>
   </div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('registered', class {
-  *intrinsicSizes() {}
-  *layout() { throw Error(); }
+  async intrinsicSizes() {}
+  async layout() { throw Error(); }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
 </html>
--- a/testing/web-platform/tests/css/css-layout-api/constraints-data-function-failure.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/constraints-data-function-failure.https.html
@@ -24,39 +24,37 @@
 <script src="/common/worklet-reftest.js"></script>
 
 <div class="test">
   <div class="child"></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('parent', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout([child], edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout([child], edges, constraints, styleMap) {
     let childFragment = null;
 
     try {
-      childFragment = yield child.layoutNextFragment({
+      childFragment = await child.layoutNextFragment({
         data: { fn: function() {} }
       });
     } catch(e) {
       // Success! The structured cloning algorithm should have thrown an error.
-      childFragment = yield child.layoutNextFragment({});
+      childFragment = await child.layoutNextFragment({});
       return {autoBlockSize: 100, childFragments: [childFragment]};
     }
 
     return {autoBlockSize: 0, childFragments: [childFragment]};
   }
 });
 
 registerLayout('child', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout() {
+  async intrinsicSizes() {}
+  async layout() {
     return {autoBlockSize: 0};
   }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
--- a/testing/web-platform/tests/css/css-layout-api/constraints-data-sab-failure.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/constraints-data-sab-failure.https.html
@@ -24,44 +24,37 @@
 <script src="/common/worklet-reftest.js"></script>
 
 <div class="test">
   <div class="child"></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('parent', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout([child], edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout([child], edges, constraints, styleMap) {
     let childFragment = null;
 
     try {
-      // We need SABs to be enabled to properly run this test.
-      if (typeof SharedArrayBuffer !== 'undefined') {
-        childFragment = yield child.layoutNextFragment({
-          data: { sab: new SharedArrayBuffer(4) }
-        });
-      } else {
-        throw Error();
-      }
+      childFragment = await child.layoutNextFragment({
+        data: { sab: new SharedArrayBuffer(4) }
+      });
     } catch(e) {
       // Success! The structured cloning algorithm should have thrown an error.
-      childFragment = yield child.layoutNextFragment({});
+      childFragment = await child.layoutNextFragment({});
       return {autoBlockSize: 100, childFragments: [childFragment]};
     }
 
     return {autoBlockSize: 0, childFragments: [childFragment]};
   }
 });
 
 registerLayout('child', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout() {
+  async intrinsicSizes() {}
+  async layout() {
     return {autoBlockSize: 0};
   }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
--- a/testing/web-platform/tests/css/css-layout-api/constraints-data.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/constraints-data.https.html
@@ -30,35 +30,33 @@
 <script id="code" type="text/worklet">
 const DATA = {
   str: 'hello',
   num: 42,
   obj: {str2: 'world'},
 };
 
 registerLayout('parent', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout([child], edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout([child], edges, constraints, styleMap) {
 
-    const childFragment = yield child.layoutNextFragment({data: DATA});
+    const childFragment = await child.layoutNextFragment({data: DATA});
 
     // If the child's block-size is 100 the structured cloning worked.
     if (childFragment.blockSize === 100) {
       return {autoBlockSize: 100, childFragments: [childFragment]};
     }
 
     return {autoBlockSize: 0, childFragments: [childFragment]};
   }
 });
 
 registerLayout('child', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout(children, edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout(children, edges, constraints, styleMap) {
     // Use JSON.stringify to make sure the structured cloning worked.
     if (constraints.data !== DATA &&
         JSON.stringify(constraints.data) === JSON.stringify(DATA)) {
       return {autoBlockSize: 100};
     }
 
     return {autoBlockSize: 0};
   }
--- a/testing/web-platform/tests/css/css-layout-api/fallback-constructor-error.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/fallback-constructor-error.https.html
@@ -35,17 +35,17 @@
 <div class="test">
   <div class="float"></div>
   <div class="fc"></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('throwing-ctor', class {
   constructor() { throw Error('fail!'); }
-  *intrinsicSizes() {}
-  *layout() {}
+  async intrinsicSizes() {}
+  async layout() {}
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
 </html>
--- a/testing/web-platform/tests/css/css-layout-api/fallback-layout-error.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/fallback-layout-error.https.html
@@ -34,17 +34,17 @@
 <!-- This tests that when the "layout()" layout function fails, it will fallback to block layout. -->
 <div class="test">
   <div class="float"></div>
   <div class="fc"></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('throwing-layout', class {
-  *intrinsicSizes() {}
-  *layout() { throw Error('fail!'); }
+  async intrinsicSizes() {}
+  async layout() { throw Error('fail!'); }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
 </html>
--- a/testing/web-platform/tests/css/css-layout-api/fallback-layout-invalid-child.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/fallback-layout-invalid-child.https.html
@@ -27,25 +27,25 @@
 <div class="test">
   <div></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('bad-child-layout', class {
   static get inputProperties() { return ['--fail']; }
 
-  *intrinsicSizes() {}
-  *layout(children, _, __, styleMap) {
+  async intrinsicSizes() {}
+  async layout(children, _, __, styleMap) {
     if (styleMap.get('--fail').toString() !== 'true') {
       this.child = children[0];
     }
 
     // Try to perform layout on the child. If its invalid (we skipped the if
     // statement above) we should fallback to block layout.
-    const fragment = yield this.child.layoutNextFragment({});
+    const fragment = await this.child.layoutNextFragment({});
 
     return {autoBlockSize: 0, childFragments: [fragment]};
   }
 });
 </script>
 
 <script>
 function raf() {
deleted file mode 100644
--- a/testing/web-platform/tests/css/css-layout-api/fallback-layout-invalid-fragment-request.https.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!DOCTYPE html>
-<html class=reftest-wait>
-<link rel="help" href="https://drafts.css-houdini.org/css-layout-api/#invoke-a-layout-callback">
-<link rel="match" href="fallback-ref.html">
-<meta name="assert" content="This test checks that a layout() class performing layout on an invalid fragment request will fallback to block layout." />
-<style>
-.test {
-  background: red;
-  border: solid 2px;
-  width: 100px;
-}
-
-.test > div {
-  height: 100px;
-}
-
-@supports (display: layout(bad-request)) {
-  .test {
-    display: layout(bad-request);
-    background: green;
-  }
-}
-</style>
-<script src="/common/reftest-wait.js"></script>
-<script src="/common/worklet-reftest.js"></script>
-
-<div class="test">
-  <div></div>
-</div>
-
-<script id="code" type="text/worklet">
-registerLayout('bad-request', class {
-  static get inputProperties() { return ['--fail']; }
-
-  *intrinsicSizes() {}
-  *layout(children, _, __, styleMap) {
-    if (styleMap.get('--fail').toString() !== 'true') {
-      this.request = children[0].layoutNextFragment({});
-    }
-
-    // Try to perform layout on the child. If its invalid (we skipped the if
-    // statement above) we should fallback to block layout.
-    const childFragments = yield [this.request];
-
-    return {autoBlockSize: 0, childFragments};
-  }
-});
-</script>
-
-<script>
-function raf() {
-  return new Promise((resolve) => {
-    requestAnimationFrame(() => {
-      resolve();
-    });
-  });
-}
-
-(async function() {
-  if (typeof CSS.layoutWorklet === 'undefined') {
-    takeScreenshot();
-    return;
-  }
-
-  await importWorklet(CSS.layoutWorklet, document.getElementById('code').textContent);
-
-  // Ensure that all instances have a child to perform an invalid layout upon.
-  const test = document.getElementsByClassName('test')[0];
-  for (let i = 0; i < 100; i++) {
-    test.innerHTML = '<div><div>';
-    await raf();
-  }
-
-  // The next layout should mean that we will fallback to block.
-  test.innerHTML = '<div></div>';
-  test.style.setProperty('--fail', 'true');
-
-  // Finish up the test.
-  await raf();
-  await raf();
-  takeScreenshot();
-})();
-</script>
-</html>
--- a/testing/web-platform/tests/css/css-layout-api/fallback-layout-invalid-fragment.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/fallback-layout-invalid-fragment.https.html
@@ -27,20 +27,20 @@
 <div class="test">
   <div></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('bad-request', class {
   static get inputProperties() { return ['--fail']; }
 
-  *intrinsicSizes() {}
-  *layout(children, _, __, styleMap) {
+  async intrinsicSizes() {}
+  async layout(children, _, __, styleMap) {
     if (styleMap.get('--fail').toString() !== 'true') {
-      this.fragment = yield children[0].layoutNextFragment({});
+      this.fragment = await children[0].layoutNextFragment({});
     }
 
     // Return, if the fragment is invalid (we skipped the if statement above)
     // we should fallback to block layout.
     return {autoBlockSize: 0, childFragments: [this.fragment]};
   }
 });
 </script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-layout-api/fallback-layout-no-promise.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel="help" href="https://drafts.css-houdini.org/css-layout-api/#invoke-a-layout-callback">
+<link rel="match" href="fallback-ref.html">
+<meta name="assert" content="This test checks that a layout() class with a layout function that doesn't return a promise will fallback to block layout." />
+<style>
+.test {
+  background: red;
+  border: solid 2px;
+  width: 100px;
+}
+
+.child {
+  height: 100px;
+}
+
+@supports (display: layout(no-promise)) {
+  .test {
+    display: layout(no-promise);
+    background: green;
+  }
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+
+<div class="test">
+  <div class="child"></div>
+</div>
+
+<script id="code" type="text/worklet">
+registerLayout('no-promise', class {
+  async intrinsicSizes() {}
+  layout() { return {autoBlockSize: 50}; }
+});
+</script>
+
+<script>
+importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
+</script>
+</html>
--- a/testing/web-platform/tests/css/css-layout-api/fallback-layout-return.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/fallback-layout-return.https.html
@@ -34,17 +34,17 @@
 <!-- This tests that when the "layout()" layout function returns a bad value, it will fallback to block layout. -->
 <div class="test">
   <div class="float"></div>
   <div class="fc"></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('bad-return', class {
-  *intrinsicSizes() {}
-  *layout() { return 42; }
+  async intrinsicSizes() {}
+  async layout() { return 42; }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
 </html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-layout-api/fallback-layout-unresolved-promise.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel="help" href="https://drafts.css-houdini.org/css-layout-api/#invoke-a-layout-callback">
+<link rel="match" href="fallback-ref.html">
+<meta name="assert" content="This test checks that a layout() class with a layout function that doesn't return a promise will fallback to block layout." />
+<style>
+.test {
+  background: red;
+  border: solid 2px;
+  width: 100px;
+}
+
+.child {
+  height: 100px;
+}
+
+@supports (display: layout(unresolved-promise)) {
+  .test {
+    display: layout(unresolved-promise);
+    background: green;
+  }
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+
+<div class="test">
+  <div class="child"></div>
+</div>
+
+<script id="code" type="text/worklet">
+registerLayout('unresolved-promise', class {
+  async intrinsicSizes() {}
+  layout() { return new Promise(() => { /* never resolves */ }); }
+});
+</script>
+
+<script>
+importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
+</script>
+</html>
--- a/testing/web-platform/tests/css/css-layout-api/fragment-data-function-failure.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/fragment-data-function-failure.https.html
@@ -24,20 +24,19 @@
 <script src="/common/worklet-reftest.js"></script>
 
 <div class="test">
   <div class="child"></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('fallback-fn', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout(children, edges, constraints, styleMap) {
-    const childFragments = yield children.map(child => child.layoutNextFragment());
+  async intrinsicSizes() {}
+  async layout(children, edges, constraints, styleMap) {
+    const childFragments = await children.map(child => child.layoutNextFragment());
     return {autoBlockSize: 0, childFragments, data: {fn: function() {}}};
   }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
--- a/testing/web-platform/tests/css/css-layout-api/fragment-data-immutable.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/fragment-data-immutable.https.html
@@ -24,47 +24,45 @@
 <script src="/common/worklet-reftest.js"></script>
 
 <div class="test">
   <div class="child"></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('parent', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout([child], edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout([child], edges, constraints, styleMap) {
 
-    const childFragment10 = yield child.layoutNextFragment({fixedInlineSize: 10});
+    const childFragment10 = await child.layoutNextFragment({fixedInlineSize: 10});
 
     // First layout data should be "10".
     if (childFragment10.data.size !== 10) {
       return {autoBlockSize: 0, childFragments: [childFragment10]};
     }
 
-    const childFragment20 = yield child.layoutNextFragment({fixedInlineSize: 20});
+    const childFragment20 = await child.layoutNextFragment({fixedInlineSize: 20});
 
     // Second layout data should be "20".
     if (childFragment20.data.size !== 20) {
       return {autoBlockSize: 0, childFragments: [childFragment10]};
     }
 
     // First layout data should still be "10".
     if (childFragment10.data.size !== 10) {
       return {autoBlockSize: 0, childFragments: [childFragment10]};
     }
 
     return {autoBlockSize: 100, childFragments: [childFragment20]};
   }
 });
 
 registerLayout('child', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout(children, edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout(children, edges, constraints, styleMap) {
     return {autoBlockSize: 10, data: {size: constraints.fixedInlineSize}};
   }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
--- a/testing/web-platform/tests/css/css-layout-api/fragment-data-sab-failure.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/fragment-data-sab-failure.https.html
@@ -24,26 +24,21 @@
 <script src="/common/worklet-reftest.js"></script>
 
 <div class="test">
   <div class="child"></div>
 </div>
 
 <script id="code" type="text/worklet">
 registerLayout('fallback-sab', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout(children, edges, constraints, styleMap) {
-    const childFragments = yield children.map(child => child.layoutNextFragment());
+  async intrinsicSizes() {}
+  async layout(children, edges, constraints, styleMap) {
+    const childFragments = await Promise.all(children.map(child => child.layoutNextFragment()));
 
-    if (typeof SharedArrayBuffer !== 'undefined') {
-      return {autoBlockSize: 0, childFragments, data: {sab: new SharedArrayBuffer(4) }};
-    } else {
-      throw Error();
-    }
+    return {autoBlockSize: 0, childFragments, data: {sab: new SharedArrayBuffer(4) }};
   }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
 </html>
--- a/testing/web-platform/tests/css/css-layout-api/fragment-data.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/fragment-data.https.html
@@ -30,36 +30,34 @@
 <script id="code" type="text/worklet">
 const DATA = {
   str: 'hello',
   num: 42,
   obj: {str2: 'world'},
 };
 
 registerLayout('parent', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout([child], edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout([child], edges, constraints, styleMap) {
 
-    const childFragment = yield child.layoutNextFragment();
+    const childFragment = await child.layoutNextFragment();
 
     // Use JSON.stringify to make sure the structured cloning worked.
     if (childFragment.data !== DATA &&
         JSON.stringify(childFragment.data) === JSON.stringify(DATA)) {
       return {autoBlockSize: 100, childFragments: [childFragment]};
     }
 
     return {autoBlockSize: 0, childFragments: [childFragment]};
   }
 });
 
 registerLayout('child', class {
-  *intrinsicSizes() {}
-  *layout() {}
-  *layout(children, edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout(children, edges, constraints, styleMap) {
     return {autoBlockSize: 10, data: DATA};
   }
 });
 </script>
 
 <script>
 importWorkletAndTerminateTestAfterAsyncPaint(CSS.layoutWorklet, document.getElementById('code').textContent);
 </script>
--- a/testing/web-platform/tests/css/css-layout-api/style-map-multi.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/style-map-multi.https.html
@@ -28,18 +28,18 @@
 <div class="test"></div>
 
 <script id="code" type="text/worklet">
 registerLayout('test', class {
   static get inputProperties() {
     return [ '--bar', '--foo', 'empty-cells', 'margin-left'];
   }
 
-  *intrinsicSizes() {}
-  *layout(children, edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout(children, edges, constraints, styleMap) {
     const expected = [
       {property: '--bar', value: '[CSSUnparsedValue=]'},
       {property: '--foo', value: '[CSSUnparsedValue= bar]'},
       {property: 'empty-cells', value: '[CSSKeywordValue=show]'},
       {property: 'margin-left', value: '[CSSUnitValue=2px]'},
     ];
 
     const actual = Array.from(styleMap.keys()).sort().map((property) => {
--- a/testing/web-platform/tests/css/css-layout-api/style-map.https.html
+++ b/testing/web-platform/tests/css/css-layout-api/style-map.https.html
@@ -35,18 +35,18 @@
 <div class="test test-3"></div>
 
 <script>
 const tmpl = (test, idx) => {
   return `
     registerLayout('test-${idx}', class {
       static get inputProperties() { return ['${test.property}']; }
 
-      *intrinsicSizes() {}
-      *layout(children, edges, constraints, styleMap) {
+      async intrinsicSizes() {}
+      async layout(children, edges, constraints, styleMap) {
         const value = styleMap.get('${test.property}');
         const result = '[' + value.constructor.name + '=' + value.toString() + ']';
         if (result != '${test.expected}')
           return {autoBlockSize: 0};
 
         const size = Array.from(styleMap.keys()).length;
         if (size != 1)
           return {autoBlockSize: 0};
--- a/testing/web-platform/tests/css/css-layout-api/support/constraints-fixed-block-size.js
+++ b/testing/web-platform/tests/css/css-layout-api/support/constraints-fixed-block-size.js
@@ -1,22 +1,22 @@
 registerLayout('test', class {
   static get inputProperties() {
     return ['--expected-block-size'];
   }
 
-  *intrinsicSizes() {}
-  *layout([child], edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout([child], edges, constraints, styleMap) {
     let childFixedInlineSize = 0;
     let childFixedBlockSize = 0;
     if (constraints.fixedBlockSize === JSON.parse(styleMap.get('--expected-block-size'))) {
       childFixedInlineSize = 100;
       childFixedBlockSize = 100;
     }
 
-    const childFragments = [yield child.layoutNextFragment({
+    const childFragments = [await child.layoutNextFragment({
       fixedInlineSize: childFixedInlineSize,
       fixedBlockSize: childFixedBlockSize,
     })];
 
     return {childFragments};
   }
 });
--- a/testing/web-platform/tests/css/css-layout-api/support/constraints-fixed-inline-size.js
+++ b/testing/web-platform/tests/css/css-layout-api/support/constraints-fixed-inline-size.js
@@ -1,9 +1,9 @@
 registerLayout('test', class {
-  *intrinsicSizes() {}
-  *layout(children, edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout(children, edges, constraints, styleMap) {
     if (constraints.fixedInlineSize !== 100)
       return {autoBlockSize: 0};
 
     return {autoBlockSize: 100};
   }
 });
--- a/testing/web-platform/tests/css/css-layout-api/support/layout-child-sizes-worklet.js
+++ b/testing/web-platform/tests/css/css-layout-api/support/layout-child-sizes-worklet.js
@@ -15,35 +15,35 @@ registerLayout('test', class {
       '--fixed-block-size',
       '--percentage-inline-size',
       '--percentage-block-size',
       '--inline-size-expected',
       '--block-size-expected'
     ];
   }
 
-  *intrinsicSizes() {}
-  *layout(children, edges, constraints, styleMap) {
-    const childFragments = yield children.map((child) => {
+  async intrinsicSizes() {}
+  async layout(children, edges, constraints, styleMap) {
+    const childFragments = await Promise.all(children.map((child) => {
       const childConstraints = {};
       const availableInlineSize = parseNumber(child.styleMap.get('--available-inline-size'));
       const availableBlockSize = parseNumber(child.styleMap.get('--available-block-size'));
       const fixedInlineSize = parseNumber(child.styleMap.get('--fixed-inline-size'));
       const fixedBlockSize = parseNumber(child.styleMap.get('--fixed-block-size'));
       const percentageInlineSize = parseNumber(child.styleMap.get('--percentage-inline-size'));
       const percentageBlockSize = parseNumber(child.styleMap.get('--percentage-block-size'));
       return child.layoutNextFragment({
         availableInlineSize,
         availableBlockSize,
         fixedInlineSize,
         fixedBlockSize,
         percentageInlineSize,
         percentageBlockSize,
       });
-    });
+    }));
 
     const actual = childFragments.map((childFragment) => {
       return {
         inlineSize: childFragment.inlineSize,
         blockSize: childFragment.blockSize,
       };
     });
 
--- a/testing/web-platform/tests/css/css-layout-api/support/layout-child-worklet.js
+++ b/testing/web-platform/tests/css/css-layout-api/support/layout-child-worklet.js
@@ -4,23 +4,23 @@ registerLayout('test', class {
   static get inputProperties() {
     return [ '--child-expected'];
   }
 
   static get childInputProperties() {
     return [ '--child' ];
   }
 
-  *intrinsicSizes() {}
-  *layout(children, edges, constraints, styleMap) {
+  async intrinsicSizes() {}
+  async layout(children, edges, constraints, styleMap) {
     const expected = JSON.parse(styleMap.get('--child-expected').toString());
     const actual = children.map((child) => {
       return child.styleMap.get('--child').toString().trim();
     });
 
-    const childFragments = yield children.map((child) => { return child.layoutNextFragment({}); });
+    const childFragments = await Promise.all(children.map(child => child.layoutNextFragment({})));
 
     if (!areArraysEqual(expected, actual))
       return {autoBlockSize: 0, childFragments};
 
     return {autoBlockSize: 100, childFragments};
   }
 });
--- a/testing/web-platform/tests/css/css-layout-api/support/layout-position-child-worklet.js
+++ b/testing/web-platform/tests/css/css-layout-api/support/layout-position-child-worklet.js
@@ -1,21 +1,19 @@
 registerLayout('test', class {
   static get childInputProperties() {
     return [
       '--inline-offset',
       '--block-offset',
     ];
   }
 
-  *intrinsicSizes() {}
-  *layout(children, edges, constraints, styleMap) {
-    const childFragments = yield children.map((child) => {
-      return child.layoutNextFragment({});
-    });
+  async intrinsicSizes() {}
+  async layout(children, edges, constraints, styleMap) {
+    const childFragments = await Promise.all(children.map((child) => child.layoutNextFragment({})));
 
     for (let i = 0; i < children.length; i++) {
       childFragments[i].inlineOffset = parseInt(children[i].styleMap.get('--inline-offset').toString());
       childFragments[i].blockOffset = parseInt(children[i].styleMap.get('--block-offset').toString());
     }
 
     return {autoBlockSize: 0, childFragments};
   }
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-layout-api/sync-layout-microtasks.https.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<link rel="help" href="https://drafts.css-houdini.org/css-layout-api/#invoke-a-layout-callback">
+<meta name="assert" content="This test checks running the microtask queue for a layout() class won't run the main world's microtask queue." />
+<style>
+#test {
+  display: layout(child-layout);
+  width: 100px;
+}
+
+#test > div {
+  height: 100px;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+
+<div id="test">
+  <div></div>
+</div>
+
+<script id="code" type="text/worklet">
+registerLayout('child-layout', class {
+  async intrinsicSizes() {}
+  async layout([child]) {
+    const fragment = await child.layoutNextFragment();
+    return {autoBlockSize: 50, childFragments: [fragment]};
+  }
+});
+</script>
+
+<script>
+promise_test(async t => {
+  if (typeof CSS.layoutWorklet === 'undefined') {
+    throw Error('CSS Layout API not supported.');
+  }
+
+  await importWorklet(CSS.layoutWorklet, document.getElementById('code').textContent);
+
+  let resolved = false;
+  let p = Promise.resolve().then(() => {
+    resolved = true;
+  });
+  assert_false(resolved);
+
+  // Running the layout-worklet's microtask queue shouldn't trigger the main
+  // world's microtask queue.
+  assert_equals(document.getElementById('test').clientHeight, 50);
+  assert_false(resolved);
+
+  await p;
+  assert_true(resolved);
+});
+</script>
+</html>
deleted file mode 100644
--- a/testing/web-platform/tests/css/css-lists/list-and-margin-collapse-003.html
+++ /dev/null
@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<meta charset="utf-8">
-<title>CSS Lists: test the margin collapse of marker</title>
-<link rel=help href="https://www.w3.org/TR/CSS22/generate.html#lists">
-<link rel="help" href="http://crbug.com/969741">
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-
-<style type="text/css">
-.checkbox{
-  -moz-appearance: checkbox;
-  -webkit-appearance: checkbox;
-  height: 0px;
-}
-</style>
-
-<div id="log"></div>
-
-<div id="target_with_marker" style="overflow:hidden; width:100px;">
-  <div style="margin-bottom:100px;"></div>
-  <div style="display:list-item; margin-left:100px; height:0px;"><div class="checkbox"></div></div>
-  <div style="margin-top:100px;"></div>
-</div>
-
-<div id="target_without_marker" style="overflow:hidden; width:100px;">
-  <div style="margin-bottom:100px;"></div>
-  <div style="display:list-item; margin-left:100px; list-style:none;"><div class="checkbox"></div></div>
-  <div style="margin-top:100px;"></div>
-</div>
-
-<script>
-test(function() {
-  var height_with_marker = document.getElementById("target_with_marker").clientHeight;
-  assert_equals(height_with_marker, 200, "Should not allow margin-collapsing through if list is with marker.");
-  var height_without_marker = document.getElementById("target_without_marker").clientHeight;
-  assert_equals(height_without_marker, 100, "Should allow margin-collapsing through if list is without marker.");
-}, "list and margin collapse");
-</script>
deleted file mode 100644
--- a/testing/web-platform/tests/css/css-lists/list-and-margin-collapse-004.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<title>Test if it doesn't crash when resolving BFC block-offset abort</title>
-<link rel=help href="https://www.w3.org/TR/CSS22/generate.html#lists">
-<link rel="help" href="http://crbug.com/969741">
-
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<style type="text/css">
-#checkbox{
-  -moz-appearance: checkbox;
-  -webkit-appearance: checkbox;
-  height: 0px;
-}
-</style>
-<body>
-  <div style="float: left; width: 100px; height: 100px;"></div>
-  <div style="display: list-item;">
-    <div id="checkbox"></div>
-  </div>
-<script>
-test(() => {}, "Layout should not crash");
-</script>
-</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-lists/parsing/counter-increment-invalid.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Lists: parsing counter-increment with invalid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-lists-3/#propdef-counter-increment">
+<meta name="assert" content="counter-increment supports only the grammar '[ <counter-name> <integer>? ]+ | none'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value('counter-increment', 'none chapter');
+test_invalid_value('counter-increment', '3');
+test_invalid_value('counter-increment', '99 imagenum');
+test_invalid_value('counter-increment', 'section -1, imagenum 99');
+test_invalid_value('counter-increment', 'section 3.14');
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-lists/parsing/counter-increment-valid.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Lists: parsing counter-increment with valid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-lists-3/#propdef-counter-increment">
+<meta name="assert" content="counter-increment supports the full grammar '[ <counter-name> <integer>? ]+ | none'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value('counter-increment', 'none');
+test_valid_value('counter-increment', 'chapter', 'chapter 1');
+test_valid_value('counter-increment', 'section -1');
+test_valid_value('counter-increment', 'first -1 second third 99', 'first -1 second 1 third 99');
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-lists/parsing/counter-reset-invalid.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Lists: parsing counter-reset with invalid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-lists-3/#propdef-counter-reset">
+<meta name="assert" content="counter-reset supports only the grammar '[ <counter-name> <integer>? ]+ | none'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value('counter-reset', 'none chapter');
+test_invalid_value('counter-reset', '3');
+test_invalid_value('counter-reset', '99 imagenum');
+test_invalid_value('counter-reset', 'section -1, imagenum 99');
+test_invalid_value('counter-reset', 'section 3.14');
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-lists/parsing/counter-reset-valid.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Lists: parsing counter-reset with valid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-lists-3/#propdef-counter-reset">
+<meta name="assert" content="counter-reset supports the full grammar '[ <counter-name> <integer>? ]+ | none'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value('counter-reset', 'none');
+test_valid_value('counter-reset', 'chapter', 'chapter 0');
+test_valid_value('counter-reset', 'section -1');
+test_valid_value('counter-reset', 'first -1 second third 99', 'first -1 second 0 third 99');
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-lists/parsing/counter-set-invalid.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Lists: parsing counter-set with invalid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-lists-3/#propdef-counter-set">
+<meta name="assert" content="counter-set supports only the grammar '[ <counter-name> <integer>? ]+ | none'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_invalid_value('counter-set', 'none chapter');
+test_invalid_value('counter-set', '3');
+test_invalid_value('counter-set', '99 imagenum');
+test_invalid_value('counter-set', 'section -1, imagenum 99');
+test_invalid_value('counter-set', 'section 3.14');
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-lists/parsing/counter-set-valid.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Lists: parsing counter-set with valid values</title>
+<link rel="help" href="https://drafts.csswg.org/css-lists-3/#propdef-counter-set">
+<meta name="assert" content="counter-set supports the full grammar '[ <counter-name> <integer>? ]+ | none'.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value('counter-set', 'none');
+test_valid_value('counter-set', 'chapter', 'chapter 0');
+test_valid_value('counter-set', 'section -1');
+test_valid_value('counter-set', 'first -1 second third 99', 'first -1 second 0 third 99');
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/background-repeat-x-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<body>
+<canvas id ="canvas" width="200" height="200"></canvas>
+<script>
+var ctx = document.getElementById('canvas').getContext('2d');
+ctx.fillStyle = 'green';
+ctx.fillRect(0, 0, 50, 50);
+ctx.fillRect(100, 0, 50, 50);
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-paint-api/background-repeat-x.https.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="help" href="https://drafts.css-houdini.org/css-paint-api/">
+<link rel="match" href="background-repeat-x-ref.html">
+<style>
+.container {
+  width: 200px;
+  height: 200px;
+}
+#foo {
+  background: paint(foo) top left/50% 50% repeat-x;
+}
+</style>
+<script src="/common/reftest-wait.js"></script>
+<script src="/common/worklet-reftest.js"></script>
+<body>
+<div id="foo" class="container"></div>
+
+<script id="code" type="text/worklet">
+registerPaint('foo', class {
+    paint(ctx, geom) {
+        ctx.fillStyle = 'green';
+        ctx.fillRect(0, 0, 50, 50);
+    }
+});
+</script>
+
+<script>
+    importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-writing-modes/bidi-line-break-001.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<title>Test implicit bidi controls do not affect line breaking</title>
+<link rel="help" href="https://drafts.csswg.org/css-writing-modes-3/#unicode-bidi">
+<link rel="author" title="Koji Ishii" href="mailto:kojii@chromium.org">
+<style>
+html {
+  font-size: 10px;
+  line-height: 1;
+}
+.isolate {
+  unicode-bidi: isolate;
+}
+.embed {
+  unicode-bidi: embed;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div id=log></div>
+<div id="container">
+  <div style="width: 4ch" data-expected-height="20">
+    <span class="isolate" dir="ltr">00</span> <span class="isolate" dir="ltr">00</span>
+  </div>
+  <div style="width: 4ch" data-expected-height="20">
+    <span class="embed" dir="ltr">00</span> <span class="embed" dir="ltr">00</span>
+  </div>
+
+  <div style="width: 4ch" data-expected-height="20">
+    <span dir="ltr">00</span> <span dir="ltr">00</span>
+  </div>
+  <div style="width: 4ch" data-expected-height="20">
+    <bdi dir="ltr">00</bdi> <bdi dir="ltr">00</bdi>
+  </div>
+  <div style="width: 4ch" data-expected-height="20">
+    <bdo dir="ltr">00</bdo> <bdo dir="ltr">00</bdo>
+  </div>
+
+  <div style="width: 4ch" data-expected-height="20">
+    <span class="isolate" dir="ltr">00 </span><span class="isolate" dir="ltr">00</span>
+  </div>
+  <div style="width: 4ch" data-expected-height="20">
+    <span class="embed" dir="ltr">00 </span><span class="embed" dir="ltr">00</span>
+  </div>
+</div>
+<script>
+run();
+function run() {
+  for (let node of document.getElementById('container').children) {
+    test(() => {
+      assert_approx_equals(node.offsetHeight, 20, 1);
+    }, node.innerHTML);
+  }
+}
+</script>
+</body>
--- a/testing/web-platform/tests/css/filter-effects/inheritance.html
+++ b/testing/web-platform/tests/css/filter-effects/inheritance.html
@@ -1,25 +1,27 @@
 <!DOCTYPE html>
 <html>
 <head>
 <meta charset="utf-8">
 <title>Inheritance of Filter Effects properties</title>
 <link rel="help" href="https://drafts.fxtf.org/filter-effects/#property-index">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#property-index">
 <meta name="assert" content="Properties inherit according to the spec.">
 <meta name="assert" content="Properties have initial values according to the spec.">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/css/support/inheritance-testcommon.js"></script>
 </head>
 <body>
 <div id="container">
   <div id="target"></div>
 </div>
 <script>
+assert_not_inherited('backdrop-filter', 'none', 'blur(10px)');
 assert_inherited('color-interpolation-filters', 'linearrgb', 'srgb');
 assert_not_inherited('filter', 'none', 'blur(10px)');
 assert_not_inherited('flood-color', 'rgb(0, 0, 0)', 'rgb(42, 53, 64)');
 assert_not_inherited('flood-opacity', '1', '0.5');
 assert_not_inherited('lighting-color', 'rgb(255, 255, 255)', 'rgb(42, 53, 64)');
 </script>
 </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/form-associated/ElementInternals-accessibility.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+class TestElement extends HTMLElement {
+  constructor() {
+    super();
+    this._internals = this.attachInternals();
+  }
+
+  get internals() {
+    return this._internals;
+  }
+
+  set internals(val) {
+    throw "Can't set internals!";
+  }
+}
+customElements.define("test-element", TestElement);
+</script>
+
+<test-element id= "testElement"></test-element>
+
+<script>
+const element = document.getElementById("testElement");
+const properties = [
+  "role",
+  "ariaActiveDescendant",
+  "ariaAtomic",
+  "ariaAutoComplete",
+  "ariaBusy",
+  "ariaChecked",
+  "ariaColCount",
+  "ariaColIndex",
+  "ariaColSpan",
+  "ariaControls",
+  "ariaCurrent",
+  "ariaDescribedBy",
+  "ariaDetails",
+  "ariaDisabled",
+  "ariaErrorMessage",
+  "ariaExpanded",
+  "ariaFlowTo",
+  "ariaHasPopup",
+  "ariaHidden",
+  "ariaKeyShortcuts",
+  "ariaLabel",
+  "ariaLabelledBy",
+  "ariaLevel",
+  "ariaLive",
+  "ariaModal",
+  "ariaMultiLine",
+  "ariaMultiSelectable",
+  "ariaOrientation",
+  "ariaOwns",
+  "ariaPlaceholder",
+  "ariaPosInSet",
+  "ariaPressed",
+  "ariaReadOnly",
+  "ariaRelevant",
+  "ariaRequired",
+  "ariaRoleDescription",
+  "ariaRowCount",
+  "ariaRowIndex",
+  "ariaRowSpan",
+  "ariaSelected",
+  "ariaSort",
+  "ariaValueMax",
+  "ariaValueMin",
+  "ariaValueNow",
+  "ariaValueText"
+];
+for (const property of properties) {
+  test(() => {
+    assert_inherits(element.internals, property);
+  }, property + " is defined in ElementInternals");
+}
+</script>
--- a/testing/web-platform/tests/docs/Makefile
+++ b/testing/web-platform/tests/docs/Makefile
@@ -8,16 +8,17 @@ SOURCEDIR     = .
 BUILDDIR      = _build
 
 # Put it first so that "make" without argument is like "make help".
 help:
 	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
 
 .PHONY: help Makefile
 
-tools/wptserve:
+tools/%:
 	mkdir -p $(shell dirname $@)
-	ln -s ../../tools/wptserve $@
+	test -d ../$@
+	ln -s ../../$@ $@
 
 # Catch-all target: route all unknown targets to Sphinx using the new
 # "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
-%: Makefile tools/wptserve
+%: Makefile tools/wptserve tools/certs
 	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
deleted file mode 100644
--- a/testing/web-platform/tests/docs/appendix/index.md
+++ /dev/null
@@ -1,10 +0,0 @@
-# Appendices
-
-```eval_rst
-.. toctree ::
-   :maxdepth: 1
-
-   github-intro
-   reverting
-   test-templates
-```
--- a/testing/web-platform/tests/docs/index.md
+++ b/testing/web-platform/tests/docs/index.md
@@ -48,15 +48,14 @@ free to add yourself to the META.yml fil
 .. toctree::
    :maxdepth: 2
 
    test-suite-design
    running-tests/index
    writing-tests/index
    reviewing-tests/index
    admin/index
-   appendix/index
 ```
 
 [public-test-infra]: https://lists.w3.org/Archives/Public/public-test-infra/
 [IRC]: irc://irc.w3.org:6667/testing
 [web irc]: http://irc.w3.org
-[github-intro]: appendix/github-intro
+[github-intro]: writing-tests/github-intro
--- a/testing/web-platform/tests/docs/make.bat
+++ b/testing/web-platform/tests/docs/make.bat
@@ -23,16 +23,17 @@ if errorlevel 9009 (
 	echo.If you don't have Sphinx installed, grab it from
 	echo.http://sphinx-doc.org/
 	exit /b 1
 )
 
 if not exist tools\ ( mkdir tools )
 
 if not exist tools\wptserve\ ( mklink /d tools\wptserve ..\..\tools\wptserve )
+if not exist tools\certs\ ( mklink /d tools\certs ..\..\tools\certs )
 
 %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
 goto end
 
 :help
 %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
 
 :end
--- a/testing/web-platform/tests/docs/reviewing-tests/git.md
+++ b/testing/web-platform/tests/docs/reviewing-tests/git.md
@@ -71,13 +71,13 @@ 4. Go to the Github Web UI to [submit a 
 When you're done reviewing or making changes,
 you can delete the branch: `git branch -d <name-of-the-PR-branch>`
 (use `-D` instead of `-d` to delete a branch that has not been merged into master yet).
 
 If you do not expect work with more PRs from the same author,
 you may also discard your connection to their repo:
 `git remote remove <author-id>`
 
-[clone]: ../appendix/github-intro.html#clone
-[commit]: ../appendix/github-intro.html#commit
-[configure]: ../appendix/github-intro.html#configure-remote-upstream
-[fork]: ../appendix/github-intro.html#fork-the-test-repository
-[submit]: ../appendix/github-intro.html#submit
+[clone]: ../writing-tests/github-intro.html#clone
+[commit]: ../writing-tests/github-intro.html#commit
+[configure]: ../writing-tests/github-intro.html#configure-remote-upstream
+[fork]: ../writing-tests/github-intro.html#fork-the-test-repository
+[submit]: ../writing-tests/github-intro.html#submit
--- a/testing/web-platform/tests/docs/reviewing-tests/index.md
+++ b/testing/web-platform/tests/docs/reviewing-tests/index.md
@@ -5,16 +5,17 @@ suites, test contributions must be revie
 
 ```eval_rst
 .. toctree::
    :maxdepth: 1
 
    checklist
    email
    git
+   reverting
 ```
 
 ## Test Review Policy
 
 The reviewer can be anyone (other than the original test author) that
 has the required experience with both the spec under test and with
 the [general test guidelines](../writing-tests/general-guidelines).
 
rename from testing/web-platform/tests/docs/appendix/reverting.md
rename to testing/web-platform/tests/docs/reviewing-tests/reverting.md
--- a/testing/web-platform/tests/docs/running-tests/from-local-system.md
+++ b/testing/web-platform/tests/docs/running-tests/from-local-system.md
@@ -91,20 +91,25 @@ port definitions of your choice e.g.:
 }
 ```
 
 After your `hosts` file is configured, the servers will be locally accessible at:
 
 http://web-platform.test:8000/<br>
 https://web-platform.test:8443/ *
 
+To use the web-based runner point your browser to:
+
+http://web-platform.test:8000/tools/runner/index.html<br>
+https://web-platform.test:8443/tools/runner/index.html *
+
 This server has all the capabilities of the publicly-deployed version--see
 [Running the Tests from the Web](from-web).
 
-\**See [Trusting Root CA](https://github.com/web-platform-tests/wpt/blob/master/README.md#trusting-root-ca)*
+\**See [Trusting Root CA](../tools/certs/README.md)*
 
 ## Via the command line
 
 Many tests can be automatically executed in a new browser instance using
 
     ./wpt run [browsername] [tests]
 
 This will automatically load the tests in the chosen browser and extract the
--- a/testing/web-platform/tests/docs/running-tests/index.md
+++ b/testing/web-platform/tests/docs/running-tests/index.md
@@ -1,16 +1,17 @@
 # Running Tests
 
 ```eval_rst
 .. toctree::
 
    from-web
    from-local-system
    custom-runner
+   ../tools/certs/README.md
 ```
 
 The simplest way to run the tests is via the public website. More detail on
 that approach is available in [Running tests from the Web](from-web).
 
 Contributors who are interested in modifying and creating tests should refer to
 [Running Tests from the Local System](from-local-system).
 
--- a/testing/web-platform/tests/docs/writing-tests/file-names.md
+++ b/testing/web-platform/tests/docs/writing-tests/file-names.md
@@ -53,11 +53,13 @@ themselves precede any test type flag, b
 
 `.tentative`
  : Indicates that a test makes assertions not yet required by any specification,
    or in contradiction to some specification. This is useful when implementation
    experience is needed to inform the specification. It should be apparent in
    context why the test is tentative and what needs to be resolved to make it
    non-tentative.
 
+It's preferable that `.window`, `.worker`, and `.any` are immediately followed
+by their final `.js` extension.
 
 [server-side substitution]: https://wptserve.readthedocs.io/en/latest/pipes.html#sub
 [RFC 2119]: https://tools.ietf.org/html/rfc2119
--- a/testing/web-platform/tests/docs/writing-tests/general-guidelines.md
+++ b/testing/web-platform/tests/docs/writing-tests/general-guidelines.md
@@ -27,17 +27,18 @@ for more details.
 
 In the css directory, the file names should be unique within the whole
 css/ directory, regardless of where they are in the directory structure.
 
 ### HTTPS
 
 By default, tests are served over plain HTTP. If a test requires HTTPS
 it must be given a filename containing `.https` before the extension,
-e.g. `test-secure.https.html`. For more details see the documentation
+e.g., `test-secure.https.html`, or be the generated service worker test
+of a `.https`-less `.any` test. For more details see the documentation
 on [file names][file-name-flags].
 
 #### Support Files
 
 Various support files are available in in the directories named `/common/`,
 `/media/`, and `/css/support/`. Reusing existing resources is encouraged where
 possible, as is adding generally-useful files to these common areas rather than
 to specific test suites.
rename from testing/web-platform/tests/docs/appendix/github-intro.md
rename to testing/web-platform/tests/docs/writing-tests/github-intro.md
--- a/testing/web-platform/tests/docs/writing-tests/index.md
+++ b/testing/web-platform/tests/docs/writing-tests/index.md
@@ -21,18 +21,21 @@ There's also a load of [general guidelin
    reftest-tutorial
    reftests
    rendering
    server-features
    submission-process
    testdriver
    testdriver-tutorial
    testharness
+   tools
    visual
    wdspec
+   test-templates
+   github-intro
 ```
 
 ## Test Type
 
 Tests in this project use a few different approaches to verify expected
 behavior. The tests can be classified based on the way they express
 expectations:
 
--- a/testing/web-platform/tests/docs/writing-tests/reftest-tutorial.md
+++ b/testing/web-platform/tests/docs/writing-tests/reftest-tutorial.md
@@ -14,17 +14,17 @@ demotivating effect that a lengthy guide
 Let's say you've discovered that WPT doesn't have any tests for the `dir`
 attribute of [the `<bdo>`
 element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/bdo). This
 tutorial will guide you through the process of writing and submitting a test.
 You'll need to [configure your system to use WPT's
 tools](../running-tests/from-local-system), but you won't need them until
 towards the end of this tutorial. Although it includes some very brief
 instructions on using git, you can find more guidance in [the tutorial for git
-and GitHub](../appendix/github-intro).
+and GitHub](../writing-tests/github-intro).
 
 WPT's reftests are great for testing web-platform features that have some
 visual effect. [The reftests reference page](reftests) describes them in the
 abstract, but for the purposes of this guide, we'll only consider the features
 we need to test the `<bdo>` element.
 
 ```eval_rst
 .. contents::
@@ -259,17 +259,17 @@ Next, we'll create a commit with the sta
 
 And now we can push the commit to our fork of WPT:
 
     $ git push origin reftest-for-bdo
 
 The last step is to submit the test for review. WPT doesn't actually need the
 test we wrote in this tutorial, but if we wanted to submit it for inclusion in
 the repository, we would create a pull request on GitHub. [The guide on git and
-GitHub](../appendix/github-intro) has all the details on how to do that.
+GitHub](../writing-tests/github-intro) has all the details on how to do that.
 
 ## More practice
 
 Here are some ways you can keep experimenting with WPT using this test:
 
 - Improve coverage by adding more tests for related behaviors (e.g. nested
   `<bdo>` elements)
 - Add another reference document which describes what the test should *not*
--- a/testing/web-platform/tests/docs/writing-tests/submission-process.md
+++ b/testing/web-platform/tests/docs/writing-tests/submission-process.md
@@ -26,17 +26,17 @@ on, e.g. `git checkout -b topic-name`
 
 * When you get review comments, make more commits to your branch to
   address the comments.
 
 * Once everything is reviewed and all issues are addressed, your pull
   request will be automatically merged.
 
 For detailed guidelines on setup and each of these steps, please refer to the
-[Github Test Submission](../appendix/github-intro) documentation.
+[Github Test Submission](../writing-tests/github-intro) documentation.
 
 Hop on to the [mailing list][public-test-infra] or [IRC][]
 ([webclient][web irc], join channel `#testing`) if you have an issue.  There is
 no need to announce your review request, as soon as you make a Pull Request
 GitHub will inform interested parties.
 
 ## Previews
 
rename from testing/web-platform/tests/docs/appendix/test-templates.md
rename to testing/web-platform/tests/docs/writing-tests/test-templates.md
--- a/testing/web-platform/tests/docs/writing-tests/testharness.md
+++ b/testing/web-platform/tests/docs/writing-tests/testharness.md
@@ -160,17 +160,17 @@ It is possible to customize the set of s
 //           dedicated, shared and service worker scopes
 ```
 
 For a test file <code><var>x</var>.any.js</code>, the available scope keywords
 are:
 
 * `window` (default): to be run at <code><var>x</var>.any.html</code>
 * `dedicatedworker` (default): to be run at <code><var>x</var>.any.worker.html</code>
-* `serviceworker`: to be run at <code><var>x</var>.https.any.serviceworker.html</code>
+* `serviceworker`: to be run at <code><var>x</var>.any.serviceworker.html</code> (`.https` is implied)
 * `sharedworker`: to be run at <code><var>x</var>.any.sharedworker.html</code>
 * `jsshell`: to be run in a JavaScript shell, without access to the DOM
   (currently only supported in SpiderMonkey, and skipped in wptrunner)
 * `default`: shorthand for the default scopes
 * `worker`: shorthand for the dedicated, shared and service worker scopes
 
 To check if your test is run from a window or worker you can use the following two methods that will
 be made available by the framework:
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/docs/writing-tests/tools.md
@@ -0,0 +1,25 @@
+# Command-line utility scripts
+
+Sometimes you may want to add a script to the repository that's meant to be
+used from the command line, not from a browser (e.g., a script for generating
+test files). If you want to ensure (e.g., for security reasons) that such
+scripts won't be handled by the HTTP server, but will instead only be usable
+from the command line, then place them in either:
+
+* the `tools` subdir at the root of the repository, or
+
+* the `tools` subdir at the root of any top-level directory in the repository
+  which contains the tests the script is meant to be used with
+
+Any files in those `tools` directories won't be handled by the HTTP server;
+instead the server will return a 404 if a user navigates to the URL for a file
+within them.
+
+If you want to add a script for use with a particular set of tests but there
+isn't yet any `tools` subdir at the root of a top-level directory in the
+repository containing those tests, you can create a `tools` subdir at the root
+of that top-level directory and place your scripts there.
+
+For example, if you wanted to add a script for use with tests in the
+`notifications` directory, create the `notifications/tools` subdir and put your
+script there.
--- a/testing/web-platform/tests/fetch/corb/img-mime-types-coverage.tentative.sub.html
+++ b/testing/web-platform/tests/fetch/corb/img-mime-types-coverage.tentative.sub.html
@@ -17,16 +17,23 @@
       null, "", "x", "x/x",
 
       // MIME-types not protected by CORB
       "image/gif", "image/png", "image/png;blah", "image/svg+xml",
       "application/javascript", "application/jsonp",
       "application/dash+xml", // video format
       "image/gif;HI=THERE",
 
+      // Non-image MIME-types that in practice get used for images on the web.
+      //
+      // https://bugzilla.mozilla.org/show_bug.cgi?id=1302539
+      "application/octet-stream",
+      // https://crbug.com/990853
+      "application/x-www-form-urlencoded",
+
       // MIME types that may seem to be JSON or XML, but really aren't - i.e.
       // these MIME types are not covered by:
       // - https://mimesniff.spec.whatwg.org/#json-mime-type
       // - https://mimesniff.spec.whatwg.org/#xml-mime-type
       // - https://tools.ietf.org/html/rfc6839
       // - https://tools.ietf.org/html/rfc7303
       "text/x-json", "text/json+blah", "application/json+blah",
       "text/xml+blah", "application/xml+blah",
--- a/testing/web-platform/tests/fetch/corb/script-resource-with-nonsniffable-types.tentative.sub.html
+++ b/testing/web-platform/tests/fetch/corb/script-resource-with-nonsniffable-types.tentative.sub.html
@@ -51,17 +51,16 @@ function test(mime_type, is_blocking_exp
 }
 
 // Some mime types should be protected by CORB without any kind
 // of confirmation sniffing.
 protected_mime_types = [
   "application/gzip",
   "application/x-gzip",
   "application/x-protobuf",
-  "application/x-www-form-urlencoded",
   "application/zip",
   "multipart/byteranges",
   "text/event-stream",
   // TODO(lukasza): https://crbug.com/944162: Add application/pdf and
   // text/csv to the list of content types tested here (after
   // kMimeHandlerViewInCrossProcessFrame gets enabled by default).
 ]
 protected_mime_types.forEach(function(type) {
new file mode 100644
index 0000000000000000000000000000000000000000..28e41f5cfb39a864dde00ca1e5ba9100786d062b
GIT binary patch
literal 1308
zc$_QucXRU(3GruOV3lFuW&i>n2?j<6tiajLO@V=dc?yvEj)8%(a|&;}w3}OqF9QQh
z3s6i7h-EtEboG24Lp*?D3xNDWpt=YqHtmQ0!TLrZHc-q4h!ccv2yi9mCKdqAa{=<r
zfpSg^yv)ZkQWH~vY!0B977&{W{`HW}015)dOrUnCu!J(d&d4pP0J>QO$OozAV86h?
zkegTmG><U=$Y%p%rT~V##N1S%7|_j(Yk@*q4a*#h3-XIgfcDk^)rbMH!v8h~<BB=S
z2`LE)43B($AG$yOnY+)Zz<57Hm%*Jg`SY56oEh1fg*%uS942!fU|@i%tvh(&zyxMB
z$A*cFq6Ul%_Bu@Npilx@&jeAESa;B(v2ki+<IMJ(&5ezTtSxCp2^-Q(m@o0HnZsjn
z;6wwTl!S<c$c%V~NK1*V1|yyxhKyP^px&p!-hQtQL~JvIRoE1!J>V4L2~w4HIl!YR
zVY5}Xtfghqkz5_8n44}BIJpxJvF&QxK4W|Dc1}N;>7oV>N?}Fk_u73=zt3QCEZ#+8
zUho;_z70KoOmYv+e#w83$g<(IIA&zWRnav0hwcMr9d*u`fi)g)`@g>`Y?1XjpuESO
zpRxaA{uEZ3Wb<o`{tAzNH}G%hwl84r)wOa9ys@CI`GBO?oZxd4l$`yxI2@citH|%I
z)HLtOOZUVIZa>g_ugonsOa0ubVngrEF*;n~`p+KSii%xzNYnS$tesrH-u)E{nJ`7l
zf6ErTMQY0zrA0<Nd%HjRk$Ymx8fU{UW#`AOa+a^(ggZT3{e9KR+utYGzLm21&2i3M
z<D*CX%j%oO8_Zm9PM;aF>8k%K-8p7cH{D+LV$Ex*%<QdYQ|mH6oA^$C6nZo2n{N8v
zta;KevqJ5*UAlFzY5tX4=A|Xi_0LvjMznuvHcDk{)ZS<Rv#On|xJds8-{abo(@I{y
z+j7&xaQ3oCUN!Fp3=-zWsQi)FtH1eS{fq+!2QRGp;Av#9bvQLawKvsn;<B4t>{s3|
zwVOZJJMudNB(4(@(i##Z+1%I!HZXpYI9Mab#;S0ZsYPMmq5uB{KK*xI;l<`=#wH=G
zuApLng^?jLk?k^AUm8R6|Fb-94qX!&c^McqLK%00%v;-k(Ce^+M9Y8s&afq0wAQl3
zC~9;lO}*m${?XM(z8`j|M3)=BoA#!QZBIpC|K-<lHqScER6FjLzqpf@(3UT-h(q9G
zVc?}R9IEP;lVACIWQEM+-m8<b)Hl@N?9oF{UOAt;WHR@H|3XV){X0H;b?<Yh?Klyq
zdij=m1EWIBZp9tKB`O8W7j`e6Z+A`ltw4>GPy=(*`F56X9Ch-JFSx}M9(<3}U46-4
zefrJNqS=1wC+A4n)qA|#5;k*zT=DK5(RTX<of<02;-ardY}poj^Mc&^$KRgm-`g5%
zUgo>|)vS978~#aMeY|V`e||%g_Pem~OJQir{<bRK@yppi&nyk37(Bw+{=@UygQSWB
zD~<~sNH|>8&d4((-avre&mq%S>53mvYtP~JE_)ab9(%>MK$6ETpy!O+;hsf2JoW3D
zZkqAP@FY1zv3eLc`6jS9hs@&=_-w#o=wWc;VTqK>QjUODt{F$!&BT?s7Ee@QXtv<x
L1jZ-x3kU`PDVXnv
deleted file mode 100644
index 3d90e64302a7d0d9708329ef41ae62d441c53e04..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index 0000000000000000000000000000000000000000..f0e0d5cbc2befa80d41c48ad9794e4aa431736b9
GIT binary patch
literal 1272
zc$_QucXRU(3GruOVEMto%>V@44h)P8Sb?*fn*sv^a}ALBgn@xEb&7e)TQ|25U!dLu
zpqLa8%XG@=>iIf`cmTyf>I#ACBAD0|H2s71jX-Rmm<<po2;C6iO3qCz0Gg)*<eLNK
zoEUhSk7cALrU2O-Kru}qHWU2oA)5gd1d5qJ?NDI}WqzHJTT%hE;{%WnQp>@9fq@}6
zu>xowV*rrP2F6SQ40(yUsX(zQKs=R!fwgSI@BHfp`Nbtbdx7>ahyk&}|278WiaE&%
zDG3P-j}A<exL#2=dp*ycGx`lmJm#NgKUcUMaNytpmPHIww>h2xH9*zY9XxPg0<)T9
z!$d|=14agW9VT~BC;_c!f~ZNXJ803^IJL2HX8X<N#>Pa}mb9XT4QVFKmw499;W0RH
zqJd9JLPSDjMm$5Lr9@VP5l;_8MlBmq@7<t{euoVNYBRZnxE~4cQ8+k3OEbtdaghhl
zirC$TE-P<GIP~NwC$u;6C$`Sbf8ZW5<K}~#hJPH`1Cm|8*L;8X?q)i}><YK0Z?}(G
zJYrF<al3QSpt95AXykLvM|y5AlaFNI@UmBmJHFz#L)xXg58j!iRL*%Ir}l`?r%0l(
z>-rPhM|$rrn>;e@_@eu$^w<6Zo?h)c8@moMnaZ$~1td=2)-S`#<{~_$=gOAkcYO&v
zO(L~^h!!%-yk2d+SZu4X_0@GRo*#Aa@e21p_UJ@Z?8-};zPIM=^?LU2N$L#8OIb0O
zF1K{ek~v-1m2-T@F<#~BE04q7&gmx4Q>-r)-yhhV9b@pwsg>*bnW>JS`Pqwu!{YqR
zCim_O@qM{v<JMWbXYR}V_Q~e_sp!<~m;J#%*6!RlVO`kOO69d*<^Ht3QN1#+<#gFW
zsc+K~57>r@T0HnKf9#T$<b>Vl_t(}rdtL9fzL=)yx_^2%^Tt0PB2p&2O|MyeShQ+F
zu-I3l+sPdPJ2;f{^u>cSb*ejT^sD}fg*|_Bzac|Y9~$oo326-pl5B2l0vi}VNgS*Z
zV`Eh~%haN<@6iAM0-ydnukd1XGh>qwR##B5zrx56naFk-tS^nB`TtoSH;1l?jJymC
z8lj9k!RDnTBqk=Lq?Gt+d->>{JahiCujkp*=g*$;);X!Kb?$_Zw&zLx^TuWd1{ZwS
zoX|Pvan|R&h9OH~w^wnHw~^80&7Xt1yB(EydVF|#cy8JMkgW4C{x>1<m*VL^&P_|(
z+c!#cM5Ide{z#ROU`dhiWlfc^NRdcxm6+iubw$ERBFyr+c!*eIPuK;IYas?k1}4ED
ze05HK_!?NCqj%2#oDYj-Z;^V?!O0E>P8>LLV#Sg>d%quFxwohK`@cJzrdO`Nq2D>b
z>c7g3Z~uNO|9X7oyl%bU#?K%Bt`dAH_V(FBCWf`z<%c0*mcr1K{cTme<Cn94o>>}5
zF?fWt{fFnH2T2tNRvZ^NkZ`!Fosnloynz6_pF^gv(iK0T)}F(<XZJEs?Z3+FU@XzI
zKw@TZo209x#J@P!O}P>l5=R=ga7{>KnSFqxZH0}f!m~tyqzMTV4!^YN@Dg0WC2G*k
XpQGm@;->7#ur-9&6&Q!iFCZ8I$Uy5n
deleted file mode 100644
index 0b7efbaf70647351f336fa5bc416fed4dc856593..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index 0000000000000000000000000000000000000000..d6f530d8e104b880d83973817c137a9c69d0264c
GIT binary patch
literal 1292
zc$_QucXRU(3GruOVC7-pW&i^23k-}5Sb?*fn*sv^a|e+5l7WG-*5jV%SvR*3Uj_!2
z5}=qA5X*GR>FW79hIjzQCII<`Ky?vJY%-4i!TLrZHc-q4h!ccv2yi9mCKdqAvjFnV
zfpSg^yv)ZkQWH~vY!0B977&{W{`HW}015)dOrUnCu!J(d&d4pP0J@n4$OozAV86h?
zkegTmG><U=$Y%p%rT~V##N1S%*c2dM0#yI5!0SnQL4GmNz05$h3}Qg6@V|}0xMEIn
zLP|mc!=p1Vvx^`9%-v^HV7#B9%izwL{CUkj&W!BL!W~Qu=4zZ>3=B}Ubq5a|n82*&
z*f5b%)PRw}UWdsY6iPtrnILKs>ke8pHcoA9oY{V}xv?>kwI!`6VMCe;^Cg}&b9f96
zoM_;ak`R#)nGw$rX(^G_V8qkIkWtG9)cZ8Z*6*-^L~Uj;3wKiL=Oz}Rm6P~HOIA;i
z@H*XeMbvfW?Fir5C(2Ye6}8Q4ZZ2R<W9vI`uKRTn6C2A$8T<OW`{y^?GaRpQY`9zA
zw(&Tl+rfp$b$Oc2`)^NJ%ir(ZbL+iad4bTq>Y9eYAD(Ffa)staalCvRTEFdReg5F!
zW3#yE<#O#ew!OD`=g=};PCh}}?h%`+)|H+`8yxt!8;etRJh<iD!&1A5GictEnB#YN
z6D_<pP1&sd$h06hY-?EeovzPsoW49-qOZ2{ta`Gc$+9ycS)rb{=Ijjm_3p3IIo_}d
z=khWy&-i#|!@8zvvrc@9pO6^QoW$bYf9mS>o{lx@&nHgae0^fg{H#sV`LFjF>&y(a
z;;rU;W_5Pfr$t}WR7<nGZG)F-UAlE+*95ij;@vB&3T511PBz+^lcIJuET1d0c&hI8
zOEZo&-B)<d9&%^b@r`*`*EsHKdttQeK*MKqyT|J`+3gIUv-{iLWmAfB^S$>@SaiMj
zsKcK-$;J`(ySi??zW#r~#^rupA3wEtPuMZ-My%bkAn9j9g>y<~-~Rc#{1fZCo8C5{
z_)SPiYe<k}b7K?O!1zhxV2v0XtHN2P7KMF>{{I*F^xt`f7n_?In}o2sf{OhWMux~l
zw#(pjk;c&c|16K2L)Sz`UIqq@P{y60^s=@;-s`Y~#F72_o%Itgt%~5>;S?a?8g<F;
zhhA;=Y-gRq*LufP-sBx<Fz-12a`Fc86P;$N9e1ru?xiKP-B(~?RCtu7oVm(%qW`B?
zlRZ~)|5OW^c`@pxRdQE%@48c!GRK8~sfwgOn)`a@=1r$&JX896VrGyY;}?d9H~S9U
zTcA2`@7G+3KRg?5zV3KX<ic={Q%#)3k27rggWZRir+nD0aVl!p%NK^VUC%zgQT1B!
z?4(sy=qeA^(vEg#+XpZA3fLUk{rlLBYYPnTUi<N^O1$jy{tq|4{JpX5?zVjYw!?S7
zhZ^UxrT<UA+jN@&k~b0(QW%=DzpaXQ{BrisGfM+029I#I|M0x^AgSWOisJ$Y5)N0j
zGxE%cHxOX=bI9~ny5a}a+H+X%XdPoP&uZz0Gy@4oLnCQk<1QnEKYO`SZW|OBbTDR$
zDxBpoYZT-OtkiNib6DYs!a;@h%U=biDmjR1C5Xx2i0RPiacg2Yv4J-d=pN=55DWkz
CeF5J9
deleted file mode 100644
index 920c81eb1bf7bf82a613c4aa27972a09765f2ee5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index 0000000000000000000000000000000000000000..d26853979607b2772597b8b9d5df28d3f45dc957
GIT binary patch
literal 1260
zc$_QucXRU(3GruOV0pv9%>V@491M&MSb?*fn*sv^a|w|7fPsNAM#g9JJU6!xU!dL)
zpqLa8%XG@=>iIf`cmTx;fc!$Bx(FsV`%M2}eIpPXC}so12|_mnxRP@dfohmlfP8bH
zoD%~t^RbN7#1tT#11P2i#AbqjJ!CV0f<Q47s2wUSq0Fx{a!V?Jc02*{L25bJFEB9V
zCRPB=V+;WD*}#}7fFUn2Hx(#01&I3@7+5_WtDQF%<QD_|z#IcqBL>6@|JxXhE9N98
zq$DITB(<K1Zu<DgEM9WQ%y<S@iM(g#=N*?VY-n!ebYWx=&*HekzyMWScksZ03CwDa
z4HFqf4Hy~hb(q{ip#-#^38E&k?x00u<J88+ne8{58ygc@ThfXWHl&#_U*cIahsWT+
zi3UC?2@wgA8SxB}mJ(SFMm#+X8MSOcy;p+_{g@2}=A33#kvbxLN5QdhqW)3M3oaa;
zOscx9A<HKVN2}~S@y+wX6ZSuile)UXKQMCHIh^I5Q7rSqkty-?r#J83RJ}26h_z8V
zSoJ1Zq_9cxp7Of|9`BU>3UBW0-qD@7O8MTQxL-0K&D!p28%=)4xAyadtB+W;Z**AC
zQ2pBxY@@0#SibSq9@jmr6YX5~^oIWG3ceEYXj&-GvI`#sEF4;$-_?3N(dam)A$jqR
z`xd_k7TKG8K1e@eEr`<3Upq5PpKq1(#p#ub$Ch4yJkg?X-8!F_zP`6w(x;xe`y@4n
z_gTQf_b)fEStmL7Le>hs=Tj2XQtlXBI(BvWqxCCP>yLHt{}f#p8O^#?non)pnkdDa
zi)Ly^|GH(BtF|xl+0H3O+W9?~SM7B*$Tbd*oBgV4;hb#SAF*5Si&l!wyVid9Q-bKN
zo5`My$?Nv#9*S~yeAkfu_iUfWuDBnYZ~0Aq@qLMfn0=0@w#ZF|$L==2{_lUMq){5U
zmm~D^g$rMsA2~%HXKtBNxqk1T{rf+$oAO9K1jl7ULRv$DB%2$Xzy`)o5(jI<*jN?L
zGPNk|JM{m*z^DJtE4<j;%-AG^)fH6iuP`!1CbC@y>q}#3{(qLo&7o@|BQFDkMkwP>
zaN0;oNK8yfNh$Hr_VUp?dFK4(v)X5Ub-i>>>T8`l;iIjoYhYqxU~s{A%?X`z9%p^d
zYcLjfdld(H8yQXB{5hz*+fj+9$A_nf=a&5s$vO|?e-jdaDW3l0+_bd4eWNr-M5=`8
z&r}HsmK2FnmQ)Fg6ba`Ri5ZSkS0sWYr&&A~4-sqZ3A^BNEyTdcz$EyCug=L2Ujqwt
z^v?O8^I_T9?esnHm8}9Wi6^Cm1iicW`|*{yV|%OX^KPEr6aHrU5&ymQLOIp{{|Npq
zeD!>q{qh?>f7D&=DCsWyT)@b%E~+>k5?(0`P1)a8#XEjE`{$XZffR#BINN`C-g%Hz
zabU%9fddJLtJ)cPX2cr^u=_b=`YK)V18VI#EOPBvW2|MEIm6imgQlbuGpRI@)Px_^
zq9?W`K1dK?zNF<aOE8B?Sz^(rkcJuUjvbCoj(p2sD{8qmXoVcmvD>gyAW)*0g^_D1
M?-F2+WPSm`0PFtVt^fc4
deleted file mode 100644
index 3e70cd29a344d195edf4ded1cc67ced91a23d2e1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 7a9dc5d4cb1bbc758d2ecf34641e331e9ac7acb0..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index 0000000000000000000000000000000000000000..d8f8ae48a6d4c24ba17ed9185b769a8956418002
GIT binary patch
literal 1244
zc$_QucXRU(3GruOV7bG<%>V>kJ`9WuSb?*fn*sv^a}JPsi-CdBT4XWb4L7$CU!YzO
zpqLa8%XG>a+4(w#0QoE_Kz=SzT?7-G@_qkceIpPXC}so12|_mnxRP@d3xMXy0Qu%X
zIVT2Q=3^PDi9mgf96&KGAT|^H>#Lgq6a<QyK<!Xr31xnrky}y$wBrhp4^qp)egSA%
zVg=AV#sDCn4UCxr81fQxQ-NYrfVdr~e(mRF`Tq*?i%Wp^h5*%w0kOjWHU{I0Imrnr
z2?-33E+@`^cI5Nzn$!nrb&Mj3J7(Tr*5u>N$j&U>!Ng!A#%apH099Le@W6oy%xaDe
z6B$Jf7#Zw!nA}031hk$Bq9(EKphaWj)W*h{?Khhn8xvVu(uxu`q?s^Z;#o6?$Kb$;
z20keX5ebnQ@eGlc5?KvKJUt8<wQNAWXD9jlF&T;++dq?0$lNXeLT{%|+Zh3c1BZ^x
z*kK@0wkF2nfP?hEDL%6w#2iwtVBvoxY183tZ}pX7R>q8FFW;Z7e*ZfAH^ZFAyo{^f
zb19!^wEFQuW|3&dc|o;@z0akr9xi`wrMIZ_Ih)l*Yvtx!l55$gmp)+-YJD!ye{kt@
zj`asuKbK1R@n|QX;L&-~6D|tBTd>jHQ?ym|st(IKL-)zq(wsqGJd#tsc&t;7+HN2-
zEAZ6c@F%hb%fF{C47=3zx-xjn<SpvQW=?%Pafhkf`OvhfX)_Ytj@>a$Ix{2F(qvmi
z!0`>!c=s;t);ekFd1>>Ky$N?3txF@X7ar-UDT|y`c>nA2d)&#Je_GAU%>G)o@J!w0
zsmG?xzT>fV3wP~}(#a~Fo6}QM>U6A^cJ9}Gx%}vz-Ltpm>1s^d9iAEJm2l!`e0k*C
zYsn$=H^1s;Jbl@^dVP1O-mSGRJV*2M=49^OA-_46P5r)fu$SnRHBxaFE3eqPmwL{4
z)|xoETg5Z__~yC4I`=WWy#Lz_9ES-BX$=XIY;J4<8yG)H9IO#zV^uiI)S|HO(EtAe
zpZ+_q@M3c_W0Me8S5UFP!pIPr$aWd5FO8x3|5+Y4hpvf?ybKH)p^Q7hX(A;dF)<+}
z#Y9)n)92hZ-&6XUC(rwy)X_WPxkg8C<rz=ib0>VXJx}VNH#RjexZu0ygw8pSvp(lF
z3|WdKC1y%UNN%bBVEku7+8@QkU!14?Y-jQ2=T9~l*l^0A=)-9P1CA30Mck(h3QibE
zaT^*mo2)Q&G5lirTs%aqktgVa$F&dxBLkD*5577lKYR@=(9t{Rf6hne<eBrz#{*L;
zSvVvlXGlm+owED;KZ~u?3*X<HAN|efz36Y%kHPQfv)sOCU++>s=hx1s=QYdh_Qjhj
z-CcCoCWc{dWo94)G^|n>nzFyGig)~S_K%sU1TTa0X*N-KetD2oabU%9fddJLtJ)cP
zX2cr^u=_b=`u;i9V%=fF&(hOSAvL9KV<JQB9S-X>k<^4A)uJc1B|b<HV7{c~FiS9p
xNm*jir;vsj?T#IeO^$raS1V|_HfV($(6QUFQy@^HmxVFy6VHEO4rG1-!2o-O)R+JO
deleted file mode 100644
index 8761585484b83e3dad6488e99340825bcdb872d1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index 0000000000000000000000000000000000000000..a3a491dbaf1f066ee4d564468c6107d324d9a988
GIT binary patch
literal 1208
zc$_QucXRU(3GruOVA;XI%>V?PB@B!VSb?*fn*sv^a|n=mo`Hc;{6e$IA2+uUU!YzU
zpqLa8%XG>a+4(w#cmTy5fc#vbx(FsV_2d4*`bHo&P|OC16NGLEa3$v^768p-0rJg(
za!w4q%*QfP6H|a}4xpG85St19_0`P)3IfGUpmwORgfhR*$StV=+OYx12dU*?zW}r>
zu>xowV*rrP2F6SQ40(yUsX(zQK%57(>*tB=kR1j2#U(&C$Q@!ptnj~$!MI{hazaW%
z0>h(Fo9$JPe&+5oDlp#9&}DGvOn$KAvV{%Jjhrrw3`$`fix?Q7YU>UjI52@(&9Px3
zqo@HRgS`%uJ1CTZ)-yrWB-S0YXl$I?*f_KOW^-d>B5O-pQNo5a6Xr`iYv%A695~Uy
zCnX^wAu=PLA<|MJtHFq;hasbu4XF2MkZ;x@2a$h5^$TWSQs!}T6rb4Hy5QZBM~gIe
z6v-!>G{5jjbJ**Ue^L7j*WE7+wvPE1tiO00y}i|%(DtzQ{n_t(zkf<&xbs+6Zq<9i
z;C9<BA75_hpZ5Jp0dMmA+Yha7?JM2U$o~KEL$zC5#b(C+?Yrl_QfouIWl?*r&Ew+_
zrQ-Is9xgre*FKl|P<`=^lRw0dU9fm?Mu$r}WrM&QW5@Pw?41IF7kLc*jc#e~737(&
z<~_C0br1WoUj^r`s%>60x5UN2ZQ_ihX0v^do{*Tk;)a&*tc6O;%DNf6wREQ+>-*R<
z^V*lNFa2jEHr8!q`s8n;E%CB`{zB{4jfI<dr`?L$YdkaR_Efuf%9^PH^QWA=v}oxB
zy>-FwCOJ(mQrfn~Qh3QzligFed3LV1ZPv<m37fxr*LKF+7pko<{!|m)yH3Qp@Z}PZ
z-ln<(+A?>(>=T>v+$Y%9An?@TqMob%$rGQo^?P|pmUZvTzxh@_^x5&5khn@nNNY%t
zWOHK^*ueNn;$V#!8>_-urWS>LhyMQ;`1Id-g%_Kf8JmQ#x`K-R6-I{0M7GOdeQ6BM
z|IhNcIdn~A<Yi#c2xZ&}HZLV1F)<+}<%*7;r_Z@-zNhpxPoCF3cfv>8^Q8WHV`Bq@
z3%+Yk=$!L7>vLYikflgcVy1+I<d*sm#(yTH{ZTyp#d+G#b{21b{$z834W|rj9!^h8
z5SWlyp{H^9fa2j3`bQ4%Tv~AK!SR4+bK(OcS&Td!l_P@>o;Yy9=b-sUmBZKF4{qFH
zVQ*=?QN`H4KcZdWZGr+Y#U`bM1iicW`|*{yV|%OX^KPEr6aHrU5&ymQLOIp{{|Npq
zeD!>q{qh?>f7D&=DCsWyT)@bXd^y??8a^ouP1)a8#XEjE`^QXFf|tShG@B?qFFZ)9
zII!Zlz=4FrRqc#CGvW;d*!>(beeZZ3;qEZuX6tFFkebrAF_9tm4u^G`NNU25YS9zh
z5+5W8FkjMgm?fCQq%5)MQ%J*%cE=9KCP%*Is};0d8?-_W=-6%8DG(^p%fc9D$MYJP
JyO>`<FaXVz&OiVF
deleted file mode 100644
index 96ebce2da516621dae35145f49245bc490deb8e4..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index 0000000000000000000000000000000000000000..bb286182e47cc5ba7142b78425c5652fb74d6dcc
GIT binary patch
literal 1228
zc$_QucXRU(3GruOU^&CU%>V?P9~c-JumWc{Hw6X;<^&+~8Uq8PPO&LRf}2~2FHo-q
zP)rJlWjf`I?0g+VJb+>$Kz<%jT?7-G48MP{z7dEG6te;11fd%OT*<kK1wiuzfP8bH
zoD%~t^RbN7#1tT#11P2m#AbqjeRVT{f<Q47s2wUSq0Fx{a!V?Jb{qlnL25bJFEB9V
zCRPB=V+;WD*}#}7fFUn2Hx(#01&C{a>XUqIZ*&&q7ncC-1-g+z42Tu}w=o!3%t=m2
zNl0LL6d~5$Q&Bg2J<pvp`VC4v=AUneOvu!DkdVL>$ndF^y&tFns<!Unfddnm)f^ip
zGKv~7GT7@dxr0IpXgw1|O=8_ai^j&Ojg2$gZ#FkJCbG7q6(wv)Ghx2Ovt|yD!GRME
zd{Po35+XC=86qtuvKowddKfZl*?@Y_PV&z><REfvzlv5#Fjwok^ovb;i#nTDSPSkF
zxLfith{JG}qoJa4)6LS0%3oymI<LPl`wQD&qnUCCS|9Kn{=K)d{@K~tj0OGr7AuZ(
zi%paL@*(-A>+#6QZwBS_b<8gm@7Fc|_`o(QZ{hRW3zswR1kRqlqDyv7U_{x+XFI0Z
z)>yrtCLOVR;#0Mj-`P7`w|?)DG<u>j(>1AGM2ac*$cun)f(l0_Y;ke%_S(6?to6~E
z7piCXsmM1*PMh9(XKB=y$9*r@9|q_s&(#x8S`{L8+T(OjUYDR?^7jv(S6@n}1x#Uo
zH~m=LB;g>h)6;%+USnLna+&}7&7B@EKgXA5tPQa0`o8bnr{0jCids|k_&dFxhRy%v
zD8N!zGEK{Om6h|V9d5khbN*#jE$`Ktp>A0F-l+RP%j;ctSDlx*lzk+0|MwZLsqTMg
ziSBm!vb%9c2Y2<Uj)nH0elj21{{4=2n&ynP|F#@T;q*QHx-DU<NSAyli{p*8dd0=z
zKbYMOp6Y?(Eg>PTAwiPOjZI(!<0pxOHDYY63TK&G6!snZ|6kzKf9DlmY;I<362j^V
zD)v_x86p$eE`#GcjiLGfSspisu8EAi3=A5fj61>UASEF&F(D<zL_^Qh=iD{jllmSf
zb@WbnuF=t3dB#)s+zB6TO<e;s1A_~`Yfk8#^Em5sUc->3NK#^^goNal`VYo`CZzpQ
zJp9FZ+Rt_tZ+`w{bAb(~4E{Wso|qsoA@PT@#^D2shgT>aIlyyi!7+hT7aq-t4~S$j
z@^Dm+3_f_`zy+U!<{MQGUw1#aafgMyrSV1;WBY!W?-O3tC;$_2Qc6hByL-PMUx_=m
zx4J&>=IK4*Z>Asd-&-$~Q~m#s;NQYm&!^chzwz@&-PMkg?y}DXj0}wrQcgnBcS1r6
zLsRy*Rq>8r&i*kImEdJ?KFuZy&mRwxDh{kTE^r{>a8)}a&y08j0d_x!Oy4(`?pSx2
zuuDoXel*eGO+L)9YlmRj8I4m1K77}jkbC&RK?SxYp$#U=H(1;ZT%N9EFywC*Xl7}a
i@e6kh>0$_7(GXdaP^`GfK#G%zVbUsIbzn|@0l@&#Hq<r%
deleted file mode 100644
index 556226f12265581701190efd0bd198586ee55139..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index 0000000000000000000000000000000000000000..52bc04458caae71c2ef71250e4c0fd9ac4290726
GIT binary patch
literal 1192
zc$_QucXRU(3GruOU|GSy%>V?P5)6zCSb?*fn*sv^vj>oQih+TVLo?RW&CM;u7pPYR
zC?*BOGM#cpcD{}wKs77|Kz=SzT?7-GalL=Az7dEG6te;11fd%OT*<kK1q=*KKY)C5
zpqvu}FY~dC)Wj5!*+4NZAT|^H>#Lgq6a<QyK<!Xr31xnrky}y$v||B~4^qp)egSA%
zVg=AV#sDCn4UCxr81fQxQ-NYrfH)cG_H`-zCnXE=i%WoPko&}dSmA#ggK@>2<b;%j
z1cpb=f5KHB{mk8GRA9WHq08XTnfzeKWeXdc8#!GV8HB1ioER9OYU>UjI52@(&9Px3
zqo@HRgS`%uJ1CTZ)-yrWB-S0YXl$I?*f_KOW^-d>B5O-pQNo5a6Xr`iYv%A695~Uy
zCnX^wAu=PLA<|MJtHFq;hasbu4XAhTr2Sck4FrzaTh=e|ei@^|;iM=j^M*%_Z;Jqv
zoY$r_^JAT^3P#hII7?n@f3dVGd$D=SKG*Mc+gz`UMI|M^E5B5`e6k;d-bbd!Z@Z6P
z+IWB=zt8qgNA_{qJKf>OV|n&iAGeLE^zZvUr#^kji?|Eb86l?JDl25FXFNPy$ljmy
zYDc$AjnzBHs+EuJgx*VXXH2m$>^>yMs-x0&!eG%{1&5A~El#JVHkEni^BrC&xpY>g
z>pf=f*m+u8b=SzGDO++L@>mxXy=GcbUeCFZtf^@;7Ah?*W1k=LK5s^3qVszP{b%dG
zevmAEQnPnfeYp6pP>I=T*7sjs63I&DPnBV5oG&+3^V6=j33~q~{ck_xS)6wJM%S%9
zJJ%adom4yFf5|Dc@FOcU|8J8wG{0Uw`$g95(<dz^82{|voe=WGzqU-(E}#2aNZ6SR
zc0xBb4nJFTi#cg-cpJYno1?`#Zrkk2_}=@Q4uRt*At9|HL6XglO<)7#Cy9eKVr;Am
zXPH_Q_8t2FU*OY!=M`RTZf0x}!s-et_E#7gA`{szgY~5`H2*)#<L1yck&%~yK_irL
zCpf-S5)u;=Qc^-R^*nvfUDG|OuW{~#kG7`n1``8=3%+Yk=$!L7>vLYikflgcVy1+I
z<d*sm#(yTH{ZTyp#d+G#b{21b{$z834W|rZo=#6p5SWm-Ls8@K0mZ{76pkF=xwPQe
zgOd{;&xsF+WHIt^RE`Wjc;dhXpM&NbRSsWwKe%y+g}tTmMipcGehzbi$36<c1e%l*
z67=rg@5fi-j_s|k&%1egPxzbZNBsBJ3*}V*|0DRf@YVBa_RDYl{84wcqolj+a{(hm
ze{{$x258u%Ff?U<TNUs4<?J6bQ3+lK=hJMW@U;IRsp7zj;{pc~4p+4^^2~@g5McLn
z$n^EmOyyNN>%i{jV8iQm_=Z7)US5l=ahH+7pS@fuw+#vmIv6uW70z;)H45?sR%$t%
qIjnF*;h;kM<xqjCN)Do031ad$VmdT>+?p8V&3M)Wa})Cm2nGNNf3Z0L
deleted file mode 100644
index d036e893087cef4dc4ad62681b968f9ef75be9c8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
copy from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html.headers
copy to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/resources/echo-iframe.html.headers
copy from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html.headers
copy to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/resources/echo-worker.js.headers
rename from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.html
rename to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.https.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/broadcastchannel-success-and-failure.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
rename from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.html
rename to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.https.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/identity-not-preserved.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-sharedworker-success.https.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+fetch_tests_from_worker(new SharedWorker("resources/nested-worker-success.js"));
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-sharedworker-success.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
deleted file mode 100644
--- a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.any.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// META: global=!default,dedicatedworker,sharedworker
-// META: script=resources/test-incrementer.js
-"use strict";
-
-promise_test(t => {
-  const worker = new Worker("resources/incrementer-worker.js");
-
-  return testSharingViaIncrementerScript(t, worker, "parent worker", worker, "sub-worker");
-}, "postMessaging to a dedicated sub-worker allows them to see each others' modifications");
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.https.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+fetch_tests_from_worker(new Worker("resources/nested-worker-success.js"));
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/nested-worker-success.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-coop-coep.https.any.js
@@ -0,0 +1,18 @@
+test(() => {
+  const sab = new SharedArrayBuffer();
+  const channel = new MessageChannel();
+  assert_throws("DataCloneError", () => channel.port1.postMessage(sab));
+}, "SharedArrayBuffer over MessageChannel without COOP+COEP");
+
+test(() => {
+  const sab = new SharedArrayBuffer();
+  const channel = new BroadcastChannel("Is mir egal");
+  assert_throws("DataCloneError", () => channel.postMessage(sab));
+}, "SharedArrayBuffer over BroadcastChannel without COOP+COEP");
+
+if (self.GLOBAL.isWindow()) {
+  test(() => {
+    const sab = new SharedArrayBuffer();
+    assert_throws("DataCloneError", () => self.postMessage(sab));
+  }, "SharedArrayBuffer over postMessage() without COOP+COEP");
+}
rename from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.html
rename to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.https.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/no-transferring.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
--- a/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html.headers
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html.headers
@@ -1,1 +1,2 @@
 Cross-Origin-Embedder-Policy: require-corp
+Cross-Origin-Resource-Policy: cross-site
copy from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html.headers
copy to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-sharedworker.js.headers
copy from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html.headers
copy to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-worker.js.headers
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe-domain.sub.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Embedder-Policy: require-corp
+Cross-Origin-Resource-Policy: same-site
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe-messagechannel.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Embedder-Policy: require-corp
+Cross-Origin-Resource-Policy: cross-site
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-iframe.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Embedder-Policy: require-corp
+Cross-Origin-Resource-Policy: cross-site
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-popup.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
copy from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html.headers
copy to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker-with-channel.js.headers
copy from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html.headers
copy to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/incrementer-worker.js.headers
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-1.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Embedder-Policy: require-corp
+Cross-Origin-Resource-Policy: cross-site
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-2.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Embedder-Policy: require-corp
+Cross-Origin-Resource-Policy: cross-site
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-3.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Embedder-Policy: require-corp
+Cross-Origin-Resource-Policy: cross-site
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-iframe-4-incrementer.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Embedder-Policy: require-corp
+Cross-Origin-Resource-Policy: cross-site
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-worker-success.js
@@ -0,0 +1,10 @@
+importScripts("/resources/testharness.js");
+importScripts("test-incrementer.js");
+
+promise_test(t => {
+  const worker = new Worker("incrementer-worker.js");
+
+  return testSharingViaIncrementerScript(t, worker, "parent worker", worker, "sub-worker");
+}, "postMessaging to a dedicated sub-worker allows them to see each others' modifications");
+
+done();
copy from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html.headers
copy to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/nested-worker-success.js.headers
copy from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html.headers
copy to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/serviceworker-failure.js.headers
copy from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/broadcastchannel-iframe.html.headers
copy to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/resources/sharedworker-failure.js.headers
rename from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.html
rename to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.https.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/serialization-via-history.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
rename from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.sub.html
rename to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.https.sub.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-success.https.sub.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
rename from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-iframe-messagechannel-success.html
rename to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-iframe-messagechannel-success.https.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-iframe-messagechannel-success.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
rename from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.html
rename to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.https.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-messagechannel-success.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-serviceworker-failure.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
rename from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.html
rename to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.https.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-sharedworker-failure.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
rename from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.sub.html
rename to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.https.sub.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-similar-but-cross-origin-success.https.sub.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
rename from testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.html
rename to testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.https.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-simple-success.https.html.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin
+Cross-Origin-Embedder-Policy: require-corp
--- a/testing/web-platform/tests/interfaces/speech-api.idl
+++ b/testing/web-platform/tests/interfaces/speech-api.idl
@@ -85,17 +85,17 @@ interface SpeechRecognitionEvent : Event
 };
 
 dictionary SpeechRecognitionEventInit : EventInit {
     unsigned long resultIndex = 0;
     required SpeechRecognitionResultList results;
 };
 
 // The object representing a speech grammar
-[Exposed=Window, Constructor]
+[Exposed=Window]
 interface SpeechGrammar {
     attribute DOMString src;
     attribute float weight;
 };
 
 // The object representing a speech grammar collection
 [Exposed=Window, Constructor]
 interface SpeechGrammarList {
--- a/testing/web-platform/tests/interfaces/web-nfc.idl
+++ b/testing/web-platform/tests/interfaces/web-nfc.idl
@@ -28,23 +28,17 @@ interface NDEFRecord {
 
 dictionary NDEFRecordInit {
   NDEFRecordType recordType;
   USVString mediaType;
 
   NDEFRecordData data;
 };
 
-enum NDEFRecordType {
-  "empty",
-  "text",
-  "url",
-  "json",
-  "opaque"
-};
+typedef DOMString NDEFRecordType;
 
 typedef (DOMString or ArrayBuffer or NDEFMessageInit) NDEFMessageSource;
 
 [Constructor(), SecureContext, Exposed=Window]
 interface NFCWriter {
   Promise<void> push(NDEFMessageSource message, optional NFCPushOptions options={});
 };
 
--- a/testing/web-platform/tests/mathml/presentation-markup/fractions/frac-parameters-1.html
+++ b/testing/web-platform/tests/mathml/presentation-markup/fractions/frac-parameters-1.html
@@ -16,42 +16,42 @@
     font-family: axisheight7000-rulethickness1000;
     src: url("/fonts/math/fraction-axisheight7000-rulethickness1000.woff");
   }
   @font-face {
     font-family: denominatordisplaystylegapmin5000-rulethickness1000;
     src: url("/fonts/math/fraction-denominatordisplaystylegapmin5000-rulethickness1000.woff");
   }
   @font-face {
-    font-family: denominatordisplaystyleshiftdown6000-rulethickness1000;
-    src: url("/fonts/math/fraction-denominatordisplaystyleshiftdown6000-rulethickness1000.woff");
+    font-family: denominatordisplaystyleshiftdown6000-axisheight1000-rulethickness1000;
+    src: url("/fonts/math/fraction-denominatordisplaystyleshiftdown6000-axisheight1000-rulethickness1000.woff");
   }
   @font-face {
     font-family: denominatorgapmin4000-rulethickness1000;
     src: url("/fonts/math/fraction-denominatorgapmin4000-rulethickness1000.woff");
   }
   @font-face {
-    font-family: denominatorshiftdown3000-rulethickness1000;
-    src: url("/fonts/math/fraction-denominatorshiftdown3000-rulethickness1000.woff");
+    font-family: denominatorshiftdown3000-axisheight1000-rulethickness1000;
+    src: url("/fonts/math/fraction-denominatorshiftdown3000-axisheight1000-rulethickness1000.woff");
   }
   @font-face {
     font-family: numeratordisplaystylegapmin8000-rulethickness1000;
     src: url("/fonts/math/fraction-numeratordisplaystylegapmin8000-rulethickness1000.woff");
   }
   @font-face {
-    font-family: numeratordisplaystyleshiftup2000-rulethickness1000;
-    src: url("/fonts/math/fraction-numeratordisplaystyleshiftup2000-rulethickness1000.woff");
+    font-family: numeratordisplaystyleshiftup2000-axisheight1000-rulethickness1000;
+    src: url("/fonts/math/fraction-numeratordisplaystyleshiftup2000-axisheight1000-rulethickness1000.woff");
   }
   @font-face {
     font-family: numeratorgapmin9000-rulethickness1000;
     src: url("/fonts/math/fraction-numeratorgapmin9000-rulethickness1000.woff");
   }
   @font-face {
-    font-family: numeratorshiftup11000-rulethickness1000;
-    src: url("/fonts/math/fraction-numeratorshiftup11000-rulethickness1000.woff");
+    font-family: numeratorshiftup11000-axisheight1000-rulethickness1000;
+    src: url("/fonts/math/fraction-numeratorshiftup11000-axisheight1000-rulethickness1000.woff");
   }
   @font-face {
     font-family: rulethickness10000;
     src: url("/fonts/math/fraction-rulethickness10000.woff");
   }
 </style>
 <script>
   var emToPx = 10 / 1000; // font-size: 10px, font.em = 1000
@@ -172,17 +172,17 @@
       <mfrac>
         <mspace width="3em"/>
         <mspace width="3em" height="1em" id="den0002" style="background: blue"/>
       </mfrac>
     </math>
   </p>
   <hr/>
   <p>
-    <math display="block" style="font-family: denominatordisplaystyleshiftdown6000-rulethickness1000;">
+    <math display="block" style="font-family: denominatordisplaystyleshiftdown6000-axisheight1000-rulethickness1000;">
       <mspace id="ref0003" width="3em" height="1em" style="background: green"/>
       <mfrac>
         <mspace width="3em"/>
         <mspace width="3em" depth="1em" id="den0003" style="background: blue"/>
       </mfrac>
     </math>
   </p>
   <hr/>
@@ -193,17 +193,17 @@
       <mfrac>
         <mspace width="3em"/>
         <mspace width="3em" height="1em" id="den0004" style="background: blue"/>
       </mfrac>
     </math>
   </p>
   <hr/>
   <p>
-    <math style="font-family: denominatorshiftdown3000-rulethickness1000;">
+    <math style="font-family: denominatorshiftdown3000-axisheight1000-rulethickness1000;">
       <mspace id="ref0005" width="3em" height="1em" style="background: green"/>
       <mfrac>
         <mspace width="3em"/>
         <mspace width="3em" depth="1em" id="den0005" style="background: blue"/>
       </mfrac>
     </math>
   </p>
   <hr/>
@@ -214,17 +214,17 @@
       <mfrac>
         <mspace width="3em" depth="1em" id="num0006" style="background: blue"/>
         <mspace width="3em"/>
       </mfrac>
     </math>
   </p>
   <hr/>
   <p>
-    <math display="block" style="font-family: numeratordisplaystyleshiftup2000-rulethickness1000;">
+    <math display="block" style="font-family: numeratordisplaystyleshiftup2000-axisheight1000-rulethickness1000;">
       <mspace id="ref0007" width="3em"
               depth="1em" style="background: green"/>
       <mfrac>
         <mspace width="3em" height="1em" id="num0007" style="background: blue"/>
         <mspace width="3em"/>
       </mfrac>
     </math>
   </p>
@@ -236,17 +236,17 @@
       <mfrac>
         <mspace width="3em" depth="1em" id="num0008" style="background: blue"/>
         <mspace width="3em"/>
       </mfrac>
     </math>
   </p>
   <hr/>
   <p>
-    <math style="font-family: numeratorshiftup11000-rulethickness1000;">
+    <math style="font-family: numeratorshiftup11000-axisheight1000-rulethickness1000;">
       <mspace id="ref0009" width="3em"
               depth="1em" style="background: green"/>
       <mfrac>
         <mspace width="3em" height="1em" id="num0009" style="background: blue"/>
         <mspace width="3em"/>
       </mfrac>
     </math>
   </p>
--- a/testing/web-platform/tests/mathml/presentation-markup/fractions/frac-parameters-2.html
+++ b/testing/web-platform/tests/mathml/presentation-markup/fractions/frac-parameters-2.html
@@ -8,42 +8,38 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/mathml/support/feature-detection.js"></script>
 <style>
   math, mspace {
     font-size: 10px;
   }
   @font-face {
-    font-family: axisheight7000;
-    src: url("/fonts/math/stack-axisheight7000.woff");
+    font-family: bottomdisplaystyleshiftdown5000-axisheight1000;
+    src: url("/fonts/math/stack-bottomdisplaystyleshiftdown5000-axisheight1000.woff");
   }
   @font-face {
-    font-family: bottomdisplaystyleshiftdown5000;
-    src: url("/fonts/math/stack-bottomdisplaystyleshiftdown5000.woff");
-  }
-  @font-face {
-    font-family: bottomshiftdown6000;
-    src: url("/fonts/math/stack-bottomshiftdown6000.woff");
+    font-family: bottomshiftdown6000-axisheight1000;
+    src: url("/fonts/math/stack-bottomshiftdown6000-axisheight1000.woff");
   }
   @font-face {
     font-family: displaystylegapmin4000;
     src: url("/fonts/math/stack-displaystylegapmin4000.woff");
   }
   @font-face {
     font-family: gapmin8000;
     src: url("/fonts/math/stack-gapmin8000.woff");
   }
   @font-face {
-    font-family: topdisplaystyleshiftup3000;
-    src: url("/fonts/math/stack-topdisplaystyleshiftup3000.woff");
+    font-family: topdisplaystyleshiftup3000-axisheight1000;
+    src: url("/fonts/math/stack-topdisplaystyleshiftup3000-axisheight1000.woff");
   }
   @font-face {
-    font-family: topshiftup9000;
-    src: url("/fonts/math/stack-topshiftup9000.woff");
+    font-family: topshiftup9000-axisheight1000;
+    src: url("/fonts/math/stack-topshiftup9000-axisheight1000.woff");
   }
 </style>
 <script>
   var emToPx = 10 / 1000; // font-size: 10px, font.em = 1000
   var epsilon = 1;
 
   function getBox(aId) {
     return document.getElementById(aId).getBoundingClientRect();
@@ -51,23 +47,16 @@
 
   setup({ explicit_done: true });
   window.addEventListener("load", function() {
     // Delay the check to workaround WebKit's bug https://webkit.org/b/174030.
     requestAnimationFrame(() => { document.fonts.ready.then(runTests); });
   });
 
   function runTests() {
-    test(function() {
-      assert_true(MathMLFeatureDetection.has_mspace());
-
-      var v = 7000 * emToPx;
-      assert_approx_equals(getBox("ref0001").top - getBox("num0001").bottom,
-                           v, epsilon, "mfrac: axis height");
-    }, "AxisHeight");
 
     test(function() {
       assert_true(MathMLFeatureDetection.has_mspace());
 
       var v = 5000 * emToPx;
       assert_approx_equals(getBox("den0002").top - getBox("ref0002").bottom,
                            v, epsilon, "mfrac: denominator shift");
     }, "BottomDisplayStyleShiftDown");
@@ -114,37 +103,27 @@
 
     done();
   }
 </script>
 </head>
 <body>
   <div id="log"></div>
   <p>
-    <math style="font-family: axisheight7000;">
-      <mspace id="ref0001" depth="1em" width="3em" style="background: green"/>
-      <mfrac linethickness="0px">
-        <mspace width="3em" height="1em" id="num0001" style="background: blue"/>
-        <mspace width="3em"/>
-      </mfrac>
-    </math>
-  </p>
-  <hr/>
-  <p>
-    <math display="block" style="font-family: bottomdisplaystyleshiftdown5000;">
+    <math display="block" style="font-family: bottomdisplaystyleshiftdown5000-axisheight1000;">
       <mspace id="ref0002" width="3em" height="1em" style="background: green"/>
       <mfrac linethickness="0px">
         <mspace width="3em"/>
         <mspace width="3em" depth="1em" id="den0002" style="background: blue"/>
       </mfrac>
     </math>
   </p>
   <hr/>
   <p>
-    <math style="font-family: bottomshiftdown6000;">
+    <math style="font-family: bottomshiftdown6000-axisheight1000;">
       <mspace id="ref0003" width="3em" height="1em" style="background: green"/>
       <mfrac linethickness="0px">
         <mspace width="3em"/>
         <mspace width="3em" depth="1em" id="den0003" style="background: blue"/>
       </mfrac>
     </math>
   </p>
   <hr/>
@@ -162,27 +141,27 @@
       <mfrac linethickness="0px">
         <mspace width="3em" height="1em" id="num0005" style="background: blue"/>
         <mspace width="3em" depth="1em" id="den0005" style="background: green"/>
       </mfrac>
     </math>
   </p>
   <hr/>
   <p>
-    <math display="block" style="font-family: topdisplaystyleshiftup3000;">
+    <math display="block" style="font-family: topdisplaystyleshiftup3000-axisheight1000;">
       <mspace id="ref0006" width="3em" depth="1em" style="background: green"/>
       <mfrac linethickness="0px">
         <mspace width="3em" height="1em" id="num0006" style="background: blue"/>
         <mspace width="3em"/>
       </mfrac>
     </math>
   </p>
   <hr/>
   <p>
-    <math style="font-family: topshiftup9000;">
+    <math style="font-family: topshiftup9000-axisheight1000;">
       <mspace id="ref0007" width="3em" depth="1em" style="background: green"/>
       <mfrac linethickness="0px">
         <mspace width="3em" height="1em" id="num0007" style="background: blue"/>
         <mspace width="3em"/>
       </mfrac>
     </math>
   </p>
 </body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mathml/relations/css-styling/not-participating-to-parent-layout.html
@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Elements not participating to the layout of their parent</title>
+<link rel="help" href="https://mathml-refresh.github.io/mathml-core/#layout-algorithms">
+<meta name="assert" content="Verify that display: none and out-of-flow positioned elements do not participate to layout of their parent.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/mathml/support/feature-detection.js"></script>
+<script src="/mathml/support/layout-comparison.js"></script>
+<script src="/mathml/support/mathml-fragments.js"></script>
+<script>
+  var epsilon = 1;
+
+  setup({ explicit_done: true });
+  window.addEventListener("load", runTests);
+
+  function runTests() {
+
+    for (tag in MathMLFragments) {
+        if (!FragmentHelper.isValidChildOfMrow(tag) ||
+            FragmentHelper.isEmpty(tag))
+            continue;
+        // TODO: Add floats too?
+        ["display: none",
+         "position: absolute",
+         "position: fixed"
+        ].forEach(style => {
+            document.body.insertAdjacentHTML("beforeend", `<div style="position: absolute;">\
+<div style="display: inline-block"><math>${MathMLFragments[tag]}</math></div>\
+<div style="display: inline-block"><math>${MathMLFragments[tag]}</math></div>\
+</div>`);
+            var div = document.body.lastElementChild;
+
+            var elementContainer = div.firstElementChild;
+            var elementContainerWidth = elementContainer.getBoundingClientRect().width;
+            var element = FragmentHelper.element(elementContainer);
+            FragmentHelper.forceNonEmptyElement(element);
+            var allowInvalid = true;
+            var child = FragmentHelper.appendChild(element, allowInvalid);
+            child.setAttribute("style", style);
+
+            var referenceContainer = div.lastElementChild;
+            var referenceContainerWidth = referenceContainer.getBoundingClientRect().width;
+            var reference = FragmentHelper.element(referenceContainer);
+            FragmentHelper.forceNonEmptyElement(reference);
+
+            var epsilon = 1;
+
+            test(function() {
+                // FIXME(fwang): Feature detection should be done per-tag.
+                assert_true(MathMLFeatureDetection.has_mspace());
+                assert_approx_equals(elementContainerWidth, referenceContainerWidth, epsilon);
+            }, `${tag} preferred width calculation is not affected by children with "${style}" style`);
+
+            test(function() {
+                // FIXME(fwang): Feature detection should be done per-tag.
+                assert_true(MathMLFeatureDetection.has_mspace());
+                compareLayout(element, reference, epsilon);
+            }, `${tag} layout is not affected by children with "${style}" style`);
+
+            div.style = "display: none;"; // Hide the div after measurement.
+        });
+    }
+
+    done();
+  }
+</script>
+</head>
+<body>
+  <div id="log"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mathml/relations/html5-tree/clipboard-event-handlers.tentative.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<title>DocumentAndElementEventHandlers / clipboard events for MathML</title>
+<link
+  rel="help"
+  href="https://mathml-refresh.github.io/mathml-core/#dom-and-javascript"
+/>
+<link
+  rel="help"
+  href="https://html.spec.whatwg.org/multipage/webappapis.html#documentandelementeventhandlers"
+/>
+<link
+  rel="help"
+  href="https://w3c.github.io/clipboard-apis/#clipboard-event-copy"
+/>
+<link
+  rel="help"
+  href="https://w3c.github.io/clipboard-apis/#clipboard-event-cut"
+/>
+<link
+  rel="help"
+  href="https://w3c.github.io/clipboard-apis/#clipboard-event-paste"
+/>
+<meta
+  name="assert"
+  content="MathMLElements incorporate a functional DocumentAndElementEventHandlers interface"
+/>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<math
+  oncopy="document.copyHappened = true"
+  oncut="document.cutHappened = true"
+  onpaste="document.pasteHappened = true"
+>
+  <mi>E</mi>
+</math>
+<script>
+  const EVENTS = ["copy", "cut", "paste"];
+  const el = document.querySelector("math");
+
+  function addEventListenerTest(name) {
+    async_test(test => {
+      el.addEventListener(
+        name,
+        test.step_func_done(e => {
+          assert_true(
+            true,
+            "MathML Elements should be able to receive ${name} events"
+          );
+        })
+      );
+      const event = new ClipboardEvent(name, {
+        bubbles: true,
+        cancellable: true
+      });
+      el.dispatchEvent(event);
+    }, `math.addEventListener for ${name}`);
+  }
+
+  function evaluatedHandlerTest(name) {
+    const handlerName = "on" + name;
+
+    test(() => {
+      const compiledHandler = el[handlerName];
+
+      assert_equals(
+        typeof compiledHandler,
+        "function",
+        `The ${handlerName} property must be a function`
+      );
+      compiledHandler();
+      assert_true(
+        window[name + "Happened"],
+        "Calling the handler must run the code"
+      );
+    }, `${handlerName}: the content attribute must be compiled into a function as the corresponding property`);
+  }
+
+  EVENTS.forEach(name => {
+    addEventListenerTest(name);
+    evaluatedHandlerTest(name);
+  });
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mathml/relations/html5-tree/css-inline-style-interface.tentative.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <title>MathML 'ElementCSSInlineStyle` Mixin Tests</title>
+    <link
+      rel="help"
+      href="https://mathml-refresh.github.io/mathml-core/#dom-and-javascript"
+    />
+    <style>
+      math * {
+        background-color: red;
+      }
+    </style>
+    <meta
+      name="assert"
+      content="MathMLElements incorporate a functional ElementCSSInlineStyle interface"
+    />
+    <script src="/mathml/support/mathml-fragments.js"></script>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+  </head>
+  <body>
+    <span
+      >This tests the presence and functionality of features of the
+      `ElementCSSInlineStyle` interface for MathMLElements</span
+    >
+    <math></math>
+    <script>
+      let mathEl = document.querySelector("math");
+
+      test(function() {
+        mathEl.style.backgroundColor = "lime";
+        assert_equals(
+          getComputedStyle(mathEl).backgroundColor,
+          "rgb(0, 255, 0)",
+          "The applied background should be green."
+        );
+      }, `The <math> element style property should be present and be functional.`);
+
+      Object.keys(MathMLFragments).forEach(elName => {
+        mathEl.innerHTML = MathMLFragments[elName];
+
+        test(function() {
+          let el = FragmentHelper.element(mathEl);
+          el.style.backgroundColor = "blue";
+
+          assert_equals(
+            getComputedStyle(el).backgroundColor,
+            "rgb(0, 0, 255)",
+            "The applied background should be blue."
+          );
+        }, `The ${elName}'s style property should be present and be functional.`);
+      });
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mathml/relations/html5-tree/html-or-foreign-element-interfaces.tentative.html
@@ -0,0 +1,114 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <title>MathML 'HTMLOrForeignElement` Mixin Tests</title>
+    <link
+      rel="help"
+      href="https://mathml-refresh.github.io/mathml-core/#dom-and-javascript"
+    />
+    <style>
+      mi {
+        background-color: red;
+      }
+      :focus {
+        background-color: rgb(0, 255, 0);
+      }
+    </style>
+    <meta
+      name="assert"
+      content="MathMLElements incorporate a functional HTMLOrForeignElement interface"
+    />
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+  </head>
+  <body tabindex="-1">
+    <span tabindex="-1"
+      >This tests the presence and functionality of features of
+      `HTMLOrForeignElement` (currently `HTMLOrSVGElement`)</span
+    >
+    <math tabindex="-1">
+      <mi>E</mi>
+    </math>
+  </body>
+  <script>
+    // spot check the functionality of several interfaces
+    let el = document.querySelector("mi");
+    let mathEl = document.querySelector("math");
+
+    // this really belongs in
+    // https://github.com/web-platform-tests/wpt/blob/master/html/dom/elements/global-attributes/dataset.html
+    // it is here tentatively
+    test(function() {
+      var mathml = document.createElementNS(
+        "http://www.w3.org/1998/Math/MathML",
+        "math"
+      );
+      assert_true(mathml.dataset instanceof DOMStringMap);
+    }, "MathML elements should have a .dataset");
+
+    // exercise some basic tests on .dataset
+    test(function() {
+      assert_equals(
+        Object.keys(el.dataset).toString(),
+        "",
+        "The .dataset property should be present"
+      );
+
+      el.setAttribute("data-one", "x");
+      el.setAttribute("data-two", "y");
+
+      assert_equals(
+        el.dataset.one,
+        "x",
+        '.one should be "x" after setting the data-one attribute'
+      );
+      assert_equals(
+        el.dataset.two,
+        "y",
+        '.one should be "y" after setting the data-two attribute'
+      );
+
+      el.dataset.one = "o";
+      assert_equals(
+        el.getAttribute("data-one"),
+        "o",
+        'the data-one attribute should reflect a change to dataset.one and contain "o"'
+      );
+    }, "The dataset property should be present and be functional.");
+
+    test(function() {
+      assert_equals(mathEl.tabIndex, -1);
+    }, "MathML elements should have a tabIndex property");
+
+    promise_test(function() {
+      function focus() {
+        mathEl.focus();
+        return Promise.resolve();
+      }
+
+      return focus().then(() => {
+        assert_equals(
+          getComputedStyle(mathEl).backgroundColor,
+          "rgb(0, 255, 0)",
+          "MathML elements with tabindex=-1 should be programmatically focusable and apply :focus"
+        );
+      });
+    }, "MathML elements should work with focus predictably");
+
+    promise_test(function() {
+      function blur() {
+        mathEl.blur();
+        return Promise.resolve();
+      }
+
+      return blur().then(() => {
+        assert_equals(
+          getComputedStyle(mathEl).backgroundColor,
+          "rgba(0, 0, 0, 0)",
+          "MathML elements with tabindex=-1 be programmatically blur() able"
+        );
+      });
+    }, "MathML elements should work with blur predictably");
+  </script>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mathml/relations/html5-tree/math-global-event-handlers.tentative.html
@@ -0,0 +1,108 @@
+<!DOCTYPE html>
+<title>MathMLElement GlobalEventHandlers</title>
+<link rel="author" title="Brian Kardell" href="mailto:bkardell@igalia.com" />
+<link
+  rel="help"
+  href="https://mathml-refresh.github.io/mathml-core/#dom-and-javascript"
+/>
+<link
+  rel="help"
+  href="https://html.spec.whatwg.org/multipage/#event-handler-idl-attributes"
+/>
+<link
+  rel="help"
+  href="https://html.spec.whatwg.org/multipage/#event-handler-content-attributes"
+/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/WebIDLParser.js"></script>
+
+<script>
+  "use strict";
+  setup({ explicit_done: true });
+
+  // basic pattern lifted from /html/webappapis/scripting/events/event-handler-all-global-events.html
+  fetch("/interfaces/html.idl")
+    .then(res => res.text())
+    .then(htmlIDL => {
+      const parsedHTMLIDL = WebIDL2.parse(htmlIDL);
+      const globalEventHandlers = parsedHTMLIDL.find(
+        idl => idl.name === "GlobalEventHandlers"
+      );
+
+      // onerror is too special
+      const names = globalEventHandlers.members
+        .map(member => member.name)
+        .filter(name => name !== "onerror");
+
+      for (const name of names) {
+        const withoutOn = name.substring(2);
+
+        test(() => {
+          const location = MathMLElement.prototype;
+          assert_true(
+            location.hasOwnProperty(name),
+            `${location.constructor.name} has an own property named "${name}"`
+          );
+
+          assert_false(
+            name in Element.prototype,
+            `Element.prototype must not contain a "${name}" property`
+          );
+        }, `${name}: must be on the appropriate locations for GlobalEventHandlers`);
+
+        test(() => {
+          const location = document.createElementNS(
+            "http://www.w3.org/1998/Math/MathML",
+            "math"
+          );
+
+          assert_equals(
+            location[name],
+            null,
+            `The default value of the property is null for a ${
+              location.constructor.name
+            } instance`
+          );
+        }, `${name}: the default value must be null`);
+
+        test(() => {
+          const el = document.createElementNS(
+            "http://www.w3.org/1998/Math/MathML",
+            "math"
+          );
+          el.setAttribute(name, `window.${name}Happened = true;`);
+          const compiledHandler = el[name];
+
+          assert_equals(
+            typeof compiledHandler,
+            "function",
+            `The ${name} property must be a function`
+          );
+          compiledHandler();
+          assert_true(
+            window[name + "Happened"],
+            "Calling the handler must run the code"
+          );
+        }, `${name}: the content attribute must be compiled into a function as the corresponding property`);
+
+        test(() => {
+          const element = document.createElementNS(
+            "http://www.w3.org/1998/Math/MathML",
+            "math"
+          );
+          element[name] = e => {
+            assert_equals(
+              e.currentTarget,
+              element,
+              "The event must be fired at the <math> element"
+            );
+          };
+
+          element.dispatchEvent(new Event(withoutOn));
+        }, `${name}: dispatching an Event at a <math> element must trigger element.${name}`);
+      }
+
+      done();
+    });
+</script>
--- a/testing/web-platform/tests/mathml/support/box-comparison.js
+++ b/testing/web-platform/tests/mathml/support/box-comparison.js
@@ -17,17 +17,17 @@ function measureSpaceAround(id) {
 
 function compareSpaceWithAndWithoutStyle(tag, style, parentStyle, direction) {
     if (!FragmentHelper.isValidChildOfMrow(tag) ||
         FragmentHelper.isEmpty(tag))
         throw `Invalid argument: ${tag}`;
 
     if (!direction)
       direction = "ltr";
-    document.body.insertAdjacentHTML("beforeend", `<div>\
+    document.body.insertAdjacentHTML("beforeend", `<div style="position: absolute;">\
 <math><mrow dir="${direction}">${MathMLFragments[tag]}</mrow></math>\
 <math><mrow dir="${direction}">${MathMLFragments[tag]}</mrow></math>\
 </div>`);
     var div = document.body.lastElementChild;
 
     var styleMath = div.firstElementChild;
     var styleParent = styleMath.firstElementChild;
     if (parentStyle)
@@ -59,17 +59,17 @@ function compareSpaceWithAndWithoutStyle
         element_height_delta: styleElementBox.height - noStyleElementBox.height
     };
 }
 
 function compareSizeWithAndWithoutStyle(tag, style) {
     if (!FragmentHelper.isValidChildOfMrow(tag))
         throw `Invalid argument: ${tag}`;
 
-    document.body.insertAdjacentHTML("beforeend", `<div>\
+    document.body.insertAdjacentHTML("beforeend", `<div style="position: absolute;">\
 <math>${MathMLFragments[tag]}</math>\
 <math>${MathMLFragments[tag]}</math>\
 </div>`);
     var div = document.body.lastElementChild;
 
     var styleMath = div.firstElementChild;
     var styleElement = FragmentHelper.element(styleMath);
     styleElement.setAttribute("style", style);
--- a/testing/web-platform/tests/mathml/support/layout-comparison.js
+++ b/testing/web-platform/tests/mathml/support/layout-comparison.js
@@ -32,46 +32,56 @@ function compareSize(element, reference,
         assert_approx_equals(elementBox.height, referenceBox.width, epsilon,
                              "block size");
         break;
     default:
         throw "compareSize: Unrecognized writing-mode value";
     }
 }
 
+function participateToParentLayout(child) {
+    var style = window.getComputedStyle(child);
+    return style.getPropertyValue("display") !== "none" &&
+        style.getPropertyValue("position") !== "absolute" &&
+        style.getPropertyValue("position") !== "fixed";
+}
+
+function childrenParticipatingToLayout(element) {
+    var children = [];
+    Array.from(element.children).forEach(child => {
+        if (participateToParentLayout(child))
+            children.push(child);
+    })
+    return children;
+}
+
 function compareLayout(element, reference, epsilon) {
-    if (element.children.length != reference.children.length)
-        throw "Reference should have the same number of children."
-
     // Compare sizes of elements and children.
     var param = getWritingMode(element, reference);
 
     compareSize(element, reference, epsilon);
     var elementBox = element.getBoundingClientRect();
     var referenceBox = reference.getBoundingClientRect();
-    for (var i = 0; i < element.children.length; i++) {
-        var childDisplay = window.
-            getComputedStyle(element.children[i]).getPropertyValue("display");
-        var referenceChildDisplay = window.
-            getComputedStyle(reference.children[i]).getPropertyValue("display");
-        if (referenceChildDisplay !== childDisplay)
-            throw "compareLayout: children of reference should have the same display values.";
-        if (childDisplay === "none")
-            continue;
+
+    var elementChildren = childrenParticipatingToLayout(element);
+    var referenceChildren = childrenParticipatingToLayout(reference);
+    if (elementChildren.length != referenceChildren.length)
+        throw "Reference should have the same number of children participating to layout."
 
-        compareSize(element.children[i], reference.children[i], epsilon);
+    for (var i = 0; i < elementChildren.length; i++) {
+        compareSize(elementChildren[i], referenceChildren[i], epsilon);
 
-        var childBox = element.children[i].getBoundingClientRect();
-        var referenceChildBox = reference.children[i].getBoundingClientRect();
+        var childBox = elementChildren[i].getBoundingClientRect();
+        var referenceChildBox = referenceChildren[i].getBoundingClientRect();
 
         switch(param.mode) {
         case "horizontal-tb":
-            if (!param.rtl)
-                throw "compareLayout: unexpected writing-mode value";
-            assert_approx_equals(elementBox.right - childBox.right,
+            assert_approx_equals(param.rtl ?
+                                 elementBox.right - childBox.right :
+                                 childBox.left - elementBox.left,
                                  referenceChildBox.left - referenceBox.left,
                                  epsilon,
                                  `inline position (child ${i})`);
             assert_approx_equals(childBox.top - elementBox.top,
                                  referenceChildBox.top - referenceBox.top,
                                  epsilon,
                                  `block position (child ${i})`);
             break;
--- a/testing/web-platform/tests/mathml/support/mathml-fragments.js
+++ b/testing/web-platform/tests/mathml/support/mathml-fragments.js
@@ -133,22 +133,30 @@ var FragmentHelper = {
     isEmpty: function(tag) {
         return tag === "mspace" || tag == "mprescripts" || tag == "none";
     },
 
     element: function(fragment) {
         return fragment.getElementsByClassName('element')[0];
     },
 
-    forceNonEmptyElement: function(fragment) {
+    appendChild: function(fragment, allowInvalid) {
         var element = this.element(fragment) || fragment;
-        if (element.firstElementChild)
-            return element.firstElementChild;
-        if (element.classList.contains("mathml-container"))
-            return element.appendChild(this.createElement("mrow"));
         if (element.classList.contains("foreign-container")) {
             var el = document.createElement("span");
             el.textContent = "a";
             return element.appendChild(el);
         }
-        throw "Cannot make the element nonempty";
+        if (element.classList.contains("mathml-container") || allowInvalid) {
+            var el = this.createElement("mi");
+            el.textContent = "a";
+            return element.appendChild(el);
+        }
+        throw "Cannot append child to the element";
+    },
+
+    forceNonEmptyElement: function(fragment) {
+        var element = this.element(fragment) || fragment;
+        if (element.firstElementChild)
+            return element.firstElementChild;
+        return this.appendChild(fragment);
     }
 }
--- a/testing/web-platform/tests/mathml/tools/fractions.py
+++ b/testing/web-platform/tests/mathml/tools/fractions.py
@@ -30,18 +30,18 @@ f.math.FractionNumeratorDisplayStyleGapM
 f.math.FractionNumeratorDisplayStyleShiftUp = 0
 f.math.FractionNumeratorGapMin = 0
 f.math.FractionNumeratorShiftUp = 0
 f.math.FractionRuleThickness = v2
 mathfont.save(f)
 
 v1 = 6 * mathfont.em
 v2 = 1 * mathfont.em
-f = mathfont.create("fraction-denominatordisplaystyleshiftdown%d-rulethickness%d" % (v1, v2))
-f.math.AxisHeight = 0
+f = mathfont.create("fraction-denominatordisplaystyleshiftdown%d-axisheight%d-rulethickness%d" % (v1, v2, v2))
+f.math.AxisHeight = v2
 f.math.FractionDenominatorDisplayStyleGapMin = 0
 f.math.FractionDenominatorDisplayStyleShiftDown = v1
 f.math.FractionDenominatorGapMin = 0
 f.math.FractionDenominatorShiftDown = 0
 f.math.FractionNumeratorDisplayStyleGapMin = 0
 f.math.FractionNumeratorDisplayStyleShiftUp = 0
 f.math.FractionNumeratorGapMin = 0
 f.math.FractionNumeratorShiftUp = 0
@@ -60,18 +60,18 @@ f.math.FractionNumeratorDisplayStyleGapM
 f.math.FractionNumeratorDisplayStyleShiftUp = 0
 f.math.FractionNumeratorGapMin = 0
 f.math.FractionNumeratorShiftUp = 0
 f.math.FractionRuleThickness = v2
 mathfont.save(f)
 
 v1 = 3 * mathfont.em
 v2 = 1 * mathfont.em
-f = mathfont.create("fraction-denominatorshiftdown%d-rulethickness%d" % (v1, v2))
-f.math.AxisHeight = 0
+f = mathfont.create("fraction-denominatorshiftdown%d-axisheight%d-rulethickness%d" % (v1, v2, v2))
+f.math.AxisHeight = v2
 f.math.FractionDenominatorDisplayStyleGapMin = 0
 f.math.FractionDenominatorDisplayStyleShiftDown = 0
 f.math.FractionDenominatorGapMin = 0
 f.math.FractionDenominatorShiftDown = v1
 f.math.FractionNumeratorDisplayStyleGapMin = 0
 f.math.FractionNumeratorDisplayStyleShiftUp = 0
 f.math.FractionNumeratorGapMin = 0
 f.math.FractionNumeratorShiftUp = 0
@@ -90,18 +90,18 @@ f.math.FractionNumeratorDisplayStyleGapM
 f.math.FractionNumeratorDisplayStyleShiftUp = 0
 f.math.FractionNumeratorGapMin = 0
 f.math.FractionNumeratorShiftUp = 0
 f.math.FractionRuleThickness = v2
 mathfont.save(f)
 
 v1 = 2 * mathfont.em
 v2 = 1 * mathfont.em
-f = mathfont.create("fraction-numeratordisplaystyleshiftup%d-rulethickness%d" % (v1, v2))
-f.math.AxisHeight = 0
+f = mathfont.create("fraction-numeratordisplaystyleshiftup%d-axisheight%d-rulethickness%d" % (v1, v2, v2))
+f.math.AxisHeight = v2
 f.math.FractionDenominatorDisplayStyleGapMin = 0
 f.math.FractionDenominatorDisplayStyleShiftDown = 0
 f.math.FractionDenominatorGapMin = 0
 f.math.FractionDenominatorShiftDown = 0
 f.math.FractionNumeratorDisplayStyleGapMin = 0
 f.math.FractionNumeratorDisplayStyleShiftUp = v1
 f.math.FractionNumeratorGapMin = 0
 f.math.FractionNumeratorShiftUp = 0
@@ -120,18 +120,18 @@ f.math.FractionNumeratorDisplayStyleGapM
 f.math.FractionNumeratorDisplayStyleShiftUp = 0
 f.math.FractionNumeratorGapMin = v1
 f.math.FractionNumeratorShiftUp = 0
 f.math.FractionRuleThickness = v2
 mathfont.save(f)
 
 v1 = 11 * mathfont.em
 v2 = 1 * mathfont.em
-f = mathfont.create("fraction-numeratorshiftup%d-rulethickness%d" % (v1, v2))
-f.math.AxisHeight = 0
+f = mathfont.create("fraction-numeratorshiftup%d-axisheight%d-rulethickness%d" % (v1, v2, v2))
+f.math.AxisHeight = v2
 f.math.FractionDenominatorDisplayStyleGapMin = 0
 f.math.FractionDenominatorDisplayStyleShiftDown = 0
 f.math.FractionDenominatorGapMin = 0
 f.math.FractionDenominatorShiftDown = 0
 f.math.FractionNumeratorDisplayStyleGapMin = 0
 f.math.FractionNumeratorDisplayStyleShiftUp = 0
 f.math.FractionNumeratorGapMin = 0
 f.math.FractionNumeratorShiftUp = v1
--- a/testing/web-platform/tests/mathml/tools/stacks.py
+++ b/testing/web-platform/tests/mathml/tools/stacks.py
@@ -1,40 +1,31 @@
 #!/usr/bin/python
 
 from utils import mathfont
 import fontforge
 
-v = 7 * mathfont.em
-f = mathfont.create("stack-axisheight%d" % v)
-f.math.AxisHeight = v
-f.math.StackBottomDisplayStyleShiftDown = 0
+v1 = 5 * mathfont.em
+v2 = 1 * mathfont.em
+f = mathfont.create("stack-bottomdisplaystyleshiftdown%d-axisheight%d" % (v1, v2))
+f.math.AxisHeight = v2
+f.math.StackBottomDisplayStyleShiftDown = v1
 f.math.StackBottomShiftDown = 0
 f.math.StackDisplayStyleGapMin = 0
 f.math.StackGapMin = 0
 f.math.StackTopDisplayStyleShiftUp = 0
 f.math.StackTopShiftUp = 0
 mathfont.save(f)
 
-v = 5 * mathfont.em
-f = mathfont.create("stack-bottomdisplaystyleshiftdown%d" % v)
-f.math.AxisHeight = 0
-f.math.StackBottomDisplayStyleShiftDown = v
-f.math.StackBottomShiftDown = 0
-f.math.StackDisplayStyleGapMin = 0
-f.math.StackGapMin = 0
-f.math.StackTopDisplayStyleShiftUp = 0
-f.math.StackTopShiftUp = 0
-mathfont.save(f)
-
-v = 6 * mathfont.em
-f = mathfont.create("stack-bottomshiftdown%d" % v)
-f.math.AxisHeight = 0
+v1 = 6 * mathfont.em
+v2 = 1 * mathfont.em
+f = mathfont.create("stack-bottomshiftdown%d-axisheight%d" % (v1, v2))
+f.math.AxisHeight = v2
 f.math.StackBottomDisplayStyleShiftDown = 0
-f.math.StackBottomShiftDown = v
+f.math.StackBottomShiftDown = v1
 f.math.StackDisplayStyleGapMin = 0
 f.math.StackGapMin = 0
 f.math.StackTopDisplayStyleShiftUp = 0
 f.math.StackTopShiftUp = 0
 mathfont.save(f)
 
 v = 4 * mathfont.em
 f = mathfont.create("stack-displaystylegapmin%d" % v)
@@ -53,29 +44,31 @@ f.math.AxisHeight = 0
 f.math.StackBottomDisplayStyleShiftDown = 0
 f.math.StackBottomShiftDown = 0
 f.math.StackDisplayStyleGapMin = 0
 f.math.StackGapMin = v
 f.math.StackTopDisplayStyleShiftUp = 0
 f.math.StackTopShiftUp = 0
 mathfont.save(f)
 
-v = 3 * mathfont.em
-f = mathfont.create("stack-topdisplaystyleshiftup%d" % v)
-f.math.AxisHeight = 0
+v1 = 3 * mathfont.em
+v2 = 1 * mathfont.em
+f = mathfont.create("stack-topdisplaystyleshiftup%d-axisheight%d" % (v1, v2))
+f.math.AxisHeight = v2
 f.math.StackBottomDisplayStyleShiftDown = 0
 f.math.StackBottomShiftDown = 0
 f.math.StackDisplayStyleGapMin = 0
 f.math.StackGapMin = 0
-f.math.StackTopDisplayStyleShiftUp = v
+f.math.StackTopDisplayStyleShiftUp = v1
 f.math.StackTopShiftUp = 0
 mathfont.save(f)
 
-v = 9 * mathfont.em
-f = mathfont.create("stack-topshiftup%d" % v)
-f.math.AxisHeight = 0
+v1 = 9 * mathfont.em
+v2 = 1 * mathfont.em
+f = mathfont.create("stack-topshiftup%d-axisheight%d" % (v1, v2))
+f.math.AxisHeight = v2
 f.math.StackBottomDisplayStyleShiftDown = 0
 f.math.StackBottomShiftDown = 0
 f.math.StackDisplayStyleGapMin = 0
 f.math.StackGapMin = 0
 f.math.StackTopDisplayStyleShiftUp = 0
-f.math.StackTopShiftUp = v
+f.math.StackTopShiftUp = v1
 mathfont.save(f)
--- a/testing/web-platform/tests/mediasession/idlharness.window.js
+++ b/testing/web-platform/tests/mediasession/idlharness.window.js
@@ -1,12 +1,12 @@
 // META: script=/resources/WebIDLParser.js
 // META: script=/resources/idlharness.js
 
-// https://wicg.github.io/mediasession/
+// https://w3c.github.io/mediasession/
 
 'use strict';
 
 idl_test(
   ['mediasession'],
   ['html'],
   idl_array => {
     idl_array.add_objects({
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mediasession/positionstate.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<title>MediaSession.setPositionState</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+test(() => {
+  window.navigator.mediaSession.setPositionState(null);
+}, 'Test setPositionState with a null value');
+
+test(() => {
+  window.navigator.mediaSession.setPositionState({
+    duration: 60.9,
+    position: 10.1,
+    playbackRate: 1.5
+  });
+}, 'Test setPositionState with a valid value for forward playback');
+
+test(() => {
+  window.navigator.mediaSession.setPositionState({
+    duration: 60.9,
+    playbackRate: 1.0
+  });
+}, 'Test setPositionState with optional position');
+
+test(() => {
+  window.navigator.mediaSession.setPositionState({
+    duration: 60.9,
+    position: 10.1
+  });
+}, 'Test setPositionState with optional playback rate');
+
+test(() => {
+  window.navigator.mediaSession.setPositionState({
+    duration: 60.9
+  });
+}, 'Test setPositionState with only duration');
+
+test(() => {
+  window.navigator.mediaSession.setPositionState({
+    duration: 0
+  });
+}, 'Test setPositionState with zero duration');
+
+test(() => {
+  assert_throws(
+      new TypeError,
+      _ => {
+        window.navigator.mediaSession.setPositionState({
+          duration: 60.9,
+          position: 10.1,
+          playbackRate: -2.0
+        });
+      });
+}, 'Test setPositionState throws a TypeError if playback rate is negative');
+
+test(() => {
+  assert_throws(
+      new TypeError,
+      _ => {
+        window.navigator.mediaSession.setPositionState({
+          duration: -1
+        });
+      });
+}, 'Test setPositionState throws a TypeError if duration is negative');
+
+test(() => {
+  assert_throws(
+      new TypeError,
+      _ => {
+        window.navigator.mediaSession.setPositionState({
+          duration: 10,
+          position: -1
+        });
+      });
+}, 'Test setPositionState throws a TypeError if position is negative');
+
+test(() => {
+  assert_throws(
+      new TypeError,
+      _ => {
+        window.navigator.mediaSession.setPositionState({
+          duration: 10,
+          position: 20
+        });
+      });
+}, 'Test setPositionState throws a TypeError if duration is less than position');
+
+test(() => {
+  assert_throws(
+      new TypeError,
+      _ => {
+        window.navigator.mediaSession.setPositionState({
+          duration: 60.9,
+          position: 10.1,
+          playbackRate: 0.0
+        });
+      });
+}, 'Test setPositionState throws a TypeError if playback rate is zero');
+
+test(() => {
+  assert_throws(
+      new TypeError,
+      _ => {
+        window.navigator.mediaSession.setPositionState({
+          position: 10.1,
+          playbackRate: 1.0
+        });
+      });
+}, 'Test setPositionState throws a TypeError if duration is not specified');
+</script>
--- a/testing/web-platform/tests/payment-request/blank.html
+++ b/testing/web-platform/tests/payment-request/blank.html
@@ -1,1 +1,16 @@
-<!DOCTYPE html> <meta charset="utf-8" />
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <title>Blank Page</title>
+    <script>
+      window.onload = function(event) {
+        // This is needed to ensure the onload event fires when this page is
+        // opened as a popup.
+        // See https://github.com/web-platform-tests/wpt/pull/18157
+      };
+    </script>
+  </head>
+  <body>
+  </body>
+</html>
--- a/testing/web-platform/tests/payment-request/payment-is-showing.https.html
+++ b/testing/web-platform/tests/payment-request/payment-is-showing.https.html
@@ -1,144 +1,145 @@
 <!DOCTYPE html> <meta charset="utf-8" />
 <title>Test for PaymentRequest.show(optional promise) method</title>
 <link
   rel="help"
   href="https://w3c.github.io/browser-payment-api/#dfn-payment-request-is-showing"
 />
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/resources/testdriver-vendor.js"></script>
 <script src="/resources/testdriver.js"></script>
 <body>
   <script>
-    'use strict';
+    "use strict";
     const applePayMethod = {
-      supportedMethods: 'https://apple.com/apple-pay',
+      supportedMethods: "https://apple.com/apple-pay",
       data: {
         version: 3,
-        merchantIdentifier: 'merchant.com.example',
-        countryCode: 'US',
-        merchantCapabilities: ['supports3DS'],
-        supportedNetworks: ['visa'],
+        merchantIdentifier: "merchant.com.example",
+        countryCode: "US",
+        merchantCapabilities: ["supports3DS"],
+        supportedNetworks: ["visa"],
       },
     };
-    const methods = [{supportedMethods: 'basic-card'}, applePayMethod];
+    const methods = [{supportedMethods: "basic-card"}, applePayMethod];
     const details = {
       total: {
-        label: 'Total',
+        label: "Total",
         amount: {
-          currency: 'USD',
-          value: '1.00',
+          currency: "USD",
+          value: "1.00",
         },
       },
     };
 
     /**
      * Attaches an iframe to window.document.
      *
      * @param {String} src Optional resource URL to load.
      * @returns {Promise} Resolves when the src loads.
      */
-    async function attachIframe(src = 'blank.html') {
-      const iframe = document.createElement('iframe');
+    async function attachIframe(src = "blank.html") {
+      const iframe = document.createElement("iframe");
       iframe.allowPaymentRequest = true;
       iframe.src = src;
       document.body.appendChild(iframe);
       await new Promise(resolve => {
-        iframe.addEventListener('load', resolve, {once: true});
+        iframe.addEventListener("load", resolve, {once: true});
       });
       return iframe;
     }
 
     /**
      * Creates a popup window. The caller must be triggered with a user gesture.
      *
      * @param {String} src Optional resource URL to load.
      * @returns {Promise} Resolves when the src loads.
      */
-    async function loadPopupInsideUserGesture(src = 'blank.html') {
-      const popupWindow = window.open(src, '', 'width=400,height=400');
+    async function loadPopupInsideUserGesture(src = "blank.html") {
+      const popupWindow = window.open(src, "", "width=400,height=400");
       await new Promise(resolve => {
-        popupWindow.addEventListener('load', resolve, {once: true});
+        popupWindow.addEventListener("load", resolve, {once: true});
       });
       popupWindow.focus();
       return popupWindow;
     }
 
     promise_test(async t => {
       const request1 = new PaymentRequest(methods, details);
       const request2 = new PaymentRequest(methods, details);
 
       // Sets the "payment-relevant browsing context's payment request is
       // showing boolean" to true and then try to show a second payment sheet in
       // the same window. The second show() should reject.
       const [showPromise1, showPromise2] = await test_driver.bless(
-        'testing one payment sheet per window',
+        "testing one payment sheet per window",
         () => {
           return [request1.show(), request2.show()];
         },
       );
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         showPromise2,
-        'Attempting to show a second payment request must reject.',
+        "Attempting to show a second payment request must reject.",
       );
 
       await request1.abort();
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         showPromise1,
-        'request1 was aborted via .abort()',
+        "request1 was aborted via .abort()",
       );
 
       // Finally, request2 should have been "closed", so trying to show
       // it will again result in promise rejected with an InvalidStateError.
       // See: https://github.com/w3c/payment-request/pull/821
       const rejectedPromise = request2.show();
       await promise_rejects(
         t,
-        'InvalidStateError',
+        "InvalidStateError",
         rejectedPromise,
-        'Attempting to show a second payment request must reject.',
+        "Attempting to show a second payment request must reject.",
       );
       // Finally, we confirm that request2's returned promises are unique.
       assert_not_equals(
         showPromise2,
         rejectedPromise,
-        'Returned Promises be unique',
+        "Returned Promises be unique",
       );
-    }, 'The top browsing context can only show one payment sheet at a time.');
+    }, "The top browsing context can only show one payment sheet at a time.");
 
     promise_test(async t => {
       const iframe = await attachIframe();
       const iframeWindow = iframe.contentWindow;
 
       // Payment requests
       const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
       const windowRequest = new window.PaymentRequest(methods, details);
 
       // Let's get some blessed showPromises
       const [showPromise] = await test_driver.bless(
-        'testing top window show() blocked by payment sheet in iframe',
+        "testing top window show() blocked by payment sheet in iframe",
         () => {
           // iframe sets "is showing boolean", ignore the returned promise.
           iframeRequest.show();
           // The top level window now tries to show() the payment request.
           return [windowRequest.show()];
         },
       );
 
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         showPromise,
-        'iframe is already showing a payment request.',
+        "iframe is already showing a payment request.",
       );
 
       // Cleanup
       await iframeRequest.abort();
       iframe.remove();
     }, "If an iframe shows a payment request, the top-level browsing context can't also show one.");
 
     promise_test(async t => {
@@ -147,126 +148,144 @@
 
       // Payment requests
       const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
       const windowRequest = new window.PaymentRequest(methods, details);
 
       // We first show a payment request via the the top level browsing context,
       // windowRequest.show() sets "is showing boolean" to true. Then we try to
       // show a payment request in the iframe, which should reject.
-      const [iframeShowPromise] = await test_driver.bless(
-        'testing iframe show() blocked by payment sheet in top window',
+      const [windowShowPromise, iframeShowPromise] = await test_driver.bless(
+        "testing iframe show() blocked by payment sheet in top window",
         () => {
-          windowRequest.show();
-          return [iframeRequest.show()];
+          return [windowRequest.show(), iframeRequest.show()];
         },
       );
 
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         iframeShowPromise,
-        'The top window is already showing a payment request.',
+        "The top window is already showing a payment request.",
       );
 
       // Cleanup
       await windowRequest.abort();
+      await promise_rejects(
+        t,
+        "AbortError",
+        windowShowPromise,
+        "The window payment request should be aborted by test.",
+        );
       iframe.remove();
-    }, 'An iframe cannot show a payment request if the top-level window is already showing one.');
+    }, "An iframe cannot show a payment request if the top-level window is already showing one.");
 
     promise_test(async t => {
       // Create a PaymentReuqest in top-level window.
       const windowRequest = new window.PaymentRequest(methods, details);
 
       // Use a single user gesture to open a popup window with a PaymentRequest.
       // Then trigger show() first on |popupRequest| then on |windowRequest|.
       // The latter should reject.
       const [
         popupWindow,
         popupRequest,
         popupShowPromise,
         windowShowPromise,
       ] = await test_driver.bless(
-        'testing top-level show() blocked by payment sheet in popup',
+        "testing top-level show() blocked by payment sheet in popup",
         async () => {
           const popupWindow = await loadPopupInsideUserGesture();
           const popupRequest = new popupWindow.PaymentRequest(methods, details);
           const popupShowPromise = popupRequest.show();
           const windowShowPromise = windowRequest.show();
           return [
             popupWindow,
             popupRequest,
             popupShowPromise,
             windowShowPromise,
           ];
         },
       );
-      await popupRequest.abort();
-      popupWindow.close();
 
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         windowShowPromise,
         "Expected window's showPromise to reject, request is already showing",
       );
-    }, 'Using a popup window prevents the top-browsing context from showing a payment request');
+
+      await popupRequest.abort();
+      await promise_rejects(
+        t,
+        "AbortError",
+        popupShowPromise,
+        "Expected popupShowPromise to be aborted by test.",
+      );
+      popupWindow.close();
+    }, "Using a popup window prevents the top-browsing context from showing a payment request");
 
     promise_test(async t => {
       const iframe = await attachIframe();
       const iframeWindow = iframe.contentWindow;
 
       // Create requests
       const windowRequest = new window.PaymentRequest(methods, details);
       const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
 
       // Open a popup window
       const [popupWindow, popupRequest] =
       await test_driver.bless(
-        'open popup to test multiple context and window calls show() first',
+        "open popup to test multiple context and window calls show() first",
         async () => {
           const popupWindow = await loadPopupInsideUserGesture();
           const popupRequest = new popupWindow.PaymentRequest(methods, details);
           return [popupWindow, popupRequest];
         },
       );
 
       // Get the showPromise for each browsing context. Doing this in a separate
       // test_driver.bless() is important because the user gesture brings
       // |window| to the foreground, so that the payment sheet can show.
       const [
         windowShowPromise,
         popupShowPromise,
         iframeShowPromise,
       ] = await test_driver.bless(
-        'test multiple nested browsing context',
+        "test multiple nested browsing context",
         () => {
           return [
             windowRequest.show(),
             popupRequest.show(),
             iframeRequest.show(),
           ];
         },
       );
       // popupRequest and iframeRequest will both reject
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         popupShowPromise,
-        'Expected popupShowPromise to reject, request is already showing.',
+        "Expected popupShowPromise to reject, request is already showing.",
       );
 
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         iframeShowPromise,
-        'Expected iframeShowPromise to reject, request is already showing.',
+        "Expected iframeShowPromise to reject, request is already showing.",
       );
 
       await windowRequest.abort();
+      await promise_rejects(
+        t,
+        "AbortError",
+        windowShowPromise,
+        "Expect window promise to be aborted by test."
+      );
       popupWindow.close();
       iframe.remove();
     }, "Given multiple nested browsing contexts, and window calls show() first, other nested browsing contexts can't show a request.");
 
     promise_test(async t => {
       const iframe = await attachIframe();
       const iframeWindow = iframe.contentWindow;
 
@@ -277,153 +296,207 @@
       // Open a popup window
       const [
         popupWindow,
         popupRequest,
         popupShowPromise,
         windowShowPromise,
         iframeShowPromise
       ] = await test_driver.bless(
-        'test multiple browsing context and iframe calls show() first',
+        "test multiple browsing context and iframe calls show() first",
         async () => {
           const popupWindow = await loadPopupInsideUserGesture();
           const popupRequest = new popupWindow.PaymentRequest(methods, details);
           const popupShowPromise = popupRequest.show();
           const windowShowPromise = windowRequest.show();
           const iframeShowPromise = iframeRequest.show();
           return [popupWindow,
                   popupRequest,
                   popupShowPromise,
                   windowShowPromise,
                   iframeShowPromise];
       });
 
       // windowShowPromise and iframeRequest will both reject
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         windowShowPromise,
-        'Expected windowShowPromise to reject, the popup is showing a payment request.',
+        "Expected windowShowPromise to reject, the popup is showing a payment request.",
       );
 
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         iframeShowPromise,
-        'Expected iframeShowPromise to reject, the popup is showing a payment request.',
+        "Expected iframeShowPromise to reject, the popup is showing a payment request.",
       );
 
       await popupRequest.abort();
+      await promise_rejects(
+        t,
+        "AbortError",
+        popupShowPromise,
+        "Expected popupShowPromise to be aborted by test.",
+      );
       popupWindow.close();
       iframe.remove();
     }, "Given multiple nested browsing contexts, and popup calls show() first, other nested browsing contexts can't show a request.");
 
     promise_test(async t => {
       const iframe = await attachIframe();
       const iframeWindow = iframe.contentWindow;
 
       // Create requests
       const windowRequest = new window.PaymentRequest(methods, details);
       const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
 
       const [popupWindow, popupRequest] = await test_driver.bless(
-        'open popup to test multiple context and iframe calls show() first',
+        "open popup to test multiple context and iframe calls show() first",
         async () => {
           const w = await loadPopupInsideUserGesture();
           const r = new w.PaymentRequest(methods, details);
           return [w, r];
         },
       );
 
       // Get the showPromise for each browsing context. Doing this in a separate
       // test_driver.bless() is important because the user gesture brings
       // |window| to the foreground, so that the payment sheet can show.
       const [
         iframeShowPromise,
         popupShowPromise,
         windowShowPromise,
       ] = await test_driver.bless(
-        'test multiple browsing context and iframe calls show() first',
+        "test multiple browsing context and iframe calls show() first",
         async () => {
           return [
             iframeRequest.show(),
             popupRequest.show(),
             windowRequest.show(),
           ];
         },
       );
 
       // windowShowPromise and iframeRequest will both reject
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         windowShowPromise,
-        'Expected windowShowPromise to reject, the popup is showing a payment request.',
+        "Expected windowShowPromise to reject, the popup is showing a payment request.",
       );
 
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         popupShowPromise,
-        'Expected popupShowPromise to reject, the popup is showing a payment request.',
+        "Expected popupShowPromise to reject, the popup is showing a payment request.",
       );
 
       await iframeRequest.abort();
+      await promise_rejects(
+        t,
+        "AbortError",
+        iframeShowPromise,
+        "Expected iframeShowPromise to be aborted by test."
+      );
       popupWindow.close();
       iframe.remove();
     }, "Given multiple nested browsing contexts, and an iframe calls show() first, other nested browsing contexts can't show a request.");
 
     promise_test(async t => {
       const iframe = await attachIframe();
       const iframeWindow = iframe.contentWindow;
       const iframeRequest = new iframeWindow.PaymentRequest(methods, details);
       const iframeShowPromise = test_driver.bless(
-        'test navigating iframe after show()',
+        "test navigating iframe after show()",
         () => iframeRequest.show(),
       );
 
       // We navigate away, causing the payment sheet to close
       // and the request is showing boolean to become false.
-      iframe.src = 'blank.html?abc=123';
+      iframe.src = "blank.html?abc=123";
       await new Promise(resolve => (iframe.onload = resolve));
       await promise_rejects(
         t,
-        'AbortError',
+        "AbortError",
         iframeShowPromise,
-        'Navigating iframe away must cause the iframeShowPromise to reject.',
+        "Navigating iframe away must cause the iframeShowPromise to reject.",
       );
       iframe.remove();
 
       // Now we should be ok to spin up a new payment request
       const request = new window.PaymentRequest(methods, details);
-      const showPromise = request.show();
-      await request.abort();
+      const [showPromise] = await test_driver.bless(
+          "start a new payment request",
+          () => {
+            return [request.show()];
+          });
+
+      // If a payment sheet fails to show, it should reject immediately. If it
+      // hasn't rejected in 1 second, then the test has passed.
+      t.step_timeout(async () => {
+        // We're done. Clean up.
+        await request.abort();
+        t.done();
+      });
+
+      // If the navigation in iframe failed to close the original payment sheet
+      // there, |showPromise| should reject immediately and this indicates a
+      // failure of this test.
+      await showPromise.then(() => {
+        assert_true(false,
+          "Second payment sheet should be pending but is resolved.");
+      })
+      .catch(e => {
+        assert_true(false,
+          "Second payment sheet should be pending but is rejected." + e.message);
+      });
     }, "Navigating an iframe as a nested browsing context sets 'payment request is showing boolean' to false.");
 
     promise_test(async t => {
-      const [popupWindow, popupRequest, showPromise] = await test_driver.bless(
-        'test navigating popup after show()',
-        async () => {
-          const popupWindow = await loadPopupInsideUserGesture();
-          const popupRequest = new popupWindow.PaymentRequest(methods, details);
-          return [popupWindow, popupRequest, popupRequest.show()];
-        },
-      );
+      const [popupWindow, popupRequest, popupShowPromise] =
+        await test_driver.bless(
+          "trigger payment in a popup window",
+          async () => {
+            const popupWindow = await loadPopupInsideUserGesture();
+            const popupRequest = new popupWindow.PaymentRequest(methods, details);
+            return [popupWindow, popupRequest, popupRequest.show()];
+          });
 
       // We navigate away, causing the payment sheet to close
       // and the request is showing boolean to become false.
-      popupWindow.location = 'blank.html?abc=123';
+      popupWindow.location = "blank.html?abc=123";
       await new Promise(resolve => (popupWindow.onload = resolve));
-      await promise_rejects(
-        t,
-        'AbortError',
-        showPromise,
-        'Navigating away must cause the showPromise to reject with an AbortError',
-      );
-      popupWindow.close();
+
+      // Don't wait for |popupShowPromise| to reject because it may never do
+      // (see https://github.com/w3c/payment-request/issues/872). Instead, try
+      // to spin up a new payment request and make sure it succeeds.
+      const request = new window.PaymentRequest(methods, details);
+      const [showPromise] = await test_driver.bless(
+        "trigger payment in main window",
+        () => {
+          return [request.show()];
+        });
 
-      // Now we should be ok to spin up a new payment request.
-      const request = new window.PaymentRequest(methods, details);
-      request.show();
-      await request.abort();
+      // If a payment sheet fails to show, it should reject immediately. If it
+      // hasn't rejected in 1 second, then the test has passed.
+      t.step_timeout(async () => {
+        // We're done. Clean up.
+        popupWindow.close();
+        await request.abort();
+        t.done();
+      }, 1000);
+
+      // If the navigation in popup window failed to close the original payment
+      // sheet there, |showPromise| should reject immediately and this indicates
+      // a failure of this test.
+      await showPromise.then(() => {
+        assert_true(false,
+          "Second payment sheet should be pending but is resolved.");
+      })
+      .catch(e => {
+        assert_true(false,
+          "Second payment sheet should be pending but is rejected.");
+      });
     }, "Navigating a popup as a nested browsing context sets 'payment request is showing boolean' to false.");
   </script>
 </body>
--- a/testing/web-platform/tests/pointerevents/pointerevent_sequence_at_implicit_release_on_drag.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_sequence_at_implicit_release_on_drag.html
@@ -22,23 +22,26 @@
         event_log = [];
         start_logging = false;
       }
 
       function run() {
         var test_pointer_event = setup_pointerevent_test("Event sequence at implicit release on drag", ["touch"]);
 
         var button = document.getElementById("done");
-        var clickIsReceived = false;
+        var actions_promise;
         on_event(document.getElementById("done"), "click", function() {
           test_pointer_event.step(function () {
             var expected_events = "pointercancel, lostpointercapture, pointerout, pointerleave";
             assert_equals(event_log.join(", "), expected_events);
           });
-          clickIsReceived = true;
+          // Make sure the test finishes after all the input actions are completed.
+          actions_promise.then( () => {
+              test_pointer_event.done();
+          });
         });
 
         var target = document.getElementById("target");
 
         All_Pointer_Events.forEach(function(eventName) {
           on_event(target, eventName, function (event) {
             detected_pointertypes[event.pointerType] = true;
 
@@ -50,23 +53,18 @@
 
             } else if (event.type != "pointermove" && start_logging) {
               event_log.push(event.type);
             }
           });
         });
 
         // Inject touch inputs.
-        pointerDragInTarget("touch", target, 'right').then(function() {
+        actions_promise = pointerDragInTarget("touch", target, 'right').then(function() {
           return clickInTarget("touch", button);
-        }).then(function() {
-          test_pointer_event.step(function () {
-            assert_true(clickIsReceived, "click should be received before the test finishes");
-          }, "click should be received before the test finishes");
-          test_pointer_event.done();
         });
       }
     </script>
     <style>
       #target {
         margin: 20px;
         background-color: black;
         touch-action: auto;
--- a/testing/web-platform/tests/pointerevents/pointerevent_touch-action-auto-css_touch.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_touch-action-auto-css_touch.html
@@ -84,16 +84,17 @@
             var xScr0, yScr0, xScr1, yScr1;
 
             add_completion_callback(showPointerTypes);
 
             function run() {
                 var target0 = document.getElementById("target0");
 
                 var test_touchaction = async_test("touch-action attribute test");
+                var actions_promise;
 
                 xScr0 = target0.scrollLeft;
                 yScr0 = target0.scrollTop;
 
                 on_event(target0, 'pointerdown', function(event) {
                     detected_pointertypes[event.pointerType] = true;
                     test_touchaction.step(function() {
                         assert_equals(event.pointerType, "touch", "wrong pointer type was detected: ");
@@ -112,28 +113,27 @@
                         test_touchaction.step(function () {
                             yScrollIsReceived = true;
                             assert_true(true, "y-scroll received.");
                         });
                         updateDescriptionNextStep();
                     }
 
                     if(xScrollIsReceived && yScrollIsReceived) {
+                        // Make sure the test finishes after all the input actions are completed.
+                        actions_promise.then( () => {
+                            test_touchaction.done();
+                        });
                         updateDescriptionComplete();
                     }
                 });
 
                 // Inject touch inputs and wait for all the actions finish to end the test.
-                touchScrollInTarget(target0, 'down').then(function() {
+                actions_promise =  touchScrollInTarget(target0, 'down').then(function() {
                     return touchScrollInTarget(target0, 'right');
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(xScrollIsReceived && yScrollIsReceived, "x-scroll and y-scroll should be received before the test finishes");
-                    }, "x-scroll and y-scroll should be received before the test finishes");
-                    test_touchaction.done();
                 });
             }
         </script>
         <h1>touch-action: auto</h1>
         <div id="complete-notice">
             <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
         </div>
         <div id="log"></div>
--- a/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_child-none_touch.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_child-none_touch.html
@@ -82,45 +82,44 @@
             var detected_pointertypes = {};
             add_completion_callback(showPointerTypes);
 
             var test_touchaction = async_test("touch-action attribute test");
 
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
+                var actions_promise;
 
                 // Check if touch-action attribute works properly for embedded divs
                 //
                 // TA: 15.9
                 on_event(btnComplete, 'click', function(event) {
                     detected_pointertypes[event.pointerType] = true;
                     test_touchaction.step(function() {
                         assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
                         assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
+
+                    // Make sure the test finishes after all the input actions are completed.
+                    actions_promise.then( () => {
+                        test_touchaction.done();
+                    });
                     updateDescriptionComplete();
                 });
 
                 on_event(target0, 'scroll', function(event) {
                     test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
                 });
 
                 // Inject touch inputs.
-                touchScrollInTarget(scrollTarget, 'down').then(function() {
+                actions_promise = touchScrollInTarget(scrollTarget, 'down').then(function() {
                     return touchScrollInTarget(scrollTarget, 'right');
                 }).then(function() {
                     return clickInTarget("touch", btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
-                    test_touchaction.done();
                 });
             }
         </script>
         <h1>behaviour: none</h1>
         <div id="complete-notice">
             <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
         </div>
         <div id="log"></div>
--- a/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch.html
@@ -86,41 +86,40 @@
         <script type='text/javascript'>
             var detected_pointertypes = {};
             var test_touchaction = async_test("touch-action attribute test");
             add_completion_callback(showPointerTypes);
 
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
+                var actions_promise;
 
                 // Check if touch-action attribute works properly for embedded divs
                 //
                 // TA: 15.6
                 on_event(btnComplete, 'click', function(event) {
                     detected_pointertypes[event.pointerType] = true;
                     test_touchaction.step(function() {
                         assert_not_equals(target0.scrollLeft, 0, "scroll x offset should not be 0 in the end of the test");
                         assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
+
+                    // Make sure the test finishes after all the input actions are completed.
+                    actions_promise.then( () => {
+                        test_touchaction.done();
+                    });
                     updateDescriptionComplete();
                 });
 
                 // Inject touch inputs.
-                touchScrollInTarget(scrollTarget, 'down').then(function() {
+                actions_promise = touchScrollInTarget(scrollTarget, 'down').then(function() {
                     return touchScrollInTarget(scrollTarget, 'right');
                 }).then(function() {
                     return clickInTarget("touch", btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
-                    test_touchaction.done();
                 });
             }
         </script>
         <h1>behaviour: pan-x</h1>
         <div id="complete-notice">
             <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
         </div>
         <div id="log"></div>
--- a/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_highest-parent-none_touch.html
@@ -87,16 +87,17 @@
 
             add_completion_callback(showPointerTypes);
             add_completion_callback(enableScrolling);
 
             function run() {
                 var target0 = document.getElementById("target0");
 
                 var test_touchaction = async_test("touch-action attribute test");
+                var actions_promise;
 
                 xScr0 = target0.scrollLeft;
                 yScr0 = target0.scrollTop;
 
                 on_event(target0, 'pointerdown', function(event) {
                     detected_pointertypes[event.pointerType] = true;
                 });
 
@@ -112,28 +113,27 @@
                     }
 
                     if(yScr1 != yScr0) {
                         yScrollIsReceived = true;
                         updateDescriptionNextStep();
                     }
 
                     if(xScrollIsReceived && yScrollIsReceived) {
+                        // Make sure the test finishes after all the input actions are completed.
+                        actions_promise.then( () => {
+                            test_touchaction.done();
+                        });
                         updateDescriptionComplete();
                     }
                 });
 
                 // Inject touch inputs and wait for all the actions finish to end the test.
-                touchScrollInTarget(target0, 'down').then(function() {
+                actions_promise = touchScrollInTarget(target0, 'down').then(function() {
                     return touchScrollInTarget(target0, 'right');
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(xScrollIsReceived && yScrollIsReceived, "x-scroll and y-scroll should be received before the test finishes");
-                    }, "x-scroll and y-scroll should be received before the test finishes");
-                    test_touchaction.done();
                 });
             }
 
             function enableScrolling() {
                 document.getElementById('divParent').setAttribute('style', 'touch-action: auto');
             }
         </script>
         <h1>behaviour: auto</h1>
--- a/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_parent-none_touch.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_touch-action-inherit_parent-none_touch.html
@@ -82,45 +82,44 @@
             var detected_pointertypes = {};
             add_completion_callback(showPointerTypes);
 
             var test_touchaction = async_test("touch-action attribute test");
 
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
+                var actions_promise;
 
                 // Check if touch-action attribute works properly for embedded divs
                 //
                 // TA: 15.8
                 on_event(btnComplete, 'click', function(event) {
                     detected_pointertypes[event.pointerType] = true;
                     test_touchaction.step(function() {
                         assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
                         assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
+
+                    // Make sure the test finishes after all the input actions are completed.
+                    actions_promise.then( () => {
+                        test_touchaction.done();
+                    });
                     updateDescriptionComplete();
                 });
 
                 on_event(target0, 'scroll', function(event) {
                     test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
                 });
 
                 // Inject touch inputs.
-                touchScrollInTarget(scrollTarget, 'down').then(function() {
+                actions_promise = touchScrollInTarget(scrollTarget, 'down').then(function() {
                     return touchScrollInTarget(scrollTarget, 'right');
                 }).then(function() {
                     return clickInTarget("touch", btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
-                    test_touchaction.done();
                 });
             }
         </script>
         <h1>behaviour: none</h1>
         <div id="complete-notice">
             <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
         </div>
         <div id="log"></div>
--- a/testing/web-platform/tests/pointerevents/pointerevent_touch-action-none-css_touch.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_touch-action-none-css_touch.html
@@ -82,44 +82,43 @@
             var detected_pointertypes = {};
 
             var test_touchaction = async_test("touch-action attribute test");
             add_completion_callback(showPointerTypes);
 
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
+                var actions_promise;
 
                 // Check if "touch-action: none" attribute works properly
                 //TA: 15.2
                 on_event(btnComplete, 'click', function(event) {
                     detected_pointertypes[event.pointerType] = true;
                     test_touchaction.step(function() {
                         assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
                         assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
+
+                    // Make sure the test finishes after all the input actions are completed.
+                    actions_promise.then( () => {
+                        test_touchaction.done();
+                    });
                     updateDescriptionComplete();
                 });
 
                 on_event(target0, 'scroll', function(event) {
                     test_touchaction.step(failOnScroll, "scroll received while touch-action is none");
                 });
 
                 // Inject touch inputs.
-                touchScrollInTarget(target0, 'down').then(function() {
+                actions_promise = touchScrollInTarget(target0, 'down').then(function() {
                     return touchScrollInTarget(target0, 'right');
                 }).then(function() {
                     return clickInTarget("touch", btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
-                    test_touchaction.done();
                 });
             }
         </script>
         <h1>touch-action: none</h1>
         <div id="complete-notice">
             <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
         </div>
         <div id="log"></div>
--- a/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-x-css_touch.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-x-css_touch.html
@@ -81,40 +81,39 @@
         <script type='text/javascript'>
             var detected_pointertypes = {};
             var test_touchaction = async_test("touch-action attribute test");
             add_completion_callback(showPointerTypes);
 
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
+                var actions_promise;
 
                 // Check if "touch-action: pan-x" attribute works properly
                 //TA: 15.3
                 on_event(btnComplete, 'click', function(event) {
                     detected_pointertypes[event.pointerType] = true;
                     test_touchaction.step(function() {
                         assert_not_equals(target0.scrollLeft, 0, "scroll x offset should not be 0 in the end of the test");
                         assert_equals(target0.scrollTop, 0, "scroll y offset should be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
+
+                    // Make sure the test finishes after all the input actions are completed.
+                    actions_promise.then( () => {
+                        test_touchaction.done();
+                    });
                     updateDescriptionComplete();
                 });
 
                 // Inject touch inputs.
-                touchScrollInTarget(target0, 'down').then(function() {
+                actions_promise = touchScrollInTarget(target0, 'down').then(function() {
                     return touchScrollInTarget(target0, 'right');
                 }).then(function() {
                     return clickInTarget("touch", btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
-                    test_touchaction.done();
                 });
             }
         </script>
         <h1>touch-action: pan-x</h1>
         <div id="complete-notice">
             <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
         </div>
         <div id="log"></div>
--- a/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-x-pan-y-pan-y_touch.html
@@ -85,41 +85,40 @@
             var detected_pointertypes = {};
             add_completion_callback(showPointerTypes);
 
             var test_touchaction = async_test("touch-action attribute test");
 
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
+                var actions_promise;
 
                 // Check if touch-action attribute works properly for embedded divs
                 //
                 // TA: 15.17
                 on_event(btnComplete, 'click', function(event) {
                     detected_pointertypes[event.pointerType] = true;
                     test_touchaction.step(function() {
                         assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
                         assert_not_equals(target0.scrollTop, 0, "scroll y offset should not be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
+
+                    // Make sure the test finishes after all the input actions are completed.
+                    actions_promise.then( () => {
+                        test_touchaction.done();
+                    });
                     updateDescriptionComplete();
                 });
 
                 // Inject touch inputs.
-                touchScrollInTarget(target0, 'down').then(function() {
+                actions_promise = touchScrollInTarget(target0, 'down').then(function() {
                     return touchScrollInTarget(target0, 'right');
                 }).then(function() {
                     return clickInTarget("touch", btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
-                    test_touchaction.done();
                 });
             }
         </script>
         <h1>behaviour: pan-y</h1>
         <div id="complete-notice">
             <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
         </div>
         <div id="log"></div>
--- a/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-x-pan-y_touch.html
@@ -84,16 +84,17 @@
             var xScr0, yScr0, xScr1, yScr1;
 
             add_completion_callback(showPointerTypes);
 
             function run() {
                 var target0 = document.getElementById("target0");
 
                 var test_touchaction = async_test("touch-action attribute test");
+                var actions_promise;
 
                 xScr0 = target0.scrollLeft;
                 yScr0 = target0.scrollTop;
 
                 on_event(target0, 'pointerdown', function(event) {
                     detected_pointertypes[event.pointerType] = true;
                 });
 
@@ -109,28 +110,27 @@
                         test_touchaction.step(function () {
                             yScrollIsReceived = true;
                             assert_true(true, "y-scroll received.");
                         });
                         updateDescriptionNextStep();
                     }
 
                     if(xScrollIsReceived && yScrollIsReceived) {
+                        // Make sure the test finishes after all the input actions are completed.
+                        actions_promise.then( () => {
+                            test_touchaction.done();
+                        });
                         updateDescriptionComplete();
                     }
                 });
 
                 // Inject touch inputs and wait for all the actions finish to end the test.
-                touchScrollInTarget(target0, 'down').then(function() {
+                actions_promise = touchScrollInTarget(target0, 'down').then(function() {
                     return touchScrollInTarget(target0, 'right');
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(xScrollIsReceived && yScrollIsReceived, "x-scroll and y-scroll should be received before the test finishes");
-                    }, "x-scroll and y-scroll should be received before the test finishes");
-                    test_touchaction.done();
                 });
             }
         </script>
         <h1>touch-action: pan-x pan-y</h1>
         <div id="complete-notice">
             <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
         </div>
         <div id="log"></div>
--- a/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-y-css_touch.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_touch-action-pan-y-css_touch.html
@@ -82,40 +82,39 @@
         <script type='text/javascript'>
             var detected_pointertypes = {};
             var test_touchaction = async_test("touch-action attribute test");
             add_completion_callback(showPointerTypes);
 
             function run() {
                 var target0 = document.getElementById("target0");
                 var btnComplete = document.getElementById("btnComplete");
-                var clickIsReceived = false;
+                var actions_promise;
 
                 // Check if "touch-action: pan-y" attribute works properly
                 //TA: 15.4
                 on_event(btnComplete, 'click', function(event) {
                     detected_pointertypes[event.pointerType] = true;
                     test_touchaction.step(function() {
                         assert_equals(target0.scrollLeft, 0, "scroll x offset should be 0 in the end of the test");
                         assert_not_equals(target0.scrollTop, 0, "scroll y offset should not be 0 in the end of the test");
                     });
-                    clickIsReceived = true;
+
+                    // Make sure the test finishes after all the input actions are completed.
+                    actions_promise.then( () => {
+                        test_touchaction.done();
+                    });
                     updateDescriptionComplete();
                 });
 
                 // Inject touch inputs.
-                touchScrollInTarget(target0, 'down').then(function() {
+                actions_promise = touchScrollInTarget(target0, 'down').then(function() {
                     return touchScrollInTarget(target0, 'right');
                 }).then(function() {
                     return clickInTarget("touch", btnComplete);
-                }).then(function() {
-                    test_touchaction.step(function () {
-                        assert_true(clickIsReceived, "click should be received before the test finishes");
-                    }, "click should be received before the test finishes");
-                    test_touchaction.done();
                 });
             }
         </script>
         <h1>touch-action: pan-y</h1>
         <div id="complete-notice">
             <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
         </div>
         <div id="log"></div>
--- a/testing/web-platform/tests/pointerevents/pointerlock/pointerevent_movementxy.html
+++ b/testing/web-platform/tests/pointerevents/pointerlock/pointerevent_movementxy.html
@@ -33,65 +33,89 @@
             left: 100px;
           }
           #square2 {
             visibility: block;
           }
         </style>
         <script>
             var expectedPointerId = NaN;
-            var startSummation = false;
-            var lastScreenX = 0;
-            var lastScreenY = 0;
+            var lastScreenX = null;
+            var lastScreenY = null;
 
             function resetTestState() {
-                startSummation = false;
-                lastScreenX = 0;
-                lastScreenY = 0;
+                lastScreenX = null;
+                lastScreenY = null;
             }
 
+            var nonPointermoveEventList = [
+                  "pointerover",
+                  "pointerenter",
+                  "pointerdown",
+                  "pointerup",
+                  "pointerout",
+                  "pointerleave",
+                  "gotpointercapture",
+                  "lostpointercapture"];
+
             function injectInput(pointerType) {
                 var pointerId = pointerType + "Pointer1";
                 return new test_driver.Actions()
                                      .addPointer(pointerId, pointerType)
                                      .pointerMove(0, 0, {origin: box1})
                                      .pointerDown()
                                      .pointerMove(20, 30, {origin: box1})
-                                     .pointerMove(60, 40, {origin: box1})
+                                     .pointerMove(50, 40, {origin: box1})
+                                     .pointerMove(80, 30, {origin: box1})
+                                     .pointerMove(110, 20, {origin: box1})
                                      .pointerMove(0, 0, {origin: box2})
                                      .pointerUp()
                                      .send();
             }
 
             function run() {
                 var test_pointerEvent = setup_pointerevent_test("pointerevent attributes", ALL_POINTERS);
 
                 [document, document.getElementById('innerFrame').contentDocument].forEach(function(element) {
+                  nonPointermoveEventList.forEach(function(eventName) {
+                    on_event(element, eventName, function (event) {
+                      if (lastScreenX && lastScreenY) {
+                        test_pointerEvent.step(function() {
+                          assert_equals(event.movementX, 0, "movementX should be 0 for event other than pointermove.");
+                          assert_equals(event.movementY, 0, "movementY should be 0 for event other than pointermove.");
+                        });
+                        // Reset when entering the new frame.
+                        if (event.type == "pointerenter") {
+                          lastScreenX = null;
+                          lastScreenY = null;
+                        }
+                      }
+                    });
+                  });
+
                   on_event(element, 'pointermove', function (event) {
-                    if (startSummation) {
-                      test_pointerEvent.step(function() {
+                    test_pointerEvent.step(function() {
+                      if (lastScreenX && lastScreenY) {
                         assert_equals(event.movementX, event.screenX - lastScreenX, "movementX should be the delta between current event's and last event's screenX");
                         assert_equals(event.movementY, event.screenY - lastScreenY, "movementY should be the delta between current event's and last event's screenY");
-                      });
-                      lastScreenX = event.screenX;
-                      lastScreenY = event.screenY;
-                    }
+                      }
+                    });
+                    lastScreenX = event.screenX;
+                    lastScreenY = event.screenY;
                   });
                 });
                 on_event(document.querySelector('#box1'), 'pointerdown', function(event) {
                   event.target.releasePointerCapture(event.pointerId);
                   test_pointerEvent.step(function() {
                       assert_equals(event.pointerType, expectedPointerType, "Use the instructed pointer type.");
                   });
-                  startSummation = true;
                   lastScreenX = event.screenX;
                   lastScreenY = event.screenY;
                 });
                 on_event(document.querySelector('#box2'), 'pointerup', function(event) {
-                  startSummation = false;
                   test_pointerEvent.done();
                 });
 
                 // Inject input
                 injectInput("mouse").then(function(){
                   return injectInput("touch")
                 }).then(function() {
                   return injectInput("pen")
--- a/testing/web-platform/tests/resources/SVGAnimationTestCase-testharness.js
+++ b/testing/web-platform/tests/resources/SVGAnimationTestCase-testharness.js
@@ -1,10 +1,10 @@
 // NOTE(edvardt):
-// This file is a slimmed down wrapper for the Chromium SVGAnimationTestCase.js,
+// This file is a slimmed down wrapper for the old SVGAnimationTestCase.js,
 // it has some convenience functions and should not be used for new tests.
 // New tests should not build on this API as it's just meant to keep things
 // working.
 
 // Helper functions
 const xlinkNS = "http://www.w3.org/1999/xlink"
 
 function expectFillColor(element, red, green, blue) {
@@ -27,16 +27,17 @@ function expectColor(element, red, green
     assert_approx_equals(Number(rgb[2]), green, 2.0);
     assert_approx_equals(Number(rgb[3]), blue, 2.0);
 }
 
 function createSVGElement(type) {
   return document.createElementNS("http://www.w3.org/2000/svg", type);
 }
 
+// Inspired by Layoutests/animations/animation-test-helpers.js
 function moveAnimationTimelineAndSample(index) {
     var animationId = expectedResults[index][0];
     var time = expectedResults[index][1];
     var sampleCallback = expectedResults[index][2];
     var animation = rootSVGElement.ownerDocument.getElementById(animationId);
 
     // If we want to sample the animation end, add a small delta, to reliable point past the end of the animation.
     newTime = time;
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/discard-on-discard.html
@@ -0,0 +1,54 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test the behavior of one discard applied on another discard</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+  <animate id="anim" attributeName="visibility" to="visible" begin="0s" end="5s"/>
+  <rect x="0" y="0" width="50" height="50" fill="rgb(255, 0, 0)">
+    <set id="set1" attributeName="fill" to="rgb(0, 255, 0)" begin="2s" fill="freeze"/>
+    <set id="set2" attributeName="fill" to="rgb(0, 0, 255)" begin="3s" fill="freeze"/>
+  </rect>
+
+  <discard id="discard1" xlink:href="#set1" begin="1s"/>
+  <discard id="discard2" xlink:href="#set2"/>
+  <discard id="discard3" xlink:href="#discard1"/>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+    expectFillColor(rect1, 255, 0, 0);
+}
+
+function sample2() {
+    expectFillColor(rect1, 0, 255, 0);
+}
+
+smil_async_test((t) => {
+    var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+    rect1 = rects[0];
+
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["anim", 0.0,   sample1],
+        ["anim", 0.01,   sample1],
+        ["anim", 2.0,   sample2],
+        ["anim", 2.01,   sample2],
+        ["anim", 3.0,   sample2],
+        ["anim", 3.01,   sample2]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/force-use-shadow-tree-recreation-while-animating.html
@@ -0,0 +1,65 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This test forces use shadow tree recreation while an animating is running</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<defs>
+    <rect id="rect" width="10" height="100" fill="red">
+        <animate id="an1" attributeName="width" fill="freeze" from="10" to="100" begin="0s" dur="4s"/>
+    </rect>
+</defs>
+
+<use xlink:href="#rect"/>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+    assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+    assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+    assert_approx_equals(rect.width.animVal.value, 55, epsilon);
+    assert_equals(rect.width.baseVal.value, 10);
+}
+
+function forceUseShadowTreeRecreation() {
+    rect.setAttribute("fill", "green");
+}
+
+function sample3() {
+    assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+    assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+    rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["an1", 0.0,   sample1],
+        ["an1", 1.999, sample2],
+        ["an1", 2.0,   forceUseShadowTreeRecreation],
+        ["an1", 2.001, sample2],
+        ["an1", 4.0,   sample3],
+        ["an1", 60.0,  sample3],
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/multiple-animations-ending.html
@@ -0,0 +1,421 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This checks the effect on multiple animations ending on one target</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- Test that the first element can end while others continue without crashing, and the second
+     can end and remain frozen. Also test that a third element can animate after the second has ended
+     but that the result is still to return to the second animation's freeze position. -->
+<rect x='0' y='0' width='50' height='50' fill='green'>
+    <animate id="an1" attributeName='x' from='0' to='100' begin='0s' dur='1s' />
+    <animate id="an2" attributeName='x' from='200' to='250' begin='1.5s' dur='1s' fill='freeze' />
+    <animate id="an3" attributeName='x' from='50' to='0' begin='2.5s' dur='0.5s' />
+</rect>
+
+<!-- Test that a second element can take priority over the first from 0-1s, then
+     test that the first element can animate for 1s, and finally test that the
+     second element can once again animate after the first has ended. After all
+     animations end, test that they are removed and the rect returns to its home. -->
+<rect x='200' y='75' width='50' height='50' fill='green'>
+    <animate id="an4" attributeName='x' from='0' to='10' begin='1s' dur='1s'/>
+    <animate id="an5" attributeName='x' from='100' to='0' begin='0s' dur='2.5s'/>
+</rect>
+
+<!-- Test that a repeating animation can take priority over another animation, and that the
+     end state is the second animation's freeze value. Also test that, after a pause, a third
+     animation can take over and have its freeze value satisfied at the end. -->
+<rect x='0' y='150' width='50' height='50' fill='green'>
+    <animate id="an6" attributeName='x' from='200' to='240' begin='0s' dur='2s' fill='freeze'/>
+    <animate id="an7" attributeName='x' from='0' to='5' begin='1s' dur='0.1s' repeatCount="5" fill='freeze'/>
+    <animate id="an8" attributeName='x' from='250' to='150' begin='3s' dur='1s' fill='freeze'/>
+</rect>
+
+<!-- Test that 4 animations can animate a rect in 20px 'steps' and that correct freeze values are
+     honored even though the animation elements are specified in non-sequential order. Also test
+     that two repeating animations (active for only a short duration) only momentarily
+     affect the overall animation and are correctly removed. -->
+<rect x='0' y='225' width='50' height='50' fill='green'>
+    <animate id="an9" attributeName='x' from='200' to='250' begin='1.6s' dur='0.1s' repeatCount="2" fill='remove'/>
+    <animate id="anA" attributeName='x' from='160' to='180' begin='3s' dur='0.5s' fill='freeze'/>
+    <animate id="anB" attributeName='x' from='110' to='130' begin='2s' dur='0.5s' fill='freeze'/>
+    <animate id="anC" attributeName='x' from='10' to='30' begin='0s' dur='0.5s' fill='freeze'/>
+    <animate id="anD" attributeName='x' from='60' to='80' begin='1s' dur='0.5s' fill='freeze'/>
+    <animate id="anE" attributeName='x' from='200' to='250' begin='3.6s' dur='0.1s' repeatCount="2" fill='remove'/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+    assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 100, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 200, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 10, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample2() {
+    assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 80, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 210, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 30, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample3() {
+    assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 80, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 210, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 30, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample4() {
+    assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 80, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 210, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 30, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample5() {
+    assert_approx_equals(rect1.x.animVal.value, 100, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 60, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 220, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 30, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample6() {
+    assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 0, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 0, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 60, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample7() {
+    assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 0, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 0, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 60, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample8() {
+    assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 5, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 80, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample9() {
+    assert_approx_equals(rect1.x.animVal.value, 200, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 5, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 80, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample10() {
+    assert_approx_equals(rect1.x.animVal.value, 200, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 5, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 80, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample11() {
+    assert_approx_equals(rect1.x.animVal.value, 225, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 10, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 80, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample12() {
+    assert_approx_equals(rect1.x.animVal.value, 225, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 20, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 110, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample13() {
+    assert_approx_equals(rect1.x.animVal.value, 225, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 20, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 110, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample14() {
+    assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 0, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 130, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample15() {
+    assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 130, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample16() {
+    assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 130, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample17() {
+    assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 5, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 130, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample18() {
+    assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 250, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 160, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample19() {
+    assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 250, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 160, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample20() {
+    assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 200, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 180, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample21() {
+    assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 200, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 180, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample22() {
+    assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 150, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 180, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+function sample23() {
+    assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+    assert_equals(rect2.x.baseVal.value, 200);
+
+    assert_approx_equals(rect3.x.animVal.value, 150, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+
+    assert_approx_equals(rect4.x.animVal.value, 180, epsilon);
+    assert_equals(rect4.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+    var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+    rect1 = rects[0];
+    rect2 = rects[1];
+    rect3 = rects[2];
+    rect4 = rects[3];
+
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["an1", 0.0,   sample1],
+        ["an1", 0.499, sample2],
+        ["an1", 0.5,   sample3],
+        ["an1", 0.501, sample4],
+        ["an1", 0.999, sample5],
+        ["an1", 1.0,   sample6],
+        ["an1", 1.001, sample7],
+        ["an1", 1.499, sample8],
+        ["an1", 1.5,   sample9],
+        ["an1", 1.501, sample10],
+        ["an1", 1.999, sample11],
+        ["an1", 2.0,   sample12],
+        ["an1", 2.001, sample13],
+        ["an1", 2.499, sample14],
+        ["an1", 2.5,   sample15],
+        ["an1", 2.501, sample16],
+        ["an1", 2.999, sample17],
+        ["an1", 3.0,   sample18],
+        ["an1", 3.001, sample19],
+        ["an1", 3.499, sample20],
+        ["an1", 3.5,   sample21],
+        ["an1", 4.0,   sample22],
+        ["an1", 9.0,   sample23]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/multiple-animations-fill-freeze.html
@@ -0,0 +1,149 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This checks the effect on multiple animations on one target</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<rect x='0' y='0' width='50' height='50' fill='green'>
+    <animate id="an1" attributeName='x' from='0' to='100' begin='0s' dur='2s' fill='freeze'/>
+    <animate id="an2" attributeName='x' from='150' to='250' begin='4s' dur='2s' fill='freeze'/>
+</rect>
+
+<rect x='0' y='100' width='50' height='50' fill='green'>
+    <animate id="an3" attributeName='x' from='0' to='100' begin='0s' dur='2s' fill='remove'/>
+    <animate id="an4" attributeName='x' from='150' to='250' begin='4s' dur='2s' fill='freeze'/>
+</rect>
+
+<rect x='0' y='200' width='50' height='50' fill='green'>
+    <animate id="an5" attributeName='x' from='0' to='100' begin='0s' dur='2s' fill='freeze'/>
+    <animate id="an6" attributeName='x' from='150' to='250' begin='4s' dur='2s' fill='remove'/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+    assert_approx_equals(rect1.x.animVal.value, 0, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 0, epsilon);
+    assert_equals(rect2.x.baseVal.value, 0);
+
+    assert_approx_equals(rect3.x.animVal.value, 0, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample2() {
+    assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 50, epsilon);
+    assert_equals(rect2.x.baseVal.value, 0);
+
+    assert_approx_equals(rect3.x.animVal.value, 50, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample3() {
+    assert_approx_equals(rect1.x.animVal.value, 100, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 100, epsilon);
+    assert_equals(rect2.x.baseVal.value, 0);
+
+    assert_approx_equals(rect3.x.animVal.value, 100, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample4() {
+    assert_approx_equals(rect1.x.animVal.value, 100, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 0, epsilon);
+    assert_equals(rect2.x.baseVal.value, 0);
+
+    assert_approx_equals(rect3.x.animVal.value, 100, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample5() {
+    assert_approx_equals(rect1.x.animVal.value, 150, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 150, epsilon);
+    assert_equals(rect2.x.baseVal.value, 0);
+
+    assert_approx_equals(rect3.x.animVal.value, 150, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample6() {
+    assert_approx_equals(rect1.x.animVal.value, 200, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 200, epsilon);
+    assert_equals(rect2.x.baseVal.value, 0);
+
+    assert_approx_equals(rect3.x.animVal.value, 200, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample7() {
+    assert_approx_equals(rect1.x.animVal.value, 250, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 250, epsilon);
+    assert_equals(rect2.x.baseVal.value, 0);
+
+    assert_approx_equals(rect3.x.animVal.value, 250, epsilon);
+    assert_equals(rect3.x.baseVal.value, 0);
+}
+
+function sample8() {
+    assert_equals(rect1.x.animVal.value, 250);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_equals(rect2.x.animVal.value, 250);
+    assert_equals(rect2.x.baseVal.value, 0);
+
+    assert_equals(rect3.x.animVal.value, 100);
+    assert_equals(rect3.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+    var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+    rect1 = rects[0];
+    rect2 = rects[1];
+    rect3 = rects[2];
+
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["an1", 0.0,   sample1],
+        ["an1", 1.0,   sample2],
+        ["an1", 1.999, sample3],
+        ["an1", 2.001, sample4],
+        ["an1", 3.0,   sample4],
+        ["an1", 3.999, sample4],
+        ["an1", 4.0,   sample5],
+        ["an1", 5.0,   sample6],
+        ["an1", 5.999, sample7],
+        ["an1", 6.001, sample8],
+        ["an1", 60.0,  sample8]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/multiple-begin-additive-animation.html
@@ -0,0 +1,136 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests additive='sum' support on animate elements with multiple begin times</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
+<rect width="100" height="100" fill="green">
+    <animate id="an1" attributeName="y" attributeType="XML" begin="0s" dur="12s" from="100" to="900" fill="freeze" />
+    <animate attributeName="x" attributeType="XML" calcMode="discrete" begin="0s; 2s" from="0" to="400" dur="8s" additive="sum" />
+</rect>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function checkBaseValues() {
+return;
+    assert_equals(rect.x.baseVal.value, 0);
+    assert_equals(rect.y.baseVal.value, 0);
+}
+
+function sample1() {
+    assert_equals(rect.x.animVal.value, 0);
+    assert_approx_equals(rect.y.animVal.value, 100, epsilon);
+    checkBaseValues();
+}
+
+function sample2() {
+    assert_equals(rect.x.animVal.value, 0);
+    assert_approx_equals(rect.y.animVal.value, 166.67, epsilon);
+    checkBaseValues();
+}
+
+function sample3() {
+    assert_equals(rect.x.animVal.value, 0);
+    assert_approx_equals(rect.y.animVal.value, 366.60, epsilon);
+    checkBaseValues();
+}
+
+function sample4() {
+    assert_equals(rect.x.animVal.value, 0);
+    assert_approx_equals(rect.y.animVal.value, 366.73, epsilon);
+    checkBaseValues();
+}
+
+function sample5() {
+    assert_equals(rect.x.animVal.value, 0);
+    assert_approx_equals(rect.y.animVal.value, 499.93, epsilon);
+    checkBaseValues();
+}
+
+function sample6() {
+    assert_equals(rect.x.animVal.value, 400);
+    assert_approx_equals(rect.y.animVal.value, 500.06, epsilon);
+    checkBaseValues();
+}
+
+function sample7() {
+    assert_equals(rect.x.animVal.value, 400);
+    assert_approx_equals(rect.y.animVal.value, 566.67, epsilon);
+    checkBaseValues();
+}
+
+function sample8() {
+    assert_equals(rect.x.animVal.value, 400);
+    assert_approx_equals(rect.y.animVal.value, 633.33, epsilon);
+    checkBaseValues();
+}
+
+function sample9() {
+    assert_equals(rect.x.animVal.value, 400);
+    assert_approx_equals(rect.y.animVal.value, 700, epsilon);
+    checkBaseValues();
+}
+
+function sample10() {
+    assert_equals(rect.x.animVal.value, 400);
+    assert_approx_equals(rect.y.animVal.value, 766.60, epsilon);
+    checkBaseValues();
+}
+
+function sample11() {
+    assert_equals(rect.x.animVal.value, 0);
+    assert_approx_equals(rect.y.animVal.value, 766.67, epsilon);
+    checkBaseValues();
+}
+
+function sample12() {
+    assert_equals(rect.x.animVal.value, 0);
+    assert_approx_equals(rect.y.animVal.value, 833.33, epsilon);
+    checkBaseValues();
+}
+
+function sample13() {
+    assert_equals(rect.x.animVal.value, 0);
+    assert_approx_equals(rect.y.animVal.value, 900, epsilon);
+    checkBaseValues();
+}
+
+smil_async_test((t) => {
+    rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+    // All animations in the test file use the same duration, so it's not needed to list all sample points individually for an5/an6/an7/an8.
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["an1", 0.0,    sample1],
+        ["an1", 1.0,    sample2],
+        ["an1", 3.999,  sample3],
+        ["an1", 4.001,  sample4],
+        ["an1", 5.999,  sample5],
+        ["an1", 6.001,  sample6],
+        ["an1", 7.0,    sample7],
+        ["an1", 7.999,  sample8],
+        ["an1", 8.001,  sample8],
+        ["an1", 9.0,    sample9],
+        ["an1", 9.999,  sample10],
+        ["an1", 10.001, sample11],
+        ["an1", 11.0,   sample12],
+        ["an1", 11.999, sample13],
+        ["an1", 12.001, sample13],
+        ["an1", 60.0,   sample13]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/non-additive-type-by-animation.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This by animation for all non-additive property types - should have no effect.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg id="svg" viewBox="0 0 200 200" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs>
+    <filter id="filter">
+        <feConvolveMatrix id="feConvolveMatrix" kernelMatrix="0 1 0   0 1 0   0 1 0" order="6 6" targetX="5" preserveAlpha="false"/>
+    </filter>
+</defs>
+
+<rect id="rect" y="100" width="100" height="100" fill="black" filter="url(#filter)"/>
+
+<!-- AnimatedBoolean -->
+<animate id="an1" xlink:href="#feConvolveMatrix" attributeName="preserveAlpha" begin="0s" dur="4s" by="true" fill="freeze"/>
+
+<!-- AnimatedEnumeration -->
+<animate xlink:href="#filter" attributeName="filterUnits" begin="0s" dur="4s" by="userSpaceOnUse" fill="freeze"/>
+
+<!-- AnimatedPreserveAspectRatio -->
+<animate xlink:href="#svg" attributeName="preserveAspectRatio" begin="0s" dur="4s" by="xMaxYMax slice" fill="freeze"/>
+
+<!-- AnimatedString -->
+<animate xlink:href="#feConvolveMatrix" attributeName="result" begin="0s" dur="4s" by="test" fill="freeze"/>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample() {
+    assert_equals(feConvolveMatrix.preserveAlpha.animVal, false);
+    assert_equals(filter.filterUnits.animVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+    assert_equals(svg.preserveAspectRatio.animVal.align, SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE);
+    assert_equals(svg.preserveAspectRatio.animVal.meetOrSlice, SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET);
+    assert_equals(feConvolveMatrix.result.animVal, "");
+
+    assert_equals(feConvolveMatrix.preserveAlpha.baseVal, false);
+    assert_equals(filter.filterUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+    assert_equals(svg.preserveAspectRatio.baseVal.align, SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE);
+    assert_equals(svg.preserveAspectRatio.baseVal.meetOrSlice, SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET);
+    assert_equals(feConvolveMatrix.result.baseVal, "");
+}
+
+smil_async_test((t) => {
+    filter = rootSVGElement.ownerDocument.getElementsByTagName("filter")[0];
+    feConvolveMatrix = rootSVGElement.ownerDocument.getElementsByTagName("feConvolveMatrix")[0];
+    svg = rootSVGElement.ownerDocument.getElementsByTagName("svg")[0];
+
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["an1", 0.0,   sample],
+        ["an1", 1.999, sample],
+        ["an1", 2.001, sample],
+        ["an1", 3.999, sample],
+        ["an1", 4.001, sample]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/non-additive-type-from-by-animation.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This is a from by animation for all non-additive property types - should have no effect.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg id="svg" viewBox="0 0 200 200" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<defs>
+    <filter id="filter">
+        <feConvolveMatrix id="feConvolveMatrix" kernelMatrix="0 1 0   0 1 0   0 1 0" order="6 6" targetX="5" preserveAlpha="false"/>
+    </filter>
+</defs>
+
+<rect id="rect" y="100" width="100" height="100" fill="black" filter="url(#filter)"/>
+
+<!-- AnimatedBoolean -->
+<animate id="an1" xlink:href="#feConvolveMatrix" attributeName="preserveAlpha" begin="0s" dur="4s" from="false" by="true" fill="freeze"/>
+
+<!-- AnimatedEnumeration -->
+<animate xlink:href="#filter" attributeName="filterUnits" begin="0s" dur="4s" from="objectBoundingBox" by="userSpaceOnUse" fill="freeze"/>
+
+<!-- AnimatedPreserveAspectRatio -->
+<animate xlink:href="#svg" attributeName="preserveAspectRatio" begin="0s" dur="4s" from="xMaxYMax meet" by="xMaxYMax slice" fill="freeze"/>
+
+<!-- AnimatedString -->
+<animate xlink:href="#feConvolveMatrix" attributeName="result" begin="0s" dur="4s" from="foo" by="test" fill="freeze"/>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample() {
+    assert_equals(feConvolveMatrix.preserveAlpha.animVal, false);
+    assert_equals(filter.filterUnits.animVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+    assert_equals(svg.preserveAspectRatio.animVal.align, SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE);
+    assert_equals(svg.preserveAspectRatio.animVal.meetOrSlice, SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET);
+    assert_equals(feConvolveMatrix.result.animVal, "");
+
+    assert_equals(feConvolveMatrix.preserveAlpha.baseVal, false);
+    assert_equals(filter.filterUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+    assert_equals(svg.preserveAspectRatio.baseVal.align, SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_NONE);
+    assert_equals(svg.preserveAspectRatio.baseVal.meetOrSlice, SVGPreserveAspectRatio.SVG_MEETORSLICE_MEET);
+    assert_equals(feConvolveMatrix.result.baseVal, "");
+}
+
+smil_async_test((t) => {
+    filter = rootSVGElement.ownerDocument.getElementsByTagName("filter")[0];
+    feConvolveMatrix = rootSVGElement.ownerDocument.getElementsByTagName("feConvolveMatrix")[0];
+    svg = rootSVGElement.ownerDocument.getElementsByTagName("svg")[0];
+
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["an1", 0.0,   sample],
+        ["an1", 1.999, sample],
+        ["an1", 2.001, sample],
+        ["an1", 3.999, sample],
+        ["an1", 4.001, sample]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/remove-animation-element-while-animation-is-running.html
@@ -0,0 +1,85 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This removes an animation element while the animation is running</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<rect x='0' y='0' width='50' height='50' fill='green'>
+    <animate id="an1" attributeName='x' from='50' to='150' begin='0s' dur='2s' fill='freeze'/>
+</rect>
+
+<rect x='0' y='100' width='50' height='50' fill='green'>
+    <animate id="an2" attributeName='x' from='50' to='150' begin='0s' dur='2s' fill='remove'/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+    assert_approx_equals(rect1.x.animVal.value, 50, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 50, epsilon);
+    assert_equals(rect2.x.baseVal.value, 0);
+}
+
+function sample2() {
+    assert_approx_equals(rect1.x.animVal.value, 100, epsilon);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 100, epsilon);
+    assert_equals(rect2.x.baseVal.value, 0);
+
+    // Remove the animation element animating rect1
+    // The effect is that rect1 is now reset to the initial state, before any animation was applied to it.
+    // Compatible with FF. In Opera it shows a repainting bug currently (two rects are visible!).
+    var an1 = rootSVGElement.ownerDocument.getElementById("an1");
+    an1.parentNode.removeChild(an1);
+}
+
+function sample3() {
+    assert_equals(rect1.x.animVal.value, 0);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_approx_equals(rect2.x.animVal.value, 100, epsilon);
+    assert_equals(rect2.x.baseVal.value, 0);
+}
+
+function sample4() {
+    assert_equals(rect1.x.animVal.value, 0);
+    assert_equals(rect1.x.baseVal.value, 0);
+
+    assert_equals(rect2.x.animVal.value, 0);
+    assert_equals(rect2.x.baseVal.value, 0);
+}
+
+smil_async_test((t) => {
+    var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+    rect1 = rects[0];
+    rect2 = rects[1];
+
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["an1", 0.0,   sample1],
+        ["an1", 1.0,   sample2],
+        ["an2", 1.001, sample3],
+        ["an2", 2.001, sample4],
+        ["an2", 60.0,  sample4]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/repeatn-remove-add-animation.html
@@ -0,0 +1,100 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This removes and adds an animation element while the animation is repeating</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+  <animate id="anim" attributeName="visibility" to="visible" begin="0s" dur="2s" repeatCount="4"/>
+  <rect x="0" y="0" width="100" height="100" fill="rgb(0, 255, 0)">
+    <set attributeName="fill" to="rgb(255, 0, 0)" begin="anim.repeat(0)"/>
+  </rect>
+  <rect x="200" y="0" width="100" height="100" fill="rgb(255, 0, 0)">
+    <set attributeName="fill" to="rgb(0, 255, 0)" begin="anim.repeat(1)"/>
+  </rect>
+  <rect x="0" y="200" width="100" height="100" fill="rgb(255, 0, 0)">
+    <set attributeName="fill" to="rgb(0, 255, 0)" begin="anim.repeat(2)"/>
+  </rect>
+  <rect x="200" y="200" width="100" height="100" fill="rgb(255, 0, 0)">
+    <set attributeName="fill" to="rgb(0, 255, 0)" begin="anim.repeat(3)"/>
+  </rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+    expectFillColor(rect1, 0, 255, 0);
+    expectFillColor(rect2, 255, 0, 0);
+    expectFillColor(rect3, 255, 0, 0);
+    expectFillColor(rect4, 255, 0, 0);
+}
+
+function sample2() {
+    expectFillColor(rect1, 0, 255, 0);
+    expectFillColor(rect2, 0, 255, 0);
+    expectFillColor(rect3, 255, 0, 0);
+    expectFillColor(rect4, 255, 0, 0);
+}
+
+function sample3() {
+    expectFillColor(rect1, 0, 255, 0);
+    expectFillColor(rect2, 0, 255, 0);
+    expectFillColor(rect3, 0, 255, 0);
+    expectFillColor(rect4, 255, 0, 0);
+}
+
+function sample4() {
+    expectFillColor(rect1, 0, 255, 0);
+    expectFillColor(rect2, 0, 255, 0);
+    expectFillColor(rect3, 0, 255, 0);
+    expectFillColor(rect4, 0, 255, 0);
+}
+
+function recreate() {
+    var anim1 = rootSVGElement.ownerDocument.getElementById("anim");
+    anim1.parentNode.removeChild(anim1);
+    var anim2 = createSVGElement("animate");
+    anim2.setAttribute("id", "anim");
+    anim2.setAttribute("attributeName", "visibility");
+    anim2.setAttribute("to", "visible");
+    anim2.setAttribute("begin", "0s");
+    anim2.setAttribute("dur", "2s");
+    anim2.setAttribute("repeatCount", "4");
+    rootSVGElement.appendChild(anim2);
+}
+
+smil_async_test((t) => {
+    var rects = rootSVGElement.ownerDocument.getElementsByTagName("rect");
+    rect1 = rects[0];
+    rect2 = rects[1];
+    rect3 = rects[2];
+    rect4 = rects[3];
+
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["anim", 0.0, sample1],
+        ["anim", 0.001, sample1],
+        ["anim", 2.0, sample1],
+        ["anim", 2.001, sample2],
+        ["anim", 4.0, sample2],
+        ["anim", 4.001, sample3],
+        ["anim", 5.0, recreate],
+        ["anim", 6.0, sample3],
+        ["anim", 6.001, sample4]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/single-values-animation.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>This tests values animation with just a single entry</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+
+<!-- an1: Change width immediately to 100 at 2s -->
+<rect width="10" height="100" fill="green">
+    <animate id="an1" attributeType="XML" attributeName="width" fill="freeze" values="100" begin="2s"/>
+</rect>
+
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup animation test
+function sample1() {
+    assert_approx_equals(rect.width.animVal.value, 10, epsilon);
+    assert_equals(rect.width.baseVal.value, 10);
+}
+
+function sample2() {
+    assert_approx_equals(rect.width.animVal.value, 100, epsilon);
+    assert_equals(rect.width.baseVal.value, 10);
+}
+
+smil_async_test((t) => {
+    rect = rootSVGElement.ownerDocument.getElementsByTagName("rect")[0];
+
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["an1", 0.0,  sample1],
+        ["an1", 2.0,  sample2],
+        ["an1", 4.0,  sample2],
+        ["an1", 60.0, sample2]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+window.animationStartsImmediately = true;
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-deg-to-grad.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from deg to grad.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0deg");
+animate.setAttribute("to", "200grad");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["animation", 0.0,   sample1],
+        ["animation", 2.0,   sample2],
+        ["animation", 3.999, sample3],
+        ["animation", 4.001, sample1]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-deg-to-rad.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from deg to rad.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0deg");
+animate.setAttribute("to", "3.14159265rad");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["animation", 0.0,   sample1],
+        ["animation", 2.0,   sample2],
+        ["animation", 3.999, sample3],
+        ["animation", 4.001, sample1]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-grad-to-deg.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from grad to deg.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0grad");
+animate.setAttribute("to", "180deg");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["animation", 0.0,   sample1],
+        ["animation", 2.0,   sample2],
+        ["animation", 3.999, sample3],
+        ["animation", 4.001, sample1]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-grad-to-rad.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from grad to rad.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0grad");
+animate.setAttribute("to", "3.14159265rad");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["animation", 0.0,   sample1],
+        ["animation", 2.0,   sample2],
+        ["animation", 3.999, sample3],
+        ["animation", 4.001, sample1]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-rad-to-deg.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from rad to deg.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0rad");
+animate.setAttribute("to", "180deg");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["animation", 0.0,   sample1],
+        ["animation", 2.0,   sample2],
+        ["animation", 3.999, sample3],
+        ["animation", 4.001, sample1]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgangle-animation-rad-to-grad.html
@@ -0,0 +1,93 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Tests SVGAngle animation from rad to grad.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "4");
+marker.setAttribute("markerHeight", "3");
+marker.setAttribute("markerUnits", "strokeWidth");
+marker.setAttribute("refX", "1");
+marker.setAttribute("refY", "5");
+marker.setAttribute("orient", "0deg");
+defs.appendChild(marker);
+
+var polyline = createSVGElement("polyline");
+polyline.setAttribute("id", "polyline");
+polyline.setAttribute("points", "0,0 10,5 0,10 1,5");
+polyline.setAttribute("fill", "green");
+marker.appendChild(polyline);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("d", "M45,50 L55,50");
+path.setAttribute("stroke-width","10");
+path.setAttribute("stroke", "green");
+path.setAttribute("marker-end", "url(#marker)");
+path.setAttribute("onclick", "executeTest()");
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "orient");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "0rad");
+animate.setAttribute("to", "200grad");
+marker.appendChild(animate);
+rootSVGElement.appendChild(defs);
+rootSVGElement.appendChild(path);
+
+// Setup animation test
+function sample1() {
+    // Check initial/end conditions
+    assert_approx_equals(marker.orientAngle.animVal.value, 0, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample2() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 90, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+function sample3() {
+    assert_approx_equals(marker.orientAngle.animVal.value, 180, epsilon);
+    assert_equals(marker.orientAngle.baseVal.value, 0);
+
+    assert_equals(marker.orientType.animVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+    assert_equals(marker.orientType.baseVal, SVGMarkerElement.SVG_MARKER_ORIENT_ANGLE);
+}
+
+smil_async_test((t) => {
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["animation", 0.0,   sample1],
+        ["animation", 2.0,   sample2],
+        ["animation", 3.999, sample3],
+        ["animation", 4.001, sample1]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgboolean-animation-1.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test 'to' animation of SVGBoolean.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var filter = createSVGElement("filter");
+filter.setAttribute("id", "filter");
+defs.appendChild(filter);
+
+var feConvolveMatrix = createSVGElement("feConvolveMatrix");
+feConvolveMatrix.setAttribute("id", "effect");
+feConvolveMatrix.setAttribute("kernelMatrix", "0 0 0   0 1 0   0 0 0");
+feConvolveMatrix.setAttribute("preserveAlpha", "false");
+filter.appendChild(feConvolveMatrix);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "green");
+rect.setAttribute("filter", "url(#filter)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "preserveAlpha");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "false");
+animate.setAttribute("to", "true");
+feConvolveMatrix.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+    assert_equals(feConvolveMatrix.preserveAlpha.animVal, false);
+    assert_equals(feConvolveMatrix.preserveAlpha.baseVal, false);
+}
+
+function sample2() {
+    assert_equals(feConvolveMatrix.preserveAlpha.animVal, false);
+    assert_equals(feConvolveMatrix.preserveAlpha.baseVal, false);
+}
+
+function sample3() {
+    assert_equals(feConvolveMatrix.preserveAlpha.animVal, true);
+    assert_equals(feConvolveMatrix.preserveAlpha.baseVal, false);
+}
+
+smil_async_test((t) => {
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["animation", 0.0,   sample1],
+        ["animation", 2.0,   sample2],
+        ["animation", 3.999, sample3],
+        ["animation", 4.001, sample1]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-1.html
@@ -0,0 +1,76 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGUnitTypes enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var defs = createSVGElement("defs");
+rootSVGElement.appendChild(defs);
+
+var pattern = createSVGElement("pattern");
+pattern.setAttribute("id", "pattern");
+pattern.setAttribute("patternUnits", "userSpaceOnUse");
+pattern.setAttribute("patternContentUnits", "userSpaceOnUse");
+pattern.setAttribute("width", "50");
+pattern.setAttribute("height", "50");
+defs.appendChild(pattern);
+
+var patternChild = createSVGElement("rect");
+patternChild.setAttribute("width", "1");
+patternChild.setAttribute("height", "1");
+patternChild.setAttribute("fill", "green");
+pattern.appendChild(patternChild);
+
+var rect = createSVGElement("rect");
+rect.setAttribute("id", "rect");
+rect.setAttribute("width", "100");
+rect.setAttribute("height", "100");
+rect.setAttribute("fill", "url(#pattern)");
+rect.setAttribute("onclick", "executeTest()");
+rootSVGElement.appendChild(rect);
+
+var animate = createSVGElement("animate");
+animate.setAttribute("id", "animation");
+animate.setAttribute("attributeName", "patternContentUnits");
+animate.setAttribute("begin", "0s");
+animate.setAttribute("dur", "4s");
+animate.setAttribute("from", "userSpaceOnUse");
+animate.setAttribute("to", "objectBoundingBox");
+animate.setAttribute("fill", "freeze");
+pattern.appendChild(animate);
+
+// Setup animation test
+function sample1() {
+    assert_equals(pattern.patternContentUnits.animVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+    assert_equals(pattern.patternContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+}
+
+function sample2() {
+    assert_equals(pattern.patternContentUnits.animVal, SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX);
+    assert_equals(pattern.patternContentUnits.baseVal, SVGUnitTypes.SVG_UNIT_TYPE_USERSPACEONUSE);
+}
+
+smil_async_test((t) => {
+    const expectedValues = [
+        // [animationId, time, sampleCallback]
+        ["animation", 0.0,   sample1],
+        ["animation", 1.999, sample1],
+        ["animation", 2.001, sample2],
+        ["animation", 3.999, sample2],
+        ["animation", 4.001, sample2]
+    ];
+
+    runAnimationTest(t, expectedValues);
+});
+
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/animations/svgenum-animation-10.html
@@ -0,0 +1,81 @@
+<!doctype html>
+<html>
+<meta charset="utf-8">
+<title>Test SVGMarkerUnitsType enumeration animations</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/SVGAnimationTestCase-testharness.js"></script>
+
+<svg>
+</svg>
+
+<script>
+var rootSVGElement = document.querySelector("svg");
+var epsilon = 1.0;
+
+// Setup test document
+var marker = createSVGElement("marker");
+marker.setAttribute("id", "marker");
+marker.setAttribute("viewBox", "0 0 10 10");
+marker.setAttribute("markerWidth", "2");
+marker.setAttribute("markerHeight", "2");
+marker.setAttribute("refX", "5");
+marker.setAttribute("refY", "5");
+marker.setAttribute("markerUnits", "userSpaceOnUse");
+
+var markerPath = createSVGElement("path");
+markerPath.setAttribute("fill", "blue");
+markerPath.setAttribute("d", "M 5 0 L 10 10 L 0 10 Z");
+marker.appendChild(markerPath);
+
+var defsElement = createSVGElement("defs");
+defsElement.appendChild(marker);
+rootSVGElement.appendChild(defsElement);
+
+var path = createSVGElement("path");
+path.setAttribute("id", "path");
+path.setAttribute("onclick", "executeTest()");
+path.setAttribute("fill", "none");
+path.setAttri