Merge mozilla-inbound to mozilla-central. a=merge default tip
authorDaniel Varga <dvarga@mozilla.com>
Mon, 19 Nov 2018 19:01:21 +0200
changeset 446992 62c4741625fe
parent 446960 0ceae9db9ec0 (current diff)
parent 446991 4ef55dde9b93 (diff)
push id35064
push userdvarga@mozilla.com
push dateMon, 19 Nov 2018 17:02:31 +0000
treeherdermozilla-central@62c4741625fe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone65.0a1
Merge mozilla-inbound to mozilla-central. a=merge
testing/web-platform/meta/css/filter-effects/css-filters-animation-combined-001.html.ini
testing/web-platform/meta/css/filter-effects/css-filters-animation-drop-shadow.html.ini
testing/web-platform/meta/css/filter-effects/css-filters-animation-hue-rotate.html.ini
testing/web-platform/meta/css/filter-effects/css-filters-animation-saturate.html.ini
testing/web-platform/meta/css/filter-effects/filter-contrast-003.html.ini
testing/web-platform/meta/css/filter-effects/filter-grayscale-002.html.ini
testing/web-platform/meta/css/filter-effects/filter-grayscale-003.html.ini
testing/web-platform/tests/cors/resources/access-control-expose-headers-parsing-2.asis
testing/web-platform/tests/cors/resources/access-control-expose-headers-parsing.asis
testing/web-platform/tests/css/filter-effects/filter-external-002-filter.svg
testing/web-platform/tests/pointerevents/pointerevent_pointermove-manual.html
--- a/browser/components/aboutconfig/content/aboutconfig.css
+++ b/browser/components/aboutconfig/content/aboutconfig.css
@@ -1,12 +1,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#search {
+  position: sticky;
+  top: 0;
+  margin: 10px;
+  box-sizing: border-box;
+  width: calc(100% - 20px);
+  min-width: 644px;
+  background-image: url("chrome://global/skin/icons/search-textbox.svg");
+  background-repeat: no-repeat;
+  background-position: 9px center;
+  background-size: 12px 12px;
+  padding-left: 30px;
+}
+
 #prefs {
   background-color: var(--in-content-box-background);
   color: var(--in-content-text-color);
   margin: 10px;
   min-width: 644px;
   /* To stay consistent with about:preferences (664px - 20px margin). */
   border: 1px solid var(--in-content-box-border-color);
   border-radius: 2px;
--- a/browser/components/aboutconfig/content/aboutconfig.html
+++ b/browser/components/aboutconfig/content/aboutconfig.html
@@ -11,11 +11,12 @@
     <link rel="stylesheet" type="text/css"
           href="chrome://browser/content/aboutconfig/aboutconfig.css">
     <link rel="localization" href="browser/aboutConfig.ftl">
     <script type="application/javascript"
             src="chrome://browser/content/aboutconfig/aboutconfig.js"></script>
     <title data-l10n-id="about-config-title"></title>
   </head>
   <body onload="onLoad();">
+    <input type="text" id="search" data-l10n-id="about-config-search">
     <table id="prefs"></table>
   </body>
 </html>
--- a/browser/components/aboutconfig/content/aboutconfig.js
+++ b/browser/components/aboutconfig/content/aboutconfig.js
@@ -24,18 +24,35 @@ function onLoad() {
     } catch (ex) {
       pref.value = "";
     }
     return pref;
   });
 
   gPrefArray.sort((a, b) => a.name > b.name);
 
+  document.getElementById("search").addEventListener("keypress", function(e) {
+    if (e.code == "Enter") {
+      filterPrefs();
+    }
+  });
+
+  document.getElementById("prefs").appendChild(createPrefsFragment(gPrefArray));
+}
+
+function filterPrefs() {
+  let substring = document.getElementById("search").value.trim();
+  let fragment = createPrefsFragment(gPrefArray.filter(pref => pref.name.includes(substring)));
+  document.getElementById("prefs").textContent = "";
+  document.getElementById("prefs").appendChild(fragment);
+}
+
+function createPrefsFragment(prefArray) {
   let fragment = document.createDocumentFragment();
-  for (let pref of gPrefArray) {
+  for (let pref of prefArray) {
     let row = document.createElement("tr");
     if (pref.hasUserValue) {
       row.classList.add("has-user-value");
     }
     row.setAttribute("aria-label", pref.name);
 
     let nameCell = document.createElement("td");
     // Add <wbr> behind dots to prevent line breaking in random mid-word places.
@@ -48,10 +65,10 @@ function onLoad() {
 
     let valueCell = document.createElement("td");
     valueCell.classList.add("cell-value");
     valueCell.textContent = pref.value;
     row.appendChild(valueCell);
 
     fragment.appendChild(row);
   }
-  document.getElementById("prefs").appendChild(fragment);
+  return fragment;
 }
--- a/browser/components/aboutconfig/content/aboutconfig.notftl
+++ b/browser/components/aboutconfig/content/aboutconfig.notftl
@@ -1,5 +1,8 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 about-config-title = about:config
+
+about-config-search =
+    .placeholder = Search
--- a/browser/components/aboutconfig/test/browser/browser.ini
+++ b/browser/components/aboutconfig/test/browser/browser.ini
@@ -1,3 +1,5 @@
 [DEFAULT]
 
 [browser_basic.js]
+[browser_search.js]
+skip-if = debug # Bug 1507747
new file mode 100644
--- /dev/null
+++ b/browser/components/aboutconfig/test/browser/browser_search.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+ChromeUtils.import("resource://gre/modules/Preferences.jsm", this);
+
+const PAGE_URL = "chrome://browser/content/aboutconfig/aboutconfig.html";
+
+add_task(async function setup() {
+  await SpecialPowers.pushPrefEnv({
+    set: [
+      ["test.aboutconfig.a", "test value 1"],
+      ["test.aboutconfig.ab", "test value 2"],
+      ["test.aboutconfig.b", "test value 3"],
+    ],
+  });
+});
+
+add_task(async function test_search() {
+  await BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: PAGE_URL,
+  }, async browser => {
+    let prefArray = Services.prefs.getChildList("");
+
+    // Test page loaded with correct number of prefs.
+    await ContentTask.spawn(browser, prefArray, aPrefArray => {
+      Assert.equal(content.document.getElementById("prefs").childElementCount,
+                   aPrefArray.length);
+
+      // Test page search of "button" returns correct number of preferences.
+      let search = content.document.getElementById("search");
+      search.value = "button   ";
+      search.focus();
+    });
+
+    EventUtils.sendKey("return");
+    await ContentTask.spawn(browser, prefArray, aPrefArray => {
+      let filteredPrefArray =
+          aPrefArray.filter(pref => pref.includes("button"));
+      Assert.equal(content.document.getElementById("prefs").childElementCount,
+                   filteredPrefArray.length);
+
+      // Test empty search returns all preferences.
+      let search = content.document.getElementById("search");
+      search.value = "";
+      search.focus();
+    });
+
+    EventUtils.sendKey("return");
+    await ContentTask.spawn(browser, prefArray, aPrefArray => {
+      Assert.equal(content.document.getElementById("prefs").childElementCount,
+                   aPrefArray.length);
+
+      // Test invalid search returns no preferences.
+      let search = content.document.getElementById("search");
+      search.value = "aJunkValueasdf";
+      search.focus();
+    });
+
+    EventUtils.sendKey("return");
+    await ContentTask.spawn(browser, prefArray, aPrefArray => {
+      Assert.equal(content.document.getElementById("prefs").childElementCount,
+                   0);
+
+      // Test added preferences search returns 2 preferences.
+      let search = content.document.getElementById("search");
+      search.value = "test.aboutconfig.a";
+      search.focus();
+    });
+
+    EventUtils.sendKey("return");
+    await ContentTask.spawn(browser, prefArray, aPrefArray => {
+      Assert.equal(content.document.getElementById("prefs").childElementCount,
+                   2);
+    });
+  });
+});
deleted file mode 100644
--- a/testing/web-platform/meta/css/filter-effects/css-filters-animation-combined-001.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[css-filters-animation-combined-001.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/filter-effects/css-filters-animation-drop-shadow.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[css-filters-animation-drop-shadow.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/filter-effects/css-filters-animation-hue-rotate.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[css-filters-animation-hue-rotate.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/filter-effects/css-filters-animation-saturate.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[css-filters-animation-saturate.html]
-  expected: FAIL
--- a/testing/web-platform/meta/css/filter-effects/fecolormatrix-type.html.ini
+++ b/testing/web-platform/meta/css/filter-effects/fecolormatrix-type.html.ini
@@ -1,2 +1,5 @@
 [fecolormatrix-type.html]
-  expected: FAIL
+  expected:
+    if not debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): PASS
+    if debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): PASS
+    FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/filter-effects/filter-contrast-003.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[filter-contrast-003.html]
-  expected: FAIL
--- a/testing/web-platform/meta/css/filter-effects/filter-external-001-test.html.ini
+++ b/testing/web-platform/meta/css/filter-effects/filter-external-001-test.html.ini
@@ -1,4 +1,2 @@
 [filter-external-001-test.html]
-  expected:
-    if webrender: PASS
-    FAIL
+  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/filter-effects/filter-grayscale-002.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[filter-grayscale-002.html]
-  expected: FAIL
deleted file mode 100644
--- a/testing/web-platform/meta/css/filter-effects/filter-grayscale-003.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[filter-grayscale-003.html]
-  expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/filter-effects/filters-test-brightness-003.html.ini
@@ -0,0 +1,2 @@
+[filters-test-brightness-003.html]
+  expected: FAIL
--- a/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/images3/object-position-svg-002o.html.ini
+++ b/testing/web-platform/meta/css/vendor-imports/mozilla/mozilla-central-reftests/images3/object-position-svg-002o.html.ini
@@ -1,4 +1,2 @@
 [object-position-svg-002o.html]
-  expected:
-    if not debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): PASS
-    FAIL
+  expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_feature_policy.tentative.sub.html.ini
@@ -0,0 +1,2 @@
+[document_domain_feature_policy.tentative.sub.html]
+  expected: TIMEOUT
--- a/testing/web-platform/meta/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/no_window_open_when_term_nesting_level_nonzero.window.js.ini
+++ b/testing/web-platform/meta/html/browsers/the-window-object/apis-for-creating-and-navigating-browsing-contexts-by-name/no_window_open_when_term_nesting_level_nonzero.window.js.ini
@@ -1,12 +1,10 @@
 [no_window_open_when_term_nesting_level_nonzero.window.html]
-  expected:
-    if not debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): TIMEOUT
-    ERROR
+  expected: ERROR
   [no popups from synchronously reachable window]
     expected: FAIL
 
   [no popups with frame navigation]
     expected: FAIL
 
   [no popups from another synchronously reachable window]
     expected:
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/infrastructure/testdriver/actions/elementPosition.html.ini
@@ -0,0 +1,4 @@
+[elementPosition.html]
+  [TestDriver actions: element position]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/infrastructure/testdriver/actions/eventOrder.html.ini
@@ -0,0 +1,4 @@
+[eventOrder.html]
+  [TestDriver actions: event order]
+    expected: FAIL
+
--- a/testing/web-platform/meta/mozilla-sync
+++ b/testing/web-platform/meta/mozilla-sync
@@ -1,2 +1,2 @@
-local: d8685a43ab2869f701764f852f1a48d8a1367e5b
-upstream: e1bde44cb56120f187d326557a681f87b31b43af
+local: d0e41ff8b7f9992909a01a87a86e1b7110c434cd
+upstream: f082fd63300fec7b6201cf5e0eaf0944ee7ccb6e
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/picture-in-picture/mediastream.html.ini
@@ -0,0 +1,4 @@
+[mediastream.html]
+  [request Picture-in-Picture resolves on user click with Picture-in-Picture window]
+    expected: FAIL
+
--- a/testing/web-platform/meta/screen-capture/getdisplaymedia.https.html.ini
+++ b/testing/web-platform/meta/screen-capture/getdisplaymedia.https.html.ini
@@ -27,26 +27,20 @@
     expected: FAIL
 
   [getDisplayMedia() call with min constraint]
     expected: FAIL
 
   [getDisplayMedia() call with advanced constraint]
     expected: FAIL
 
-  [getDisplayMedia() with advanced constraint]
-    expected: FAIL
-
   [getDisplayMedia() with constraints applied]
     expected: FAIL
 
-  [getDisplayMedia() with min constraint]
-    expected: FAIL
-
   [getDisplayMedia() with max constraint]
     expected: FAIL
 
   [getDisplayMedia() overconstrained]
     expected: FAIL
 
-  [getDisplayMedia() with exact constraint]
+  [getDisplayMedia in navigator.mediaDevices]
     expected: FAIL
 
--- a/testing/web-platform/meta/service-workers/service-worker/update-registration-with-type.https.html.ini
+++ b/testing/web-platform/meta/service-workers/service-worker/update-registration-with-type.https.html.ini
@@ -1,7 +1,13 @@
 [update-registration-with-type.https.html]
   [Update the registration with a different script type (module => classic).]
     expected: FAIL
 
   [Update the registration with a different script type (classic => module).]
     expected: FAIL
 
+  [Update the registration with a different script type (classic => module) and with a same main script. Expect evaluation failed.]
+    expected: FAIL
+
+  [Update the registration with a different script type (module => classic) and with a same main script. Expect evaluation failed.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/geometry/parsing/cx-valid.svg.ini
@@ -0,0 +1,13 @@
+[cx-valid.svg]
+  [e.style['cx'\] = "4%" should set the property value]
+    expected: FAIL
+
+  [e.style['cx'\] = "-1px" should set the property value]
+    expected: FAIL
+
+  [e.style['cx'\] = "calc(2em + 3ex)" should set the property value]
+    expected: FAIL
+
+  [e.style['cx'\] = "0" should set the property value]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/geometry/parsing/cy-valid.svg.ini
@@ -0,0 +1,13 @@
+[cy-valid.svg]
+  [e.style['cy'\] = "0" should set the property value]
+    expected: FAIL
+
+  [e.style['cy'\] = "calc(2em + 3ex)" should set the property value]
+    expected: FAIL
+
+  [e.style['cy'\] = "4%" should set the property value]
+    expected: FAIL
+
+  [e.style['cy'\] = "-1px" should set the property value]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/geometry/parsing/r-valid.svg.ini
@@ -0,0 +1,16 @@
+[r-valid.svg]
+  [e.style['r'\] = "1px" should set the property value]
+    expected: FAIL
+
+  [e.style['r'\] = "0" should set the property value]
+    expected: FAIL
+
+  [e.style['r'\] = "calc(2em + 3ex)" should set the property value]
+    expected: FAIL
+
+  [e.style['r'\] = "4%" should set the property value]
+    expected: FAIL
+
+  [e.style['r'\] = "5vmin" should set the property value]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/geometry/parsing/rx-valid.svg.ini
@@ -0,0 +1,16 @@
+[rx-valid.svg]
+  [e.style['rx'\] = "auto" should set the property value]
+    expected: FAIL
+
+  [e.style['rx'\] = "4%" should set the property value]
+    expected: FAIL
+
+  [e.style['rx'\] = "calc(2em + 3ex)" should set the property value]
+    expected: FAIL
+
+  [e.style['rx'\] = "0" should set the property value]
+    expected: FAIL
+
+  [e.style['rx'\] = "1px" should set the property value]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/geometry/parsing/ry-valid.svg.ini
@@ -0,0 +1,16 @@
+[ry-valid.svg]
+  [e.style['rx'\] = "auto" should set the property value]
+    expected: FAIL
+
+  [e.style['rx'\] = "4%" should set the property value]
+    expected: FAIL
+
+  [e.style['rx'\] = "calc(2em + 3ex)" should set the property value]
+    expected: FAIL
+
+  [e.style['rx'\] = "0" should set the property value]
+    expected: FAIL
+
+  [e.style['rx'\] = "1px" should set the property value]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/geometry/parsing/x-valid.svg.ini
@@ -0,0 +1,13 @@
+[x-valid.svg]
+  [e.style['x'\] = "-1px" should set the property value]
+    expected: FAIL
+
+  [e.style['x'\] = "0" should set the property value]
+    expected: FAIL
+
+  [e.style['x'\] = "calc(2em + 3ex)" should set the property value]
+    expected: FAIL
+
+  [e.style['x'\] = "4%" should set the property value]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/svg/geometry/parsing/y-valid.svg.ini
@@ -0,0 +1,13 @@
+[y-valid.svg]
+  [e.style['y'\] = "-1px" should set the property value]
+    expected: FAIL
+
+  [e.style['y'\] = "4%" should set the property value]
+    expected: FAIL
+
+  [e.style['y'\] = "0" should set the property value]
+    expected: FAIL
+
+  [e.style['y'\] = "calc(2em + 3ex)" should set the property value]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/trusted-types/__dir__.ini
@@ -0,0 +1,1 @@
+lsan-allowed: [Alloc, NS_NewDOMEvent, alloc_system::platform::_$LT$impl$u20$core..alloc..GlobalAlloc$u20$for$u20$alloc_system..System$GT$::alloc::h82bf91dcf8d89ced, alloc_system::platform::_$LT$impl$u20$core..alloc..GlobalAlloc$u20$for$u20$alloc_system..System$GT$::realloc::h3ab64a4bcafe2c39, mozilla::BasePrincipal::CreateCodebasePrincipal]
--- a/testing/web-platform/meta/webrtc/RTCQuicStream.https.html.ini
+++ b/testing/web-platform/meta/webrtc/RTCQuicStream.https.html.ini
@@ -36,8 +36,74 @@
     expected: FAIL
 
   [createStream() followed by reset() fires a quicstream event followed by a statechange event to 'closed' on the remote side.]
     expected: FAIL
 
   [finish() then reset() fires two statechange events on the remote side.]
     expected: FAIL
 
+  [write() throws if data longer than maxWriteBufferedAmount.]
+    expected: FAIL
+
+  [write() throws if total write buffered amount would be greater than maxWriteBufferedAmount.]
+    expected: FAIL
+
+  [write() can write exactly maxWriteBufferedAmount.]
+    expected: FAIL
+
+  [write() adds to writeBufferedAmount each call.]
+    expected: FAIL
+
+  [write() throws if the stream was reset locally.]
+    expected: FAIL
+
+  [RTCQuicTransport.stop() sets stream writeBufferedAmount to 0.]
+    expected: FAIL
+
+  [reset() sets writeBufferedAmount to 0.]
+    expected: FAIL
+
+  [write() with an empty array does nothing.]
+    expected: FAIL
+
+  [write() throws if finish() has been called.]
+    expected: FAIL
+
+  [write() throws IllegalStateError if finish() has been called.]
+    expected: FAIL
+
+  [Stream closed by local reset(): write() throws InvalidStateError.]
+    expected: FAIL
+
+  [Stream closed by remote RTCQuicTransport stop(): writeBufferedAmount is 0.]
+    expected: FAIL
+
+  [Stream closed by remote reset(): write() throws InvalidStateError.]
+    expected: FAIL
+
+  [Stream closed by local reset(): writeBufferedAmount is 0.]
+    expected: FAIL
+
+  [Stream closed by local RTCQuicTransport stop(): write() throws InvalidStateError.]
+    expected: FAIL
+
+  [Stream closed by remote reset(): writeBufferedAmount is 0.]
+    expected: FAIL
+
+  [Stream closed by local RTCQuicTransport stop(): writeBufferedAmount is 0.]
+    expected: FAIL
+
+  [Stream closed by remote RTCQuicTransport stop(): write() throws InvalidStateError.]
+    expected: FAIL
+
+  [writeBufferedAmount maintained after finish() has been called.]
+    expected: FAIL
+
+  [writeBufferedAmount set to 0 after local reset().]
+    expected: FAIL
+
+  [write() throws InvalidStateError if finish() has been called.]
+    expected: FAIL
+
+  [writeBufferedAmount set to 0 after local RTCQuicTransport stop().]
+    expected: FAIL
+
--- a/testing/web-platform/meta/worklets/animation-worklet-csp.https.html.ini
+++ b/testing/web-platform/meta/worklets/animation-worklet-csp.https.html.ini
@@ -21,8 +21,107 @@
     expected: FAIL
 
   [Importing an insecure-origin script from a secure-origin worklet script should be blocked because of mixed contents.]
     expected: FAIL
 
   [Importing an insecure-origin script from a secure-origin worklet script should not be blocked because the upgrade-insecure-requests directive translates it as the secure origin.]
     expected: FAIL
 
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin-redirected script should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [An insecure-origin-redirected worklet should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin script should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin script should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [An insecure-origin worklet should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [A remote-origin worklet should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin worklet should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [An insecure-origin worklet should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A remote-origin worklet should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [An insecure-origin-redirected worklet should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin-redirected script should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
--- a/testing/web-platform/meta/worklets/animation-worklet-import.https.html.ini
+++ b/testing/web-platform/meta/worklets/animation-worklet-import.https.html.ini
@@ -83,8 +83,14 @@
     expected: FAIL
 
   [Importing a nested script that has a syntax error should reject the given promise.]
     expected: FAIL
 
   [Importing a script that imports an invalid identifier should reject the given promise.]
     expected: FAIL
 
+  [Importing a cross-origin-redirected resource with the Access-Control-Allow-Origin header should resolve the given promise]
+    expected: FAIL
+
+  [Importing a cross-origin-redirected resource without the Access-Control-Allow-Origin header should reject the given promise]
+    expected: FAIL
+
--- a/testing/web-platform/meta/worklets/audio-worklet-csp.https.html.ini
+++ b/testing/web-platform/meta/worklets/audio-worklet-csp.https.html.ini
@@ -30,8 +30,56 @@
 
   [Importing an insecure-origin script from a secure-origin worklet script should be blocked because of mixed contents.]
     expected:
       if release_or_beta: FAIL
 
   [Importing an insecure-origin script from a secure-origin worklet script should not be blocked because the upgrade-insecure-requests directive translates it as the secure origin.]
     expected: FAIL
 
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin script should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A remote-origin worklet should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin-redirected script should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
--- a/testing/web-platform/meta/worklets/audio-worklet-import.https.html.ini
+++ b/testing/web-platform/meta/worklets/audio-worklet-import.https.html.ini
@@ -34,23 +34,26 @@
   [Importing a data URL should resolve the given promise.]
     expected:
       if release_or_beta: FAIL
 
   [Importing about:blank should reject the given promise.]
     expected: FAIL
 
   [Importing a cross origin resource with the Access-Control-Allow-Origin header should resolve the given promise]
-    expected: 
+    expected:
       if release_or_beta: FAIL
 
   [Importing a cross origin resource without the Access-Control-Allow-Origin header should reject the given promise]
     expected: FAIL
 
   [Importing a script that has a syntax error should reject the given promise.]
     expected: FAIL
 
   [Importing a nested script that has a syntax error should reject the given promise.]
     expected: FAIL
 
   [Importing a script that imports an invalid identifier should reject the given promise.]
     expected: FAIL
 
+  [Importing a cross-origin-redirected resource without the Access-Control-Allow-Origin header should reject the given promise]
+    expected: FAIL
+
--- a/testing/web-platform/meta/worklets/layout-worklet-csp.https.html.ini
+++ b/testing/web-platform/meta/worklets/layout-worklet-csp.https.html.ini
@@ -21,8 +21,107 @@
     expected: FAIL
 
   [Importing an insecure-origin script from a secure-origin worklet script should be blocked because of mixed contents.]
     expected: FAIL
 
   [Importing an insecure-origin script from a secure-origin worklet script should not be blocked because the upgrade-insecure-requests directive translates it as the secure origin.]
     expected: FAIL
 
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin-redirected script should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [An insecure-origin-redirected worklet should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin script should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin script should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [An insecure-origin worklet should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [A remote-origin worklet should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin worklet should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [An insecure-origin worklet should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A remote-origin worklet should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [An insecure-origin-redirected worklet should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin-redirected script should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
--- a/testing/web-platform/meta/worklets/layout-worklet-import.https.html.ini
+++ b/testing/web-platform/meta/worklets/layout-worklet-import.https.html.ini
@@ -42,8 +42,14 @@
     expected: FAIL
 
   [Importing a nested script that has a syntax error should reject the given promise.]
     expected: FAIL
 
   [Importing a script that imports an invalid identifier should reject the given promise.]
     expected: FAIL
 
+  [Importing a cross-origin-redirected resource with the Access-Control-Allow-Origin header should resolve the given promise]
+    expected: FAIL
+
+  [Importing a cross-origin-redirected resource without the Access-Control-Allow-Origin header should reject the given promise]
+    expected: FAIL
+
--- a/testing/web-platform/meta/worklets/paint-worklet-csp.https.html.ini
+++ b/testing/web-platform/meta/worklets/paint-worklet-csp.https.html.ini
@@ -21,8 +21,107 @@
     expected: FAIL
 
   [Importing an insecure-origin script from a secure-origin worklet script should be blocked because of mixed contents.]
     expected: FAIL
 
   [Importing an insecure-origin script from a secure-origin worklet script should not be blocked because the upgrade-insecure-requests directive translates it as the secure origin.]
     expected: FAIL
 
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin-redirected script should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [An insecure-origin-redirected worklet should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin script should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin script should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [An insecure-origin worklet should be blocked because of mixed contents.]
+    expected: FAIL
+
+  [A remote-origin worklet should be blocked by the script-src 'self' directive.]
+    expected: FAIL
+
+  [A remote-origin worklet should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [An insecure-origin worklet should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A remote-origin worklet should be blocked by the script-src directive specifying the origin.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked because the script-src * directive allows it.]
+    expected: FAIL
+
+  [An insecure-origin-redirected worklet should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A same-origin worklet importing an insecure-origin-redirected script should not be blocked because of upgrade-insecure-requests.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should not be blocked by the worker-src directive because worklets obey the script-src directive.]
+    expected: FAIL
+
+  [A remote-origin worklet should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A remote-origin-redirected worklet should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A same-origin worklet importing a remote-origin-redirected script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
+  [A remote-origin worklet importing a remote-origin script should not be blocked because the script-src directive specifying the origin allows it.]
+    expected: FAIL
+
--- a/testing/web-platform/meta/worklets/paint-worklet-import.https.html.ini
+++ b/testing/web-platform/meta/worklets/paint-worklet-import.https.html.ini
@@ -83,8 +83,14 @@
     expected: FAIL
 
   [Importing a nested script that has a syntax error should reject the given promise.]
     expected: FAIL
 
   [Importing a script that imports an invalid identifier should reject the given promise.]
     expected: FAIL
 
+  [Importing a cross-origin-redirected resource with the Access-Control-Allow-Origin header should resolve the given promise]
+    expected: FAIL
+
+  [Importing a cross-origin-redirected resource without the Access-Control-Allow-Origin header should reject the given promise]
+    expected: FAIL
+
--- a/testing/web-platform/tests/bluetooth/resources/bluetooth-helpers.js
+++ b/testing/web-platform/tests/bluetooth/resources/bluetooth-helpers.js
@@ -21,18 +21,19 @@ function performChromiumSetup() {
   // Make sure we are actually on Chromium.
   if (!Mojo) {
     return;
   }
 
   // Load the Chromium-specific resources.
   let prefix = '/resources/chromium';
   let extra = [];
-  if (window.location.pathname.includes('/LayoutTests/')) {
-    let root = window.location.pathname.match(/.*LayoutTests/);
+  const pathname = window.location.pathname;
+  if (pathname.includes('/LayoutTests/') || pathname.includes('/web_tests/')) {
+    let root = pathname.match(/.*(?:LayoutTests|web_tests)/);
     prefix = `${root}/external/wpt/resources/chromium`;
     extra = [
       `${root}/resources/bluetooth/bluetooth-fake-adapter.js`,
     ];
   } else if (window.location.pathname.startsWith('/bluetooth/https/')) {
     extra = [
       '/js-test-resources/bluetooth/bluetooth-fake-adapter.js',
     ];
--- a/testing/web-platform/tests/cors/access-control-expose-headers-parsing.window.js
+++ b/testing/web-platform/tests/cors/access-control-expose-headers-parsing.window.js
@@ -1,13 +1,15 @@
-function exposeTest(resource, desc) {
-  const url = new URL("resources/" + resource, location.href).href.replace("://", "://élève.");
+promise_test(() => fetch("resources/access-control-expose-headers.json").then(res => res.json()).then(runTests), "Loading JSON…");
 
-  promise_test(() => {
-    return fetch(url).then(res => {
-      assert_equals(res.headers.get("content-language"), "sure")
-      assert_equals(res.headers.get("x-custom"), null);
-    })
-  }, "Access-Control-Expose-Headers parsing: " + desc);
+function runTests(allTestData) {
+  allTestData.forEach(testData => {
+    const encodedInput = encodeURIComponent(testData.input);
+    promise_test(() => {
+      const relativeURL = "resources/expose-headers.py?expose=" + encodedInput,
+            url = new URL(relativeURL, location.href).href.replace("://", "://élève.");
+      return fetch(url).then(res => {
+        assert_equals(res.headers.get("content-language"), "mkay");
+        assert_equals(res.headers.get("bb-8"), (testData.exposed ? "hey" : null));
+      });
+    }, "Parsing: " + encodedInput);
+  })
 }
-
-exposeTest("access-control-expose-headers-parsing.asis", "#1");
-exposeTest("access-control-expose-headers-parsing-2.asis", "#2")
deleted file mode 100644
--- a/testing/web-platform/tests/cors/resources/access-control-expose-headers-parsing-2.asis
+++ /dev/null
@@ -1,8 +0,0 @@
-HTTP/1.1 200 OK
-Access-Control-Allow-Origin: *
-Access-Control-Expose-Headers: not valid
-Access-Control-Expose-Headers: x-custom
-X-Custom: test
-Content-Language: sure
-
-TEST
deleted file mode 100644
--- a/testing/web-platform/tests/cors/resources/access-control-expose-headers-parsing.asis
+++ /dev/null
@@ -1,7 +0,0 @@
-HTTP/1.1 200 OK
-Access-Control-Allow-Origin: *
-Access-Control-Expose-Headers: not valid, x-custom
-X-Custom: test
-Content-Language: sure
-
-TEST
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/cors/resources/access-control-expose-headers.json
@@ -0,0 +1,62 @@
+[
+  {
+    "input": "access-control-expose-headers: BB-8",
+    "exposed": true
+  },
+  {
+    "input": "Access-Control-Expose-Headers: bb-8,,@#$#%%&^&^*()()11!",
+    "exposed": false
+  },
+  {
+    "input": "Access-Control-Expose-Headers: bb-8, no no",
+    "exposed": false
+  },
+  {
+    "input": "Access-Control-Expose-Headers: @#$#%%&^&^*()()11!,bb-8",
+    "exposed": false
+  },
+  {
+    "input": "Access-Control-Expose-Headers: bb-8\r\nAccess-Control-Expose-Headers: no",
+    "exposed": true
+  },
+  {
+    "input": "Access-Control-Expose-Headers: bb-8\r\nAccess-Control-Expose-Headers: no no",
+    "exposed": false
+  },
+  {
+    "input": "Access-Control-Expose-Headers: no\r\nAccess-Control-Expose-Headers: bb-8",
+    "exposed": true
+  },
+  {
+    "input": "Access-Control-Expose-Headers:\r\nAccess-Control-Expose-Headers: bb-8",
+    "exposed": true
+  },
+  {
+    "input": "Access-Control-Expose-Headers: ,bb-8",
+    "exposed": true
+  },
+  {
+    "input": "Access-Control-Expose-Headers: bb-8\u000C",
+    "exposed": false
+  },
+  {
+    "input": "Access-Control-Expose-Headers: bb-8\u000B",
+    "exposed": false
+  },
+  {
+    "input": "Access-Control-Expose-Headers: bb-8\u000B,bb-8",
+    "exposed": false
+  },
+  {
+    "input": "Access-Control-Expose-Headers: 'bb-8'",
+    "exposed": false
+  },
+  {
+    "input": "Access-Control-Expose-Headers: 'bb-8',bb-8",
+    "exposed": true
+  },
+  {
+    "input": "Access-Control-Expose-Headers: \"bb-8\",bb-8",
+    "exposed": false
+  }
+]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/cors/resources/expose-headers.py
@@ -0,0 +1,10 @@
+def main(request, response):
+    response.add_required_headers = False
+    output =  "HTTP/1.1 221 ALL YOUR BASE BELONG TO H1\r\n"
+    output += "Access-Control-Allow-Origin: *\r\n"
+    output += "BB-8: hey\r\n"
+    output += "Content-Language: mkay\r\n"
+    output += request.GET.first("expose") + "\r\n"
+    output += "\r\n"
+    response.writer.write(output)
+    response.close_connection = True
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-backgrounds/background-size-one-value-1x1-image.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>CSS Background Test: A single size value with a 1x1 image should work as intended</title>
+    <link rel="author" title="schenney" href="mailto:schenney@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/css3-background/#the-background-size">
+    <link rel="match" href="reference/background-size-one-value-1x1-image-ref.html">
+    <style type="text/css">
+    .backgroundSize{
+        background: url("support/1x1-green.png");
+        background-size: 50%;
+        background-repeat: repeat-y;
+        height: 100px;
+    }
+    </style>
+</head>
+<body>
+    <div style="background: #7957d5">
+        <div class="backgroundSize"></div>
+    </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-backgrounds/reference/background-size-one-value-1x1-image-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>CSS Background Test Reference</title>
+    <link rel="author" title="schenney" href="mailto:schenney@chromium.org">
+    <style type="text/css">
+    .backgroundSize{
+        background: url("../support/1x1-green.png");
+        background-size: 50% 100%;
+        background-repeat: repeat-y;
+        height: 100px;
+    }
+    </style>
+</head>
+<body>
+    <div style="background: #7957d5">
+        <div class="backgroundSize"></div>
+    </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-flexbox/flex-wrap-002.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<link rel="author" title="Google LLC" href="http://www.google.com" />
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#cross-sizing" />
+<title>css-flexbox: Tests that we size items in a wrapping column flexbox as fit-content</title>
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht" />
+<meta name="assert" content="The flexbox here should have two flex lines, each 50px wide and 100px tall. The flex items overflow but are transparent." />
+
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+
+<!-- This makes sure that we only see green if the flex items are sized correctly -->
+<div style="position: absolute; width: 100px; height: 100px; background: green;"></div>
+
+<div style="display: flex; flex-direction: column; flex-wrap: wrap; width: 50px; height: 100px; line-height: 20px;">
+  <div style="background-color: red; height: 100px;">
+    <!-- These zero-height divs give the flex item has a min-content width of
+         25px and a max-content width of 125px -->
+    <div style="width: 25px; display: inline-block;"></div>
+    <div style="width: 25px; display: inline-block;"></div>
+    <div style="width: 25px; display: inline-block;"></div>
+    <div style="width: 25px; display: inline-block;"></div>
+    <div style="width: 25px; display: inline-block;"></div>
+  </div>
+  <div style="background-color: red; height: 100px;">
+    <div style="width: 25px; display: inline-block;"></div>
+    <div style="width: 25px; display: inline-block;"></div>
+    <div style="width: 25px; display: inline-block;"></div>
+    <div style="width: 25px; display: inline-block;"></div>
+    <div style="width: 25px; display: inline-block;"></div>
+  </div>
+</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-flexbox/flex-wrap-003.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<link rel="author" title="Google LLC" href="http://www.google.com" />
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#cross-sizing" />
+<title>css-flexbox: Tests that we size items in a wrapping column flexbox as fit-content</title>
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht" />
+<meta name="assert" content="The flexbox here should have one flex line, 100px by 100px. The flex items overflow but are transparent." />
+
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+
+<!-- This makes sure that we only see green if the flex items are sized correctly -->
+<div style="position: absolute; width: 100px; height: 100px; background: green;"></div>
+
+<div style="display: flex; flex-direction: column; flex-wrap: wrap; width: 100px; height: 100px; line-height: 20x;">
+  <div style="background-color: red; height: 100px;">
+    <!-- These zero-height divs give the flex item has a min-content width of
+         50px and a max-content width of 250px -->
+    <div style="width: 50px; display: inline-block;"></div>
+    <div style="width: 50px; display: inline-block;"></div>
+    <div style="width: 50px; display: inline-block;"></div>
+    <div style="width: 50px; display: inline-block;"></div>
+    <div style="width: 50px; display: inline-block;"></div>
+  </div>
+</div>
--- a/testing/web-platform/tests/css/css-properties-values-api/var-reference-registered-properties-cycles.html
+++ b/testing/web-platform/tests/css/css-properties-values-api/var-reference-registered-properties-cycles.html
@@ -20,24 +20,23 @@
 <script>
 test(function() {
     CSS.registerProperty({name: '--registered-1-a', syntax: '<length>', initialValue: '1px', inherits: false});
     CSS.registerProperty({name: '--registered-1-b', syntax: '<length>', initialValue: '2px', inherits: false});
     CSS.registerProperty({name: '--registered-1-c', syntax: '<length>', initialValue: '3px', inherits: false});
     CSS.registerProperty({name: '--registered-1-d', syntax: '<length>', initialValue: '4px', inherits: false});
 
     computedStyle = getComputedStyle(test1);
-    assert_equals(computedStyle.getPropertyValue('--registered-1-a'), '1px');
-    assert_equals(computedStyle.getPropertyValue('--registered-1-b'), '2px');
-
-    assert_equals(computedStyle.getPropertyValue('--registered-1-c'), '2px');
-    assert_equals(computedStyle.getPropertyValue('--registered-1-d'), '2px');
-    assert_equals(computedStyle.getPropertyValue('--unregistered-1-a'), '1px');
-    assert_equals(computedStyle.left, '1px');
-    assert_equals(computedStyle.top, '2px');
+    assert_equals(computedStyle.getPropertyValue('--registered-1-a'), '');
+    assert_equals(computedStyle.getPropertyValue('--registered-1-b'), '');
+    assert_equals(computedStyle.getPropertyValue('--registered-1-c'), '30px');
+    assert_equals(computedStyle.getPropertyValue('--registered-1-d'), '4px');
+    assert_equals(computedStyle.getPropertyValue('--unregistered-1-a'), '');
+    assert_equals(computedStyle.left, '50px');
+    assert_equals(computedStyle.top, '60px');
 }, "A var() cycle between two registered properties is handled correctly.");
 </script>
 
 <style>
 #test2 {
     --registered-2-a: var(--unregistered-2-a, 10px);
     --unregistered-2-a:var(--registered-2-a,20px);
 
@@ -58,28 +57,28 @@ test(function() {
 test(function() {
     CSS.registerProperty({name: '--registered-2-a', syntax: '<length>', initialValue: '1px', inherits: false});
     CSS.registerProperty({name: '--registered-2-b', syntax: '<length>', initialValue: '2px', inherits: false});
     CSS.registerProperty({name: '--registered-2-c', syntax: '<length>', initialValue: '3px', inherits: false});
     CSS.registerProperty({name: '--registered-2-d', syntax: '<length>', initialValue: '4px', inherits: false});
     CSS.registerProperty({name: '--registered-2-e', syntax: '<length>', initialValue: '5px', inherits: false});
 
     computedStyle = getComputedStyle(test2);
-    assert_equals(computedStyle.getPropertyValue('--registered-2-a'), '1px');
+    assert_equals(computedStyle.getPropertyValue('--registered-2-a'), '');
     assert_equals(computedStyle.getPropertyValue('--unregistered-2-a'), '');
 
-    assert_equals(computedStyle.getPropertyValue('--registered-2-b'), '1px');
-    assert_equals(computedStyle.getPropertyValue('--registered-2-c'), '1px');
+    assert_equals(computedStyle.getPropertyValue('--registered-2-b'), '30px');
+    assert_equals(computedStyle.getPropertyValue('--registered-2-c'), '3px');
     assert_equals(computedStyle.getPropertyValue('--registered-2-d'), '40px');
     assert_equals(computedStyle.getPropertyValue('--registered-2-e'), '5px');
-    assert_equals(computedStyle.getPropertyValue('--unregistered-2-b'), '1px');
-    assert_equals(computedStyle.getPropertyValue('--unregistered-2-c'), '1px');
+    assert_equals(computedStyle.getPropertyValue('--unregistered-2-b'), '50px');
+    assert_equals(computedStyle.getPropertyValue('--unregistered-2-c'), '');
     assert_equals(computedStyle.getPropertyValue('--unregistered-2-d'), '60px');
     assert_equals(computedStyle.getPropertyValue('--unregistered-2-e'), '');
-    assert_equals(computedStyle.left, '1px');
+    assert_equals(computedStyle.left, '70px');
     assert_equals(computedStyle.top, '80px');
 }, "A var() cycle between a registered properties and an unregistered property is handled correctly.");
 </script>
 
 <style>
 #test3 {
     --unregistered-3-a:var(--unregistered-3-b,10px);
     --unregistered-3-b:var(--unregistered-3-a,20px);
--- a/testing/web-platform/tests/css/css-text/white-space/pre-wrap-002.html
+++ b/testing/web-platform/tests/css/css-text/white-space/pre-wrap-002.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>CSS Text level 3 Test: preserved white space at the end of and white-space:pre-wrap does not change based on word-break:break-all</title>
+<title>CSS Text level 3 Test: preserved white space at the end of the line and white-space:pre-wrap does not change based on word-break:break-all</title>
 <link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
 <link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-phase-2">
 <link rel="match" href="reference/pre-wrap-001-ref.html">
 <meta name="assert" content="preserved white space at the end of the line is not wrapped when the white-space property is set to pre-wrap, even if word-break is break-all">
 <style>
 div {
   font-size: 20px;
   font-family: Ahem;
--- a/testing/web-platform/tests/css/filter-effects/css-filters-animation-combined-001.html
+++ b/testing/web-platform/tests/css/filter-effects/css-filters-animation-combined-001.html
@@ -23,17 +23,17 @@
                 filter:
                     blur(20px)
                     brightness(0%)
                     sepia(100%)
                     grayscale(100%)
                     saturate(0%)
                     hue-rotate(90deg)
                     invert(100%)
-                    opacity(100%)
+                    opacity(0%)
             }
             100% {
                 filter: none;
             }
         }
 
         .square {
             width: 100px;
--- a/testing/web-platform/tests/css/filter-effects/css-filters-animation-drop-shadow-ref.html
+++ b/testing/web-platform/tests/css/filter-effects/css-filters-animation-drop-shadow-ref.html
@@ -5,17 +5,17 @@
     <link rel="author" title="Gunther Brunner" href="mailto:takeshimiya@gmail.com">
     <link rel="reviewer" title="Dirk Schulze" href="mailto:dschulze@adobe.com">
     <link rel="reviewer" title="Rebecca Hauck" href="mailto:rhauck@adobe.com">
     <style type="text/css">
         .square {
             width: 100px;
             height: 100px;
             background: blue;
-            filter: drop-shadow(15px 15px 0px gray);
+            filter: drop-shadow(15px 15px 0px rgba(0, 0, 0, 0.5));
         }
     </style>
 </head>
 <body>
 <p>You should see a blue rectangle in top of a gray one.</p>
 <div class="square"></div>
 </body>
 </html>
--- a/testing/web-platform/tests/css/filter-effects/css-filters-animation-drop-shadow.html
+++ b/testing/web-platform/tests/css/filter-effects/css-filters-animation-drop-shadow.html
@@ -4,17 +4,17 @@
     <title>CSS Filters Animation: Drop Shadow</title>
     <link rel="author" title="Gunther Brunner" href="mailto:takeshimiya@gmail.com">
     <link rel="reviewer" title="Dirk Schulze" href="mailto:dschulze@adobe.com">
     <link rel="reviewer" title="Rebecca Hauck" href="mailto:rhauck@adobe.com">
     <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#FilterProperty">
     <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-drop-shadow">
     <link rel="help" href="http://www.w3.org/TR/css3-animations/#animations">
     <link rel="match" href="css-filters-animation-drop-shadow-ref.html">
-    <meta name="assert" content="The blue square should be in top of a gray one">
+    <meta name="assert" content="The blue square should be on top of a gray one">
     <style type="text/css">
         @keyframes animate {
             0% {
                 filter: drop-shadow(30px 30px 0px black);
             }
             100% {
                 filter: none;
             }
--- a/testing/web-platform/tests/css/filter-effects/css-filters-animation-hue-rotate.html
+++ b/testing/web-platform/tests/css/filter-effects/css-filters-animation-hue-rotate.html
@@ -21,17 +21,17 @@
         }
 
         .square {
             width: 100px;
             height: 100px;
             background: blue;
             animation-name: animate;
             animation-play-state: paused;
-            animation-delay: -1s;
+            animation-delay: -2s;
             animation-duration: 4s;
             animation-timing-function: linear;
         }
     </style>
 </head>
 <body>
 <p>You should see a violet rectangle. Neither red nor blue.</p>
 <div class="square"></div>
--- a/testing/web-platform/tests/css/filter-effects/css-filters-animation-saturate.html
+++ b/testing/web-platform/tests/css/filter-effects/css-filters-animation-saturate.html
@@ -8,17 +8,17 @@
     <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#FilterProperty">
     <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-saturate">
     <link rel="help" href="http://www.w3.org/TR/css3-animations/#animations">
     <link rel="match" href="css-filters-animation-saturate-ref.html">
     <meta name="assert" content="The blue square should be light-blue">
     <style type="text/css">
         @keyframes animate {
             0% {
-                filter: saturate(5000%);
+                filter: saturate(4900%);
             }
             100% {
                 filter: none;
             }
         }
 
         .square {
             width: 100px;
--- a/testing/web-platform/tests/css/filter-effects/fecolormatrix-type-ref.html
+++ b/testing/web-platform/tests/css/filter-effects/fecolormatrix-type-ref.html
@@ -4,17 +4,17 @@
     <title>Filter Effects: Test feColorMatrix with type matrix</title>
     <link rel="author" title="Takaki Yasuma" href="mailto:takakiyasuma@gmail.com">
     <link rel="reviewer" title="Dirk Schulze" href="mailto:dschulze@adobe.com">
     <style type="text/css">
 
        div{
 	       width: 200px;
 	       height: 200px;
-	       background-color: #a8d7c1;
+	       background-color: rgba(39.3%, 68.6%, 53.4%, 1);
        }
 
     </style>
 </head>
 
 <body>
 
 	<p>You should see a aquamarine colored rectangle.</p>
--- a/testing/web-platform/tests/css/filter-effects/fecolormatrix-type.html
+++ b/testing/web-platform/tests/css/filter-effects/fecolormatrix-type.html
@@ -23,17 +23,17 @@
 
 <body>
 
 	<p>You should see a aquamarine colored rectangle.</p>
 
 	<div></div>
 
 	<svg>
-		<filter id="sepia">
+		<filter id="sepia" color-interpolation-filters="sRGB">
 			<feColorMatrix type="matrix" values="0.393 0.189 0.349 0 0
 	                   0.686 0.168 0.272 0 0
 	                   0.534 0.131 0 0 0
 	                   0 0 0 1 0"/>
 		</filter>
 	</svg>
 
 </body>
--- a/testing/web-platform/tests/css/filter-effects/filter-contrast-003.html
+++ b/testing/web-platform/tests/css/filter-effects/filter-contrast-003.html
@@ -1,25 +1,25 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <title>CSS Filter contrast: Test for CSS contrast filter shotrhand</title>
+    <title>CSS Filter contrast: Test for CSS contrast filter shorthand</title>
     <link rel="author" title="Takeshi Kurosawa" href="mailto:taken.spc@gmail.com">
     <link rel="reviewer" title="Dirk Schulze" href="mailto:dschulze@adobe.com">
     <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#FilterProperty">
     <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-contrast">
     <link rel="match" href="filter-contrast-003-ref.html">
     <meta name="flags" content="">
     <meta name="assert" content="CSS contrast filter will apply a component transfer to the div element to adjust the
     contrast of the colors. Since contrast is 200%, it will be less contrast.">
     <style type="text/css">
        div {
            width: 200px;
            height: 200px;
-           background-color: #400000;
+           background-color: #3f0000;
            filter: contrast(200%);
        }
     </style>
 </head>
 <body>
     <p>The test passes if there is a black box and no dark red.</p>
 
     <div></div>
--- a/testing/web-platform/tests/css/filter-effects/filter-external-001-ref.html
+++ b/testing/web-platform/tests/css/filter-effects/filter-external-001-ref.html
@@ -3,17 +3,17 @@
 <head>
     <title>CSS Filter Test: Reference for Saturate short hand</title>
     <link rel="author" title="Akihiro Oyamada" href="mailto:admin@yomotsu.net">
     <link rel="reviewer" title="Dirk Schulze" href="mailto:dschulze@adobe.com">
     <style type="text/css">
     div {
         width: 200px;
         height: 200px;
-        background: #00b60d;
+        background: rgb(0%, 46.896%, 0.396%);
     }
 
     </style>
 </head>
 <body>
     <p>You should see a green rectangle.</p>
 
     <div></div>
--- a/testing/web-platform/tests/css/filter-effects/filter-external-001-test.html
+++ b/testing/web-platform/tests/css/filter-effects/filter-external-001-test.html
@@ -21,14 +21,14 @@
     </style>
 </head>
 <body>
     <p>You should see a green rectangle.</p>
 
     <div></div>
 
     <svg>
-        <filter id="filter">
+        <filter id="filter" color-interpolation-filters="sRGB">
             <feColorMatrix type="hueRotate" in="SourceGraphic" values="150"/>
         </filter>
     </svg>
 </body>
 </html>
deleted file mode 100644
--- a/testing/web-platform/tests/css/filter-effects/filter-external-002-filter.svg
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
-	<filter id="filter">
-		<feColorMatrix type="hueRotate" in="SourceGraphic" values="120"/>
-	</filter>
-</svg>
\ No newline at end of file
--- a/testing/web-platform/tests/css/filter-effects/filter-external-002-test.html
+++ b/testing/web-platform/tests/css/filter-effects/filter-external-002-test.html
@@ -10,17 +10,17 @@
     <link rel="match" href="filter-external-001-ref.html">
     <meta name="flags" content="svg">
     <meta name="assert" content="the test passes if you see green box.">
     <style type="text/css">
     div {
         width: 200px;
         height: 200px;
         background: red;
-        filter: url( filter-external-002-filter.svg#filter );
+        filter: url( support/filter-external-002-filter.svg#filter );
     }
 
     </style>
 </head>
 <body>
     <p>You should see a green rectangle.</p>
 
     <div></div>
--- a/testing/web-platform/tests/css/filter-effects/filter-grayscale-001.html
+++ b/testing/web-platform/tests/css/filter-effects/filter-grayscale-001.html
@@ -17,14 +17,14 @@
 				width: 30px;
 			}
 			.filter{
 				filter: grayscale(100%);
 			}
 		</style>
 	</head>
 	<body>
-		<p>The test passes if the little box looks grey. (and not blue)</p>
+		<p>The test passes if the little box looks grey.</p>
 		<div class="testzone">
 			<div class="box filter"></div>
 		</div>
 	</body>
-</html>
\ No newline at end of file
+</html>
--- a/testing/web-platform/tests/css/filter-effects/filter-grayscale-004.html
+++ b/testing/web-platform/tests/css/filter-effects/filter-grayscale-004.html
@@ -17,14 +17,14 @@
 				width: 30px;
 			}
 			.filter{
 				filter: grayscale(1);
 			}
 		</style>
 	</head>
 	<body>
-		<p>The test passes if the little box looks grey. (and not blue)</p>
+		<p>The test passes if the little box looks grey.</p>
 		<div class="testzone">
 			<div class="box filter"></div>
 		</div>
 	</body>
-</html>
\ No newline at end of file
+</html>
--- a/testing/web-platform/tests/css/filter-effects/filter-grayscale-005.html
+++ b/testing/web-platform/tests/css/filter-effects/filter-grayscale-005.html
@@ -17,14 +17,14 @@
 				width: 30px;
 			}
 			.filter{
 				filter: grayscale(300%);
 			}
 		</style>
 	</head>
 	<body>
-		<p>The test passes if the little box looks grey. (and not blue)</p>
+		<p>The test passes if the little box looks grey.</p>
 		<div class="testzone">
 			<div class="box filter"></div>
 		</div>
 	</body>
-</html>
\ No newline at end of file
+</html>
--- a/testing/web-platform/tests/css/filter-effects/filter-grayscale-ref.html
+++ b/testing/web-platform/tests/css/filter-effects/filter-grayscale-ref.html
@@ -11,14 +11,14 @@
 			.box{
 				background-color: #121212;
 				height: 30px;
 				width: 30px;
 			}
 		</style>
 	</head>
 	<body>
-		<p>The test passes if the little box looks grey. (and not blue)</p>
+		<p>The test passes if the little box looks grey.</p>
 		<div class="testzone">
 			<div class="box"></div>
 		</div>
 	</body>
-</html>
\ No newline at end of file
+</html>
--- a/testing/web-platform/tests/css/filter-effects/filters-test-brightness-003.html
+++ b/testing/web-platform/tests/css/filter-effects/filters-test-brightness-003.html
@@ -1,26 +1,27 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <title>CSS Writing Modes Test: drop-shadow offset test</title>
+    <title>CSS Filter Effects: brightness(...) without argument</title>
     <link rel="author" title="Jun Ichikawa" href="mailto:jun1ka0@gmail.com">
     <link rel="reviewer" title="Dirk Schulze" href="mailto:dschulze@adobe.com">
     <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#FilterProperty">
     <link rel="help" href="http://www.w3.org/TR/filter-effects-1/#funcdef-brightness">
     <link rel="match" href="filters-ref-brightness-003.html">
     <meta name="flags" content="">
     <meta name="assert" content="This test verifies that the brightness shorthand works. Green rectangle must shown,
     when brightness is not set.">
     <style type="text/css">
 
         div.brightness_noset {
             width: 200px;
             height: 200px;
             background-color: rgb(0, 255, 0);
+            filter: brightness(0);
             filter: brightness();
         }
     </style>
 </head>
 <body>
     <p>You should see green rectangle.</p>
     <div class="brightness_noset"></div>
 
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/filter-effects/support/filter-external-002-filter.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+	<filter id="filter" color-interpolation-filters="sRGB">
+		<feColorMatrix type="hueRotate" in="SourceGraphic" values="150"/>
+	</filter>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_feature_policy.tentative.sub.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src=/feature-policy/resources/featurepolicy.js></script>
+  <script>
+  run_all_fp_tests_allow_all(
+      'http://{{domains[www]}}:{{ports[http][0]}}',
+      'document-domain',
+      'SecurityError',
+      () => {
+        return new Promise((resolve, reject) => {
+          try {
+            document.domain = "{{domains[]}}";
+            resolve();
+          } catch(e) {
+            reject(e);
+          }
+       });
+      });
+  </script>
+</body>
--- a/testing/web-platform/tests/infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/testdriver/actions/elementPosition.html.ini
@@ -1,3 +1,3 @@
 [elementPosition.html]
-  expected:
-    if product == "chrome": ERROR
+  [TestDriver actions: element position]
+    expected: FAIL
--- a/testing/web-platform/tests/infrastructure/metadata/infrastructure/testdriver/actions/eventOrder.html.ini
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/testdriver/actions/eventOrder.html.ini
@@ -1,3 +1,3 @@
 [eventOrder.html]
-  expected:
-    if product == "chrome": ERROR
+  [TestDriver actions: event order]
+    expected: FAIL
--- a/testing/web-platform/tests/infrastructure/testdriver/actions/elementPosition.html
+++ b/testing/web-platform/tests/infrastructure/testdriver/actions/elementPosition.html
@@ -29,15 +29,15 @@ async_test(t => {
   test.addEventListener("click", e => {
     events.push(e.clientX);
     events.push(e.clientY)
   });
 
   let div = document.getElementById("test");
   let actions = new test_driver.Actions()
     .pointerMove(0, 0, {origin: test})
-    .pointerDown()
+    .pointerDown(0, 0, {origin: test})
     .pointerUp()
     .send()
     .then(t.step_func_done(() => assert_array_equals(events, [50, 25])))
     .catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e)));
 });
 </script>
--- a/testing/web-platform/tests/infrastructure/testdriver/actions/eventOrder.html
+++ b/testing/web-platform/tests/infrastructure/testdriver/actions/eventOrder.html
@@ -12,26 +12,24 @@
 
 <script>
 // Pointer 1 is added before Pointer 2 so it comes first in the list of sources
 // Therefore its actions happen first
 let events = [];
 
 async_test(t => {
   Array.prototype.forEach.call(document.getElementsByTagName("button"),
-                               (x) => x.addEventListener("mousedown", () => {events.push(x.id)}));
+                               (x) => x.addEventListener("pointerdown", () => {events.push(x.id)}));
 
   let button_a = document.getElementById("a");
   let button_b = document.getElementById("b");
   let actions = new test_driver.Actions()
-    .addPointer("pointer1")
-    .addPointer("pointer2")
-    .pointerMove(0, 0, {origin: button_a, sourceName: "pointer1"})
-    .pointerMove(0, 0, {origin: button_b, sourceName: "pointer2"})
-    .pointerDown({sourceName: "pointer2"})
-    .pointerDown({sourceName: "pointer1"})
+    .addPointer("pointer1", "touch")
+    .addPointer("pointer2", "touch")
+    .pointerDown(0, 0, {origin: button_a, sourceName: "pointer1"})
+    .pointerDown(0, 0, {origin: button_b, sourceName: "pointer2"})
+    .pointerUp({sourceName: "pointer1"})
     .pointerUp({sourceName: "pointer2"})
-    .pointerUp({sourceName: "pointer1"})
     .send()
     .then(t.step_func_done(() => assert_array_equals(events, ["a", "b"])))
     .catch(e => t.step_func(() => assert_unreached("Actions sequence failed " + e)));
 });
 </script>
--- a/testing/web-platform/tests/lint.whitelist
+++ b/testing/web-platform/tests/lint.whitelist
@@ -373,17 +373,16 @@ SUPPORT-WRONG-DIR: css/css-backgrounds/b
 SUPPORT-WRONG-DIR: css/css-color/htaccess
 SUPPORT-WRONG-DIR: css/css-fonts/font-variant-debug.html
 SUPPORT-WRONG-DIR: css/css-masking/clip-path/svg-clipPath.svg
 SUPPORT-WRONG-DIR: css/css-multicol/multicol-red.png
 SUPPORT-WRONG-DIR: css/CSS2/section-index.xht
 SUPPORT-WRONG-DIR: css/CSS2/other-formats/xml/background-18.css
 SUPPORT-WRONG-DIR: css/CSS2/other-formats/xml/background-19-alt.xml
 SUPPORT-WRONG-DIR: css/CSS2/other-formats/xml/background-19.css
-SUPPORT-WRONG-DIR: css/filter-effects/filter-external-002-filter.svg
 SUPPORT-WRONG-DIR: css/vendor-imports/mozilla/mozilla-central-reftests/check-for-references.sh
 SUPPORT-WRONG-DIR: css/vendor-imports/mozilla/mozilla-central-reftests/sync-tests-filter
 SUPPORT-WRONG-DIR: css/vendor-imports/mozilla/mozilla-central-reftests/sync-tests.sh
 SUPPORT-WRONG-DIR: css/vendor-imports/mozilla/mozilla-central-reftests/masking/blank.html
 SUPPORT-WRONG-DIR: css/WOFF2/testcaseindex.xht
 NON-EXISTENT-REF: css/css-masking/clip-path-svg-content/clip-path-clip-rule-008.svg
 
 
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/picture-in-picture/mediastream.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>Test mediastream video in Picture-in-Picture</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="resources/picture-in-picture-helpers.js"></script>
+<body></body>
+<script>
+promise_test(async t => {
+  const canvas = document.createElement('canvas');
+  const video = document.createElement('video');
+  const mediastreamVideoLoadedPromise = new Promise((resolve, reject) => {
+    video.autoplay = true;
+    video.srcObject = canvas.captureStream(60 /* fps */);
+    video.onloadedmetadata = () => {
+      resolve(video);
+    };
+    video.onerror = error => {
+      reject(error);
+    };
+  });
+  await mediastreamVideoLoadedPromise;
+
+  return requestPictureInPictureWithTrustedClick(video)
+  .then(pipWindow => {
+    assert_not_equals(pipWindow.width, 0);
+    assert_not_equals(pipWindow.height, 0);
+  });
+}, 'request Picture-in-Picture resolves on user click with Picture-in-Picture window');
+</script>
--- a/testing/web-platform/tests/picture-in-picture/shadow-dom.html
+++ b/testing/web-platform/tests/picture-in-picture/shadow-dom.html
@@ -53,10 +53,11 @@ promise_test(async t => {
   .then(() => {
     assert_equals(document.pictureInPictureElement, ids.host2);
     assert_equals(ids.root.pictureInPictureElement, null);
     assert_equals(ids.root2.pictureInPictureElement, ids.host3);
     assert_equals(ids.root3.pictureInPictureElement, ids.video);
     assert_equals(ids.root4.pictureInPictureElement, null);
     assert_equals(ids.root5.pictureInPictureElement, null);
   })
+  .then(() => document.exitPictureInPicture());
 });
 </script>
deleted file mode 100644
--- a/testing/web-platform/tests/pointerevents/pointerevent_pointermove-manual.html
+++ /dev/null
@@ -1,44 +0,0 @@
-<!doctype html>
-<html>
-    <head>
-        <title>Pointermove</title>
-        <meta name="viewport" content="width=device-width">
-        <meta name="assert" content="When a pointer changes coordinates, the pointermove event must be dispatched."/>
-        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
-        <script src="/resources/testharness.js"></script>
-        <script src="/resources/testharnessreport.js"></script>
-        <!-- Additional helper script for common checks across event types -->
-        <script type="text/javascript" src="pointerevent_support.js"></script>
-    </head>
-    <body onload="run()">
-        <h2>PointerMove</h2>
-        <h4>Test Description: This test checks if pointermove event triggers. Move your mouse over the black rectangle or slide it if you are using touchscreen.</h4>
-        <div id="target0" style="background:black"></div>
-        <script>
-            var eventTested = false;
-            var detected_pointertypes = {};
-            var test_pointermove = async_test("pointermove event received");
-            add_completion_callback(showPointerTypes);
-
-            function run() {
-                var target0 = document.getElementById("target0");
-
-                // When a pointer changes coordinates, the pointermove event must be dispatched.
-                // TA: 5.3
-                on_event(target0, "pointermove", function (event) {
-                    detected_pointertypes[event.pointerType] = true;
-                    if (eventTested == false) {
-                        test_pointermove.done();
-                        eventTested = true;
-                    }
-                });
-            }
-        </script>
-        <h1>Pointer Events pointermove Tests</h1>
-        <div id="complete-notice">
-            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
-            <p>Refresh the page to run the tests again with a different pointer type.</p>
-        </div>
-        <div id="log"></div>
-    </body>
-</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/pointerevents/pointerevent_pointermove.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<html>
+    <head>
+        <title>Pointermove</title>
+        <meta name="viewport" content="width=device-width">
+        <meta name="assert" content="When a pointer changes coordinates, the pointermove event must be dispatched."/>
+        <link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
+        <script src="/resources/testharness.js"></script>
+        <script src="/resources/testharnessreport.js"></script>
+        <script src="/resources/testdriver.js"></script>
+        <script src="/resources/testdriver-actions.js"></script>
+        <script src="/resources/testdriver-vendor.js"></script>
+        <!-- Additional helper script for common checks across event types -->
+        <script type="text/javascript" src="pointerevent_support.js"></script>
+    </head>
+    <body onload="run()">
+        <h2>PointerMove</h2>
+        <h4>Test Description: This test checks if pointermove event triggers. Move your mouse over the black rectangle or slide it if you are using touchscreen.</h4>
+        <div id="target0" style="background:black"></div>
+        <script>
+            var eventTested = false;
+            var detected_pointertypes = {};
+            var test_pointermove = async_test("pointermove event received");
+            add_completion_callback(showPointerTypes);
+
+            function run() {
+                var target0 = document.getElementById("target0");
+
+                // When a pointer changes coordinates, the pointermove event must be dispatched.
+                // TA: 5.3
+                on_event(target0, "pointermove", function (event) {
+                    detected_pointertypes[event.pointerType] = true;
+                    if (eventTested == false) {
+                        test_pointermove.done();
+                        eventTested = true;
+                    }
+                });
+
+                // Inject the inputs to run this test.
+                new test_driver.Actions().pointerMove(0, 0, {origin: target0}).send();
+            }
+        </script>
+        <h1>Pointer Events pointermove Tests</h1>
+        <div id="complete-notice">
+            <p>The following pointer types were detected: <span id="pointertype-log"></span>.</p>
+            <p>Refresh the page to run the tests again with a different pointer type.</p>
+        </div>
+        <div id="log"></div>
+    </body>
+</html>
\ No newline at end of file
--- a/testing/web-platform/tests/resources/testdriver-actions.js
+++ b/testing/web-platform/tests/resources/testdriver-actions.js
@@ -17,16 +17,24 @@
     for (let sourceType of this.sourceTypes.keys()) {
       this.currentSources.set(sourceType, null);
     }
     this.createSource("general");
     this.tickIdx = 0;
   }
 
   Actions.prototype = {
+    ButtonType: {
+      LEFT: 0,
+      MIDDLE: 1,
+      RIGHT: 2,
+      BACK: 3,
+      FORWARD: 4,
+    },
+
     /**
      * Generate the action sequence suitable for passing to
      * test_driver.action_sequence
      *
      * @returns {Array} Array of WebDriver-compatible actions sequences
      */
     serialize: function() {
       let actions = [];
@@ -93,17 +101,17 @@
     /**
      * Add a new key input source with the given name
      *
      * @param {String} name - Name of the key source
      * @param {Bool} set - Set source as the default key source
      * @returns {Actions}
      */
     addKeyboard: function(name, set=true) {
-      this.createSource("key", name, true);
+      this.createSource("key", name);
       if (set) {
         this.setKeyboard(name);
       }
       return this;
     },
 
     /**
      * Set the current default key source
@@ -120,17 +128,17 @@
      * Add a new pointer input source with the given name
      *
      * @param {String} type - Name of the key source
      * @param {String} pointerType - Type of pointing device
      * @param {Bool} set - Set source as the default key source
      * @returns {Actions}
      */
     addPointer: function(name, pointerType="mouse", set=true) {
-      this.createSource("pointer", name, true, {pointerType: pointerType});
+      this.createSource("pointer", name, {pointerType: pointerType});
       if (set) {
         this.setPointer(name);
       }
       return this;
     },
 
     /**
      * Set the current default pointer source
@@ -220,31 +228,31 @@
     /**
      * Create a pointerDown event for the current default pointer source
      *
      * @param {String} button - Button to press
      * @param {String?} sourceName - Named pointer source to use or null for the default
      *                               pointer source
      * @returns {Actions}
      */
-    pointerDown: function({button=0, sourceName=null}={}) {
+    pointerDown: function(x, y, {origin="viewport", button=this.ButtonType.LEFT, sourceName=null}={}) {
       let source = this.getSource("pointer", sourceName);
-      source.pointerDown(this, button);
+      source.pointerDown(this, button, x, y, origin);
       return this;
     },
 
     /**
      * Create a pointerUp event for the current default pointer source
      *
      * @param {String} button - Button to release
      * @param {String?} sourceName - Named pointer source to use or null for the default pointer
      *                               source
      * @returns {Actions}
      */
-    pointerUp: function({button=0, sourceName=null}={}) {
+    pointerUp: function({button=this.ButtonType.LEFT, sourceName=null}={}) {
       let source = this.getSource("pointer", sourceName);
       source.pointerUp(this, button);
       return this;
     },
 
     /**
      * Create a move event for the current default pointer source
      *
@@ -354,22 +362,22 @@
           actions.push(this.actions.get(i));
         } else {
           actions.push({"type": "pause"});
         }
       }
       return data;
     },
 
-    pointerDown: function(actions, button) {
+    pointerDown: function(actions, button, x, y, origin) {
       let tick = actions.tickIdx;
       if (this.actions.has(tick)) {
         tick = actions.addTick().tickIdx;
       }
-      this.actions.set(tick, {type: "pointerDown", button});
+      this.actions.set(tick, {type: "pointerDown", button, x, y, origin});
     },
 
     pointerUp: function(actions, button) {
       let tick = actions.tickIdx;
       if (this.actions.has(tick)) {
         tick = actions.addTick().tickIdx;
       }
       this.actions.set(tick, {type: "pointerUp", button});
--- a/testing/web-platform/tests/resources/testdriver.js
+++ b/testing/web-platform/tests/resources/testdriver.js
@@ -187,17 +187,17 @@
                                     input source and each input source itself has an actions
                                     property detailing the behaviour of that source at each timestep
                                     (or tick). Authors are not expected to construct the actions
                                     sequence by hand, but to use the builder api provided in
                                     testdriver-actions.js
          * @returns {Promise} fufiled after the actions are performed, or rejected in
          *                    the cases the WebDriver command errors
          */
-        action_sequence(actions) {
+        action_sequence: function(actions) {
             return window.test_driver_internal.action_sequence(actions);
         }
     };
 
     window.test_driver_internal = {
         /**
          * Triggers a user-initiated click
          *
@@ -228,16 +228,16 @@
          */
         freeze: function() {
             return Promise.reject(new Error("unimplemented"));
         },
 
         /**
          * Send a sequence of pointer actions
          *
-         * @returns {Promise} fufilled after actions are sent, rejected if any actions
+         * @returns {Promise} fulfilled after actions are sent, rejected if any actions
          *                    fail
          */
         action_sequence: function(actions) {
             return Promise.reject(new Error("unimplemented"));
         }
     };
 })();
--- a/testing/web-platform/tests/screen-capture/getdisplaymedia.https.html
+++ b/testing/web-platform/tests/screen-capture/getdisplaymedia.https.html
@@ -1,150 +1,141 @@
 <!doctype html>
 <meta charset=utf-8>
-<title>RTCDTMFSender.prototype.insertDTMF</title>
+<title>getDisplayMedia</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
   'use strict';
+test(() => {
+  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
+}, "getDisplayMedia in navigator.mediaDevices");
 
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   const stream = await navigator.mediaDevices.getDisplayMedia({video: true});
   const [track] = stream.getTracks();
   t.add_cleanup(() => track.stop());
   assert_equals(stream.getTracks().length, 1);
   assert_equals(stream.getVideoTracks().length, 1);
   assert_equals(stream.getAudioTracks().length, 0);
 }, 'getDisplayMedia() with video true');
 
 // Empty constraint parameter and boolean values of false defaults to
 // {video: true}. This is described in items 3-4 of section 5.1, see
 // https://w3c.github.io/mediacapture-screen-share/#navigator-additions.
 // Note that this results in some non-intuitive cases returning a video track,
 // i.e. {video: false}.
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   const stream = await navigator.mediaDevices.getDisplayMedia();
   const [track] = stream.getTracks();
   t.add_cleanup(() => track.stop());
   assert_equals(stream.getTracks().length, 1);
   assert_equals(stream.getVideoTracks().length, 1);
   assert_equals(stream.getAudioTracks().length, 0);
 }, 'getDisplayMedia() with no constraints');
 
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   const stream = await navigator.mediaDevices.getDisplayMedia({video: false});
   const [track] = stream.getTracks();
   t.add_cleanup(() => track.stop());
   assert_equals(stream.getTracks().length, 1);
   assert_equals(stream.getVideoTracks().length, 1);
   assert_equals(stream.getAudioTracks().length, 0);
 }, 'getDisplayMedia() with video false');
 
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   const stream = await navigator.mediaDevices.getDisplayMedia({audio: false});
   const [track] = stream.getTracks();
   t.add_cleanup(() => track.stop());
   assert_equals(stream.getTracks().length, 1);
   assert_equals(stream.getVideoTracks().length, 1);
   assert_equals(stream.getAudioTracks().length, 0);
 }, 'getDisplayMedia() with audio false');
 
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   const stream = await navigator.mediaDevices.getDisplayMedia({audio: true});
   const [track] = stream.getTracks();
   t.add_cleanup(() => track.stop());
   assert_equals(stream.getTracks().length, 1);
   assert_equals(stream.getVideoTracks().length, 0);
   assert_equals(stream.getAudioTracks().length, 1);
 }, 'getDisplayMedia() with audio true');
 
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   try {
     const stream = await navigator.mediaDevices.getDisplayMedia(
         {video: {advanced: [{zoom: 1}]}});
   } catch (err) {
     assert_equals(err.name, 'TypeError');
     return;
   }
   assert_unreached('getDisplayMedia should have failed');
 }, 'getDisplayMedia() with advanced constraint');
 
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   try {
     const stream = await navigator.mediaDevices.getDisplayMedia(
         {video: {width: {min: 360}}});
   } catch (err) {
     assert_equals(err.name, 'TypeError');
     return;
   }
   assert_unreached('getDisplayMedia should have failed');
 }, 'getDisplayMedia() with min constraint');
 
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   try {
     const stream = await navigator.mediaDevices.getDisplayMedia(
         {video: {width: {exact: 360}}});
   } catch (err) {
     assert_equals(err.name, 'TypeError');
     return;
   }
   assert_unreached('getDisplayMedia should have failed');
 }, 'getDisplayMedia() with exact constraint');
 
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   const maxWidth = 360;
   const stream = await navigator.mediaDevices.getDisplayMedia(
       {video: {width: {max: maxWidth}}});
   const [track] = stream.getTracks();
   t.add_cleanup(() => track.stop());
   assert_equals(stream.getVideoTracks().length, 1);
   assert_equals(stream.getAudioTracks().length, 0);
   assert_less_than_equal(
       stream.getVideoTracks()[0].getSettings().width, maxWidth);
 }, 'getDisplayMedia() with max constraint');
 
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   const maxWidth = 360;
   const maxFrameRate = 4;
   const stream = await navigator.mediaDevices.getDisplayMedia(
       {video: {width: {max: maxWidth}, frameRate: {max: maxFrameRate}}});
   const [track] = stream.getTracks();
   t.add_cleanup(() => track.stop());
   assert_equals(stream.getVideoTracks().length, 1);
   assert_equals(stream.getAudioTracks().length, 0);
   const settings = stream.getVideoTracks()[0].getSettings();
   assert_less_than_equal(settings.width, maxWidth);
   assert_less_than_equal(settings.frameRate, maxFrameRate);
 }, 'getDisplayMedia() with constraints applied');
 
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   try {
     const stream = await navigator.mediaDevices.getDisplayMedia(
         {video: {width: {max: 0}}});
   } catch (err) {
     assert_equals(err.name, 'OverconstrainedError');
     return;
   }
   assert_unreached('getDisplayMedia should have failed');
 }, 'getDisplayMedia() overconstrained');
 
 // Content shell picks a fake desktop device by default.
 promise_test(async t => {
-  assert_idl_attribute(navigator.mediaDevices, 'getDisplayMedia');
   const stream = await navigator.mediaDevices.getDisplayMedia({video: true});
   const [track] = stream.getTracks();
   t.add_cleanup(() => track.stop());
   assert_equals(stream.getVideoTracks().length, 1);
   assert_equals(stream.getAudioTracks().length, 0);
   const settings = stream.getVideoTracks()[0].getSettings();
   assert_any(
       assert_equals, settings.displaySurface,
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/screen-capture/historical.https.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>getDisplayMedia historical tests</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(function() {
+    assert_false('getDisplayMedia' in navigator);
+}, 'navigator.getDisplayMedia should not exist');
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/classic-worker.js
@@ -0,0 +1,1 @@
+importScripts('./imported-classic-script.js');
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/service-workers/service-worker/resources/module-worker.js
@@ -0,0 +1,1 @@
+import * as module from './imported-module-script.js';
--- a/testing/web-platform/tests/service-workers/service-worker/update-registration-with-type.https.html
+++ b/testing/web-platform/tests/service-workers/service-worker/update-registration-with-type.https.html
@@ -2,73 +2,207 @@
 <meta charset="utf-8">
 <title>Service Worker: Update the registration with a different script type.</title>
 <!-- common.js is for guid() -->
 <script src="/mixed-content/generic/common.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <script>
-// These tests check that a registration is updated correctly with
-// different script type. At first Service Worker is register as
+// The following two tests check that a registration is updated correctly
+// with different script type. At first Service Worker is registered as
 // classic script type, then it is re-registered as module script type,
 // and vice versa. A main script is also updated at the same time.
 promise_test(async t => {
   const key = guid();
   const script = `resources/update-registration-with-type.py?classic_first=1&key=${key}`;
   const scope = 'resources/update-registration-with-type';
   await service_worker_unregister(t, scope);
+  t.add_cleanup(() => service_worker_unregister(t, scope));
 
   // Register with classic script type.
   const firstRegistration = await navigator.serviceWorker.register(script, {
     scope: scope,
     type: 'classic'
   });
-  firstRegistration.installing.postMessage(' ');
-  let msgEvent = await new Promise(resolve => {
-    navigator.serviceWorker.onmessage = resolve;
-  });
+  const firstWorker = firstRegistration.installing;
+  await wait_for_state(t, firstWorker, 'activated');
+  firstWorker.postMessage(' ');
+  let msgEvent = await new Promise(r => navigator.serviceWorker.onmessage = r);
   assert_equals(msgEvent.data, 'A classic script.');
 
   // Re-register with module script type.
   const secondRegistration = await navigator.serviceWorker.register(script, {
     scope: scope,
     type: 'module'
   });
-  secondRegistration.installing.postMessage(' ');
-  msgEvent = await new Promise(resolve => {
-    navigator.serviceWorker.onmessage = resolve;
-  });
+  const secondWorker = secondRegistration.installing;
+  secondWorker.postMessage(' ');
+  msgEvent = await new Promise(r => navigator.serviceWorker.onmessage = r);
   assert_equals(msgEvent.data, 'A module script.');
+
+  assert_not_equals(firstWorker, secondWorker);
   assert_equals(firstRegistration, secondRegistration);
 }, 'Update the registration with a different script type (classic => module).');
 
 promise_test(async t => {
   const key = guid();
   const script = `resources/update-registration-with-type.py?classic_first=0&key=${key}`;
   const scope = 'resources/update-registration-with-type';
   await service_worker_unregister(t, scope);
+  t.add_cleanup(() => service_worker_unregister(t, scope));
 
   // Register with module script type.
   const firstRegistration = await navigator.serviceWorker.register(script, {
     scope: scope,
     type: 'module'
   });
-  firstRegistration.installing.postMessage(' ');
-  let msgEvent = await new Promise(resolve => {
-    navigator.serviceWorker.onmessage = resolve;
-  });
+  const firstWorker = firstRegistration.installing;
+  await wait_for_state(t, firstWorker, 'activated');
+  firstWorker.postMessage(' ');
+  let msgEvent = await new Promise(r => navigator.serviceWorker.onmessage = r);
   assert_equals(msgEvent.data, 'A module script.');
 
   // Re-register with classic script type.
   const secondRegistration = await navigator.serviceWorker.register(script, {
     scope: scope,
     type: 'classic'
   });
-  secondRegistration.installing.postMessage(' ');
-  msgEvent = await new Promise(resolve => {
-    navigator.serviceWorker.onmessage = resolve;
-  });
+  const secondWorker = secondRegistration.installing;
+  secondWorker.postMessage(' ');
+  msgEvent = await new Promise(r => navigator.serviceWorker.onmessage = r);
   assert_equals(msgEvent.data, 'A classic script.');
+
+  assert_not_equals(firstWorker, secondWorker);
   assert_equals(firstRegistration, secondRegistration);
 }, 'Update the registration with a different script type (module => classic).');
+
+// The following two tests change the script type while keeping
+// the script identical.
+promise_test(async t => {
+  const script = 'resources/empty-worker.js';
+  const scope = 'resources/update-registration-with-type';
+  await service_worker_unregister(t, scope);
+  t.add_cleanup(() => service_worker_unregister(t, scope));
+
+  // Register with classic script type.
+  const firstRegistration = await navigator.serviceWorker.register(script, {
+    scope: scope,
+    type: 'classic'
+  });
+  const firstWorker = firstRegistration.installing;
+  await wait_for_state(t, firstWorker, 'activated');
+
+  // Re-register with module script type.
+  const secondRegistration = await navigator.serviceWorker.register(script, {
+    scope: scope,
+    type: 'module'
+  });
+  const secondWorker = secondRegistration.installing;
+
+  assert_not_equals(firstWorker, secondWorker);
+  assert_equals(firstRegistration, secondRegistration);
+}, 'Update the registration with a different script type (classic => module) '
+    + 'and with a same main script.');
+
+promise_test(async t => {
+  const script = 'resources/empty-worker.js';
+  const scope = 'resources/update-registration-with-type';
+  await service_worker_unregister(t, scope);
+  t.add_cleanup(() => service_worker_unregister(t, scope));
+
+  // Register with module script type.
+  const firstRegistration = await navigator.serviceWorker.register(script, {
+    scope: scope,
+    type: 'module'
+  });
+  const firstWorker = firstRegistration.installing;
+  await wait_for_state(t, firstWorker, 'activated');
+
+  // Re-register with classic script type.
+  const secondRegistration = await navigator.serviceWorker.register(script, {
+    scope: scope,
+    type: 'classic'
+  });
+  const secondWorker = secondRegistration.installing;
+
+  assert_not_equals(firstWorker, secondWorker);
+  assert_equals(firstRegistration, secondRegistration);
+}, 'Update the registration with a different script type (module => classic) '
+    + 'and with a same main script.');
+
+// This test checks that a registration is not updated with the same script
+// type and the same main script.
+promise_test(async t => {
+  const script = 'resources/empty-worker.js';
+  const scope = 'resources/update-registration-with-type';
+  await service_worker_unregister(t, scope);
+  t.add_cleanup(() => service_worker_unregister(t, scope));
+
+  // Register with module script type.
+  const firstRegistration = await navigator.serviceWorker.register(script, {
+    scope: scope,
+    type: 'module'
+  });
+  await wait_for_state(t, firstRegistration.installing, 'activated');
+
+  // Re-register with module script type.
+  const secondRegistration = await navigator.serviceWorker.register(script, {
+    scope: scope,
+    type: 'module'
+  });
+  assert_equals(secondRegistration.installing, null);
+
+  assert_equals(firstRegistration, secondRegistration);
+}, 'Does not update the registration with the same script type and '
+    + 'the same main script.');
+
+// In the case (classic => module), a worker script contains importScripts()
+// that is disallowed on module scripts, so the second registration is
+// expected to fail script evaluation.
+promise_test(async t => {
+  const script = 'resources/classic-worker.js';
+  const scope = 'resources/update-registration-with-type';
+  await service_worker_unregister(t, scope);
+  t.add_cleanup(() => service_worker_unregister(t, scope));
+
+  // Register with classic script type.
+  const firstRegistration = await navigator.serviceWorker.register(script, {
+    scope: scope,
+    type: 'classic'
+  });
+  assert_not_equals(firstRegistration.installing, null);
+  await wait_for_state(t, firstRegistration.installing, 'activated');
+
+  // Re-register with module script type and expect TypeError.
+  return promise_rejects(t, new TypeError, navigator.serviceWorker.register(script, {
+    scope: scope,
+    type: 'module'
+  }), 'Registering with invalid evaluation should be failed.');
+}, 'Update the registration with a different script type (classic => module) '
+    + 'and with a same main script. Expect evaluation failed.');
+
+// In the case (module => classic), a worker script contains static-import
+// that is disallowed on classic scripts, so the second registration is
+// expected to fail script evaluation.
+promise_test(async t => {
+  const script = 'resources/module-worker.js';
+  const scope = 'resources/update-registration-with-type';
+  await service_worker_unregister(t, scope);
+  t.add_cleanup(() => service_worker_unregister(t, scope));
+
+  // Register with module script type.
+  const firstRegistration = await navigator.serviceWorker.register(script, {
+    scope: scope,
+    type: 'module'
+  });
+  assert_not_equals(firstRegistration.installing, null);
+  await wait_for_state(t, firstRegistration.installing, 'activated');
+
+  // Re-register with classic script type and expect TypeError.
+  return promise_rejects(t, new TypeError, navigator.serviceWorker.register(script, {
+    scope: scope,
+    type: 'classic'
+  }), 'Registering with invalid evaluation should be failed.');
+}, 'Update the registration with a different script type (module => classic) '
+    + 'and with a same main script. Expect evaluation failed.');
 </script>
 </body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/inheritance.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>Inheritance of geometry properties</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html"/>
+    <h:meta name="assert" content="None of the geometry properties inherit."/>
+    <h:meta name="assert" content="Properties have initial values according to spec."/>
+  </metadata>
+  <g id="container">
+      <g id="target"></g>
+  </g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/inheritance-testcommon.js"/>
+  <script><![CDATA[
+
+assert_not_inherited('cx', '0px', '-10px');
+assert_not_inherited('cy', '0px', '-10px');
+assert_not_inherited('r', '0px', '10px');
+assert_not_inherited('rx', 'auto', '10px');
+assert_not_inherited('ry', 'auto', '10px');
+assert_not_inherited('x', '0px', '-10px');
+assert_not_inherited('y', '0px', '-10px');
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/cx-invalid.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing cx with invalid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#CX"/>
+    <h:meta name="assert" content="cx supports only the grammar '&lt;length-percentage&gt;'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_invalid_value("cx", "10");
+test_invalid_value("cx", "auto");
+test_invalid_value("cx", "10px 20px");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/cx-valid.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing cx with valid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#CX"/>
+    <h:meta name="assert" content="cx supports the full grammar '&lt;length-percentage&gt;'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_valid_value("cx", "0", "0px");
+test_valid_value("cx", "-1px");
+test_valid_value("cx", "calc(2em + 3ex)");
+test_valid_value("cx", "4%");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/cy-invalid.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing cy with invalid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#CY"/>
+    <h:meta name="assert" content="cy supports only the grammar '&lt;length-percentage&gt;'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_invalid_value("cy", "10");
+test_invalid_value("cy", "auto");
+test_invalid_value("cy", "10px 20px");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/cy-valid.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing cy with valid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#CY"/>
+    <h:meta name="assert" content="cy supports the full grammar '&lt;length-percentage&gt;'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_valid_value("cy", "0", "0px");
+test_valid_value("cy", "-1px");
+test_valid_value("cy", "calc(2em + 3ex)");
+test_valid_value("cy", "4%");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/r-invalid.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing r with invalid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#R"/>
+    <h:meta name="assert" content="r supports only the grammar '&lt;length-percentage&gt;'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_invalid_value("r", "10");
+test_invalid_value("r", "auto");
+test_invalid_value("r", "10px 20px");
+test_invalid_value("r", "-1px");
+test_invalid_value("r", "-10%");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/r-valid.svg
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing r with valid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#R"/>
+    <h:meta name="assert" content="r supports the full grammar '&lt;length-percentage&gt;'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_valid_value("r", "0", "0px");
+test_valid_value("r", "1px");
+test_valid_value("r", "calc(2em + 3ex)");
+test_valid_value("r", "4%");
+test_valid_value("r", "5vmin");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/rx-invalid.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing rx with invalid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#RX"/>
+    <h:meta name="assert" content="rx supports only the grammar '&lt;length-percentage&gt; | auto'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_invalid_value("rx", "10");
+test_invalid_value("rx", "none");
+test_invalid_value("rx", "10px 20px");
+test_invalid_value("rx", "-1px");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/rx-valid.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing rx with valid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#RX"/>
+    <h:meta name="assert" content="rx supports the full grammar '&lt;length-percentage&gt; | auto'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_valid_value("rx", "auto");
+
+test_valid_value("rx", "0", "0px");
+test_valid_value("rx", "1px");
+test_valid_value("rx", "calc(2em + 3ex)");
+test_valid_value("rx", "4%");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/ry-invalid.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing rx with invalid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#RY"/>
+    <h:meta name="assert" content="rx supports only the grammar '&lt;length-percentage&gt; | auto'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_invalid_value("rx", "10");
+test_invalid_value("rx", "none");
+test_invalid_value("rx", "10px 20px");
+test_invalid_value("rx", "-1px");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/ry-valid.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing rx with valid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#RY"/>
+    <h:meta name="assert" content="rx supports the full grammar '&lt;length-percentage&gt; | auto'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_valid_value("rx", "auto");
+
+test_valid_value("rx", "0", "0px");
+test_valid_value("rx", "1px");
+test_valid_value("rx", "calc(2em + 3ex)");
+test_valid_value("rx", "4%");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/x-invalid.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing x with invalid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#X"/>
+    <h:meta name="assert" content="x supports only the grammar '&lt;length-percentage&gt;'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_invalid_value("x", "10");
+test_invalid_value("x", "auto");
+test_invalid_value("x", "10px 20px");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/x-valid.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing x with valid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#X"/>
+    <h:meta name="assert" content="x supports the full grammar '&lt;length-percentage&gt;'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_valid_value("x", "0", "0px");
+test_valid_value("x", "-1px");
+test_valid_value("x", "calc(2em + 3ex)");
+test_valid_value("x", "4%");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/y-invalid.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing y with invalid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#Y"/>
+    <h:meta name="assert" content="y supports only the grammar '&lt;length-percentage&gt;'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_invalid_value("y", "10");
+test_invalid_value("y", "auto");
+test_invalid_value("y", "10px 20px");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/geometry/parsing/y-valid.svg
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>SVG Geometry Properties: parsing y with valid values</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#Y"/>
+    <h:meta name="assert" content="y supports the full grammar '&lt;length-percentage&gt;'."/>
+  </metadata>
+  <g id="target"></g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/parsing-testcommon.js"/>
+  <script><![CDATA[
+
+test_valid_value("y", "0", "0px");
+test_valid_value("y", "-1px");
+test_valid_value("y", "calc(2em + 3ex)");
+test_valid_value("y", "4%");
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/painting/inheritance.svg
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>Inheritance of SVG painting properties</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/painting.html"/>
+    <h:meta name="assert" content="properties inherit according to the spec."/>
+    <h:meta name="assert" content="properties have expected initial values."/>
+  </metadata>
+  <g id="container">
+      <g id="target"></g>
+  </g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/inheritance-testcommon.js"/>
+  <script><![CDATA[
+
+assert_inherited('fill', 'rgb(0, 0, 0)', 'rgb(42, 53, 64)');
+assert_inherited('fill-rule', 'nonzero', 'evenodd');
+assert_inherited('fill-opacity', '1', '0.5');
+assert_inherited('stroke', 'none', 'rgb(42, 53, 64)');
+assert_inherited('stroke-opacity', '1', '0.5');
+assert_inherited('stroke-width', '1px', '3px');
+assert_inherited('stroke-linecap', 'butt', 'round');
+assert_inherited('stroke-linejoin', 'miter', 'round');
+assert_inherited('stroke-miterlimit', '4', '12');
+assert_inherited('stroke-dasharray', 'none', '1px, 2px, 3px');
+assert_inherited('stroke-dashoffset', '0px', '50%');
+assert_inherited('marker-start', 'none', 'url("https://example/com/diagram.svg#marker")');
+assert_inherited('marker-mid', 'none', 'url("https://example/com/diagram.svg#marker")');
+assert_inherited('marker-end', 'none', 'url("https://example/com/diagram.svg#marker")');
+assert_inherited('paint-order', 'normal', 'markers stroke');
+assert_inherited('color-interpolation', 'srgb', 'linearrgb');
+assert_inherited('color-rendering', 'auto', 'optimizespeed');
+assert_inherited('shape-rendering', 'auto', 'optimizespeed');
+assert_inherited('text-rendering', 'auto', 'optimizespeed');
+assert_inherited('image-rendering', 'auto', 'optimizequality');
+
+  ]]></script>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/svg/text/inheritance.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     xmlns:h="http://www.w3.org/1999/xhtml"
+     width="800px" height="8000px">
+  <title>Inheritance of text properties</title>
+  <metadata>
+    <h:link rel="help" href="https://svgwg.org/svg2-draft/text.html"/>
+    <h:meta name="assert" content="text properties do not inherit."/>
+    <h:meta name="assert" content="text properties have expected initial values."/>
+  </metadata>
+  <g id="container">
+      <g id="target"></g>
+  </g>
+  <h:script src="/resources/testharness.js"/>
+  <h:script src="/resources/testharnessreport.js"/>
+  <h:script src="/css/support/inheritance-testcommon.js"/>
+  <script><![CDATA[
+
+assert_not_inherited('inline-size', 'auto', '10px');
+assert_not_inherited('shape-inside', 'auto', 'url("https://example/com/")');
+assert_not_inherited('shape-subtract', 'auto', 'url("https://example/com/")');
+assert_not_inherited('shape-margin', '0px', '10px');
+assert_inherited('text-anchor', 'start', 'middle');
+assert_not_inherited('text-decoration-fill', 'none', 'url("https://example/com/")');
+assert_not_inherited('text-decoration-stroke', 'none', 'url("https://example/com/")');
+
+  ]]></script>
+</svg>
--- a/testing/web-platform/tests/tools/manifest/item.py
+++ b/testing/web-platform/tests/tools/manifest/item.py
@@ -24,17 +24,18 @@ item_types = {}
 
 class ManifestItemMeta(ABCMeta):
     """Custom metaclass that registers all the subclasses in the
     item_types dictionary according to the value of their item_type
     attribute, and otherwise behaves like an ABCMeta."""
 
     def __new__(cls, name, bases, attrs, **kwargs):
         rv = ABCMeta.__new__(cls, name, bases, attrs, **kwargs)
-        item_types[rv.item_type] = rv
+        if rv.item_type:
+            item_types[rv.item_type] = rv
 
         return rv
 
 
 class ManifestItem(object):
     __metaclass__ = ManifestItemMeta
 
     item_type = None
--- a/testing/web-platform/tests/tools/wpt/run.py
+++ b/testing/web-platform/tests/tools/wpt/run.py
@@ -225,16 +225,21 @@ Consider installing certutil via your OS
                                                     self.venv.path,
                                                     channel=kwargs["browser_channel"])
             kwargs["prefs_root"] = prefs_root
 
         if kwargs["headless"] is None:
             kwargs["headless"] = True
             logger.info("Running in headless mode, pass --no-headless to disable")
 
+        # Turn off Firefox WebRTC ICE logging on WPT (turned on by mozrunner)
+        os.unsetenv('R_LOG_LEVEL')
+        os.unsetenv('R_LOG_DESTINATION')
+        os.unsetenv('R_LOG_VERBOSE')
+
         # Allow WebRTC tests to call getUserMedia.
         kwargs["extra_prefs"].append("media.navigator.streams.fake=true")
 
 
 class Fennec(BrowserSetup):
     name = "fennec"
     browser_cls = browser.Fennec
 
--- a/testing/web-platform/tests/tools/wptserve/tests/functional/test_cookies.py
+++ b/testing/web-platform/tests/tools/wptserve/tests/functional/test_cookies.py
@@ -1,9 +1,8 @@
-import sys
 import unittest
 
 import pytest
 
 wptserve = pytest.importorskip("wptserve")
 from .base import TestUsingServer
 
 
@@ -46,17 +45,16 @@ class TestResponseSetCookie(TestUsingSer
         parts = dict(item.split("=") for
                      item in resp.info()["Set-Cookie"].split("; ") if item)
 
         self.assertEqual(parts["name"], "")
         self.assertEqual(parts["Path"], "/")
         #Should also check that expires is in the past
 
 class TestRequestCookies(TestUsingServer):
-    @pytest.mark.xfail(sys.version_info >= (3,), reason="wptserve only works on Py2")
     def test_set_cookie(self):
         @wptserve.handlers.handler
         def handler(request, response):
             return request.cookies["name"].value
 
         route = ("GET", "/test/set_cookie", handler)
         self.server.router.register(*route)
         resp = self.request(route[1], headers={"Cookie": "name=value"})
--- a/testing/web-platform/tests/tools/wptserve/wptserve/request.py
+++ b/testing/web-platform/tests/tools/wptserve/wptserve/request.py
@@ -1,12 +1,12 @@
 import base64
 import cgi
 from six.moves.http_cookies import BaseCookie
-from six import BytesIO, binary_type, text_type
+from six import BytesIO, binary_type, text_type, iteritems, PY3
 import tempfile
 
 from six.moves.urllib.parse import parse_qsl, urlsplit
 
 from . import stash
 from .utils import HTTPException
 
 missing = object()
@@ -314,19 +314,21 @@ class Request(object):
             self.raw_input.seek(pos)
         return self._POST
 
     @property
     def cookies(self):
         if self._cookies is None:
             parser = BaseCookie()
             cookie_headers = self.headers.get("cookie", b"")
+            if PY3:
+                cookie_headers = cookie_headers.decode("iso-8859-1")
             parser.load(cookie_headers)
             cookies = Cookies()
-            for key, value in parser.iteritems():
+            for key, value in iteritems(parser):
                 cookies[key] = CookieValue(value)
             self._cookies = cookies
         return self._cookies
 
     @property
     def headers(self):
         if self._headers is None:
             self._headers = RequestHeaders(self.raw_headers)
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/webrtc/RTCQuicStream-helper.js
@@ -0,0 +1,62 @@
+'use strict';
+
+// This file depends on RTCQuicTransport-helper.js which should be loaded from
+// the main HTML file.
+// The following helper methods are called from RTCQuicTransport-helper.js:
+//   makeTwoConnectedQuicTransports
+
+// Run a test function for as many ways as an RTCQuicStream can transition to
+// the 'closed' state.
+// |test_func| will be called with the test as the first argument and the closed
+//     RTCQuicStream as the second argument.
+function closed_stream_test(test_func, description) {
+  promise_test(async t => {
+    const [ localQuicTransport, remoteQuicTransport ] =
+        await makeTwoConnectedQuicTransports(t);
+    const localStream = localQuicTransport.createStream();
+    localStream.reset();
+    assert_equals(localStream.state, 'closed');
+    return test_func(t, localStream);
+  }, 'Stream closed by local reset(): ' + description);
+
+  promise_test(async t => {
+    const [ localQuicTransport, remoteQuicTransport ] =
+        await makeTwoConnectedQuicTransports(t);
+    const localStream = localQuicTransport.createStream();
+    localStream.write(new Uint8Array(1));
+    const remoteWatcher =
+        new EventWatcher(t, remoteQuicTransport, 'quicstream');
+    const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream');
+    localStream.reset();
+    const remoteStreamWatcher =
+        new EventWatcher(t, remoteStream, 'statechange');
+    await remoteStreamWatcher.wait_for('statechange');
+    assert_equals(remoteStream.state, 'closed');
+    return test_func(t, remoteStream);
+  }, 'Stream closed by remote reset(): ' + description);
+
+  promise_test(async t => {
+    const [ localQuicTransport, remoteQuicTransport ] =
+        await makeTwoConnectedQuicTransports(t);
+    const localStream = localQuicTransport.createStream();
+    localQuicTransport.stop();
+    assert_equals(localStream.state, 'closed');
+    return test_func(t, localStream);
+  }, 'Stream closed by local RTCQuicTransport stop(): ' + description);
+
+  promise_test(async t => {
+    const [ localQuicTransport, remoteQuicTransport ] =
+        await makeTwoConnectedQuicTransports(t);
+    const localStream = localQuicTransport.createStream();
+    localStream.write(new Uint8Array(1));
+    const remoteWatcher =
+        new EventWatcher(t, remoteQuicTransport,
+            [ 'quicstream', 'statechange' ]);
+    const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream');
+    localQuicTransport.stop();
+    await remoteWatcher.wait_for('statechange');
+    assert_equals(localStream.state, 'closed');
+    return test_func(t, localStream);
+  }, 'Stream closed by remote RTCQuicTransport stop(): ' + description);
+}
+
--- a/testing/web-platform/tests/webrtc/RTCQuicStream.https.html
+++ b/testing/web-platform/tests/webrtc/RTCQuicStream.https.html
@@ -1,35 +1,40 @@
 <!doctype html>
 <meta charset=utf-8>
 <title>RTCQuicStream.https.html</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="RTCIceTransport-extension-helper.js"></script>
 <script src="RTCQuicTransport-helper.js"></script>
+<script src="RTCQuicStream-helper.js"></script>
 <script>
 'use strict';
 
 // These tests are based on the following specification:
 // https://w3c.github.io/webrtc-quic/
 
 // The following helper functions are called from RTCQuicTransport-helper.js:
 //   makeStandaloneQuicTransport
 //   makeTwoConnectedQuicTransports
+// The following helper functions are called from RTCQuicStream-helper.js:
+//   closed_stream_test
 
 promise_test(async t => {
   const [ quicTransport, ] = await makeTwoConnectedQuicTransports(t);
   const quicStream = quicTransport.createStream();
   assert_equals(quicStream.transport, quicTransport,
       'Expect transport to be set to the creating RTCQuicTransport.');
   assert_equals(quicStream.state, 'open', `Expect state to be 'open'.`);
   assert_equals(quicStream.readBufferedAmount, 0,
       'Expect read buffered amount to be 0.');
   assert_equals(quicStream.writeBufferedAmount, 0,
       'Expect write buffered amount to be 0.');
+  assert_greater_than(quicStream.maxWriteBufferedAmount, 0,
+      'Expect max write buffered amount to be greater than 0.');
 }, 'createStream() returns an RTCQuicStream with initial properties set.');
 
 promise_test(async t => {
   const quicTransport = await makeStandaloneQuicTransport(t);
   assert_throws('InvalidStateError', () => quicTransport.createStream());
 }, 'createStream() throws if the transport is not connected.');
 
 promise_test(async t => {
@@ -150,9 +155,102 @@ promise_test(async t => {
   const { stream: remoteStream } = await remoteWatcher.wait_for('quicstream');
   const remoteStreamWatcher = new EventWatcher(t, remoteStream, 'statechange');
   await remoteStreamWatcher.wait_for('statechange');
   assert_equals(remoteStream.state, 'closing');
   await remoteStreamWatcher.wait_for('statechange');
   assert_equals(remoteStream.state, 'closed');
 }, 'finish() then reset() fires two statechange events on the remote side.');
 
+promise_test(async t => {
+  const [ localQuicTransport, remoteQuicTransport ] =
+    await makeTwoConnectedQuicTransports(t);
+  const localStream = localQuicTransport.createStream();
+  localStream.write(new Uint8Array(0));
+  assert_equals(localStream.writeBufferedAmount, 0);
+}, 'write() with an empty array does nothing.');
+
+promise_test(async t => {
+  const [ localQuicTransport, remoteQuicTransport ] =
+    await makeTwoConnectedQuicTransports(t);
+  const localStream = localQuicTransport.createStream();
+  localStream.write(new Uint8Array([65]));
+  assert_equals(localStream.writeBufferedAmount, 1);
+  localStream.write(new Uint8Array([66, 67]));
+  assert_equals(localStream.writeBufferedAmount, 3);
+  localStream.write(new Uint8Array([68, 69, 70]));
+  assert_equals(localStream.writeBufferedAmount, 6);
+}, 'write() adds to writeBufferedAmount each call.');
+
+promise_test(async t => {
+  const [ localQuicTransport, remoteQuicTransport ] =
+      await makeTwoConnectedQuicTransports(t);
+  const localStream = localQuicTransport.createStream();
+  localStream.write(new Uint8Array(localStream.maxWriteBufferedAmount));
+  assert_equals(localStream.writeBufferedAmount,
+      localStream.maxWriteBufferedAmount);
+}, 'write() can write exactly maxWriteBufferedAmount.');
+
+promise_test(async t => {
+  const [ localQuicTransport, remoteQuicTransport ] =
+      await makeTwoConnectedQuicTransports(t);
+  const localStream = localQuicTransport.createStream();
+  assert_throws('OperationError',
+      () =>
+          localStream.write(
+              new Uint8Array(localStream.maxWriteBufferedAmount + 1)));
+  assert_equals(localStream.writeBufferedAmount, 0);
+}, 'write() throws if data longer than maxWriteBufferedAmount.');
+
+promise_test(async t => {
+  const [ localQuicTransport, remoteQuicTransport ] =
+      await makeTwoConnectedQuicTransports(t);
+  const localStream = localQuicTransport.createStream();
+  localStream.write(new Uint8Array(10));
+  assert_throws('OperationError',
+      () =>
+          localStream.write(
+              new Uint8Array(localStream.maxWriteBufferedAmount)));
+  assert_equals(localStream.writeBufferedAmount, 10);
+}, 'write() throws if total write buffered amount would be greater than ' +
+    'maxWriteBufferedAmount.');
+
+promise_test(async t => {
+  const [ localQuicTransport, remoteQuicTransport ] =
+      await makeTwoConnectedQuicTransports(t);
+  const localStream = localQuicTransport.createStream();
+  localStream.finish();
+  assert_throws('InvalidStateError',
+      () => localStream.write(new Uint8Array()));
+}, 'write() throws InvalidStateError if finish() has been called.');
+
+closed_stream_test(async (t, stream) => {
+  assert_throws('InvalidStateError', () => stream.write(new Uint8Array()));
+}, 'write() throws InvalidStateError.');
+
+promise_test(async t => {
+  const [ localQuicTransport, remoteQuicTransport ] =
+      await makeTwoConnectedQuicTransports(t);
+  const localStream = localQuicTransport.createStream();
+  localStream.write(new Uint8Array(10));
+  localStream.reset();
+  assert_equals(localStream.writeBufferedAmount, 0);
+}, 'writeBufferedAmount set to 0 after local reset().');
+
+promise_test(async t => {
+  const [ localQuicTransport, remoteQuicTransport ] =
+      await makeTwoConnectedQuicTransports(t);
+  const localStream = localQuicTransport.createStream();
+  localStream.write(new Uint8Array(10));
+  localQuicTransport.stop();
+  assert_equals(localStream.writeBufferedAmount, 0);
+}, 'writeBufferedAmount set to 0 after local RTCQuicTransport stop().');
+
+promise_test(async t => {
+  const [ localQuicTransport, remoteQuicTransport ] =
+      await makeTwoConnectedQuicTransports(t);
+  const localStream = localQuicTransport.createStream();
+  localStream.write(new Uint8Array(10));
+  localStream.finish();
+  assert_equals(localStream.writeBufferedAmount, 10);
+}, 'writeBufferedAmount maintained after finish() has been called.');
+
 </script>
--- a/testing/web-platform/tests/webusb/resources/usb-helpers.js
+++ b/testing/web-platform/tests/webusb/resources/usb-helpers.js
@@ -9,18 +9,19 @@
 //
 //   --enable-blink-features=MojoJS,MojoJSTest
 
 (() => {
   // Load scripts needed by the test API on context creation.
   if ('MojoInterfaceInterceptor' in self) {
     let prefix = '/resources/chromium';
     if ('window' in self) {
-      if (window.location.pathname.includes('/LayoutTests/')) {
-        let root = window.location.pathname.match(/.*LayoutTests/);
+      const pathname = window.location.pathname;
+      if (pathname.includes('/LayoutTests/') || pathname.includes('/web_tests/')) {
+        let root = pathname.match(/.*(?:LayoutTests|web_tests)/);
         prefix = `${root}/external/wpt/resources/chromium`;
       }
     }
     let scriptPath = `${prefix}/webusb-child-test.js`;
     if (typeof document == 'undefined') {
       importScripts(scriptPath);
     } else {
       let script = document.createElement('script');
--- a/testing/web-platform/tests/worklets/resources/csp-tests.js
+++ b/testing/web-platform/tests/worklets/resources/csp-tests.js
@@ -17,114 +17,170 @@ function openWindowAndExpectResult(windo
   }).then(msg_event => assert_equals(msg_event.data, expectation));
 }
 
 // Runs a series of tests related to content security policy on a worklet.
 //
 // Usage:
 // runContentSecurityPolicyTests("paint");
 function runContentSecurityPolicyTests(workletType) {
-  promise_test(t => {
-    const kWindowURL =
-        'resources/addmodule-window.html?pipe=header(' +
-        'Content-Security-Policy, script-src \'self\' \'unsafe-inline\')';
-    const kScriptURL =
-        get_host_info().HTTPS_REMOTE_ORIGIN +
-        '/worklets/resources/import-empty-worklet-script-with-cors-header.js';
-    return openWindowAndExpectResult(
-        kWindowURL, kScriptURL, workletType, 'REJECTED');
-  }, 'Importing a remote-origin worklet script should be blocked by the ' +
-     'script-src \'self\' directive.');
+  runSrcTests(workletType);
+  runMixedContentTests(workletType);
+  runUpgradeInsecureRequestsTests(workletType);
+}
 
-  promise_test(t => {
-    const kWindowURL =
+// script-src and worker-src tests.
+function runSrcTests(workletType) {
+  const kWindowConfigs = [
+    {
+      'windowURL':
         'resources/addmodule-window.html?pipe=header(' +
-        'Content-Security-Policy, script-src \'self\' \'unsafe-inline\')';
-    const kScriptURL = 'import-remote-origin-empty-worklet-script.sub.js';
-    return openWindowAndExpectResult(
-        kWindowURL, kScriptURL, workletType, 'REJECTED');
-  }, 'Importing a remote-origin script from a same-origin worklet script ' +
-     'should be blocked by the script-src \'self\' directive.');
-
-  promise_test(t => {
-    const kWindowURL =
+        'Content-Security-Policy, script-src \'self\' \'unsafe-inline\')',
+      'crossOriginExpectation': 'REJECTED',
+      'message': 'should be blocked by the script-src \'self\' directive.'
+    },
+    {
+      'windowURL':
         'resources/addmodule-window.html?pipe=header(' +
-        'Content-Security-Policy, script-src * \'unsafe-inline\')';
-    const kScriptURL =
-        get_host_info().HTTPS_REMOTE_ORIGIN +
-        '/worklets/resources/empty-worklet-script-with-cors-header.js';
-    return openWindowAndExpectResult(
-        kWindowURL, kScriptURL, workletType, 'RESOLVED');
-  }, 'Importing a remote-origin worklet script should not be blocked ' +
-     'because the script-src * directive allows it.');
-
-  promise_test(t => {
-    const kWindowURL =
+        'Content-Security-Policy, script-src ' + location.origin + ' ' +
+        get_host_info().HTTPS_REMOTE_ORIGIN + ' \'unsafe-inline\')',
+      'crossOriginExpectation': 'RESOLVED',
+      'message':
+        'should not be blocked because the script-src directive ' +
+        'specifying the origin allows it.'
+    },
+    {
+      'windowURL':
         'resources/addmodule-window.html?pipe=header(' +
-        'Content-Security-Policy, script-src * \'unsafe-inline\')';
-    // A worklet on HTTPS_REMOTE_ORIGIN will import a child script on
-    // HTTPS_REMOTE_ORIGIN.
-    const kScriptURL =
-        get_host_info().HTTPS_REMOTE_ORIGIN +
-        '/worklets/resources/import-empty-worklet-script-with-cors-header.js';
-    return openWindowAndExpectResult(
-        kWindowURL, kScriptURL, workletType, 'RESOLVED');
-  }, 'Importing a remote-origin script from a remote-origin worklet script '+
-     'should not be blocked because the script-src * directive allows it.');
-
-  promise_test(t => {
-    const kWindowURL =
+        'Content-Security-Policy, script-src * \'unsafe-inline\')',
+      'crossOriginExpectation': 'RESOLVED',
+      'message':
+        'should not be blocked because the script-src * directive allows it.'
+    },
+    {
+      'windowURL':
         'resources/addmodule-window.html?pipe=header(' +
-        'Content-Security-Policy, worker-src \'self\' \'unsafe-inline\')';
-    const kScriptURL =
-        get_host_info().HTTPS_REMOTE_ORIGIN +
-        '/worklets/resources/empty-worklet-script-with-cors-header.js';
-    return openWindowAndExpectResult(
-        kWindowURL, kScriptURL, workletType, 'RESOLVED');
-  }, 'Importing a remote-origin worklet script should not be blocked by ' +
-     'the worker-src directive because worklets obey the script-src ' +
-     'directive.');
+        'Content-Security-Policy, worker-src \'self\' \'unsafe-inline\')',
+      'crossOriginExpectation': 'RESOLVED',
+      'message':
+        'should not be blocked by the worker-src directive ' +
+        'because worklets obey the script-src directive.'
+    }
+  ];
+  for (const windowConfig of kWindowConfigs) {
+    promise_test(t => {
+        const kScriptURL =
+          get_host_info().HTTPS_REMOTE_ORIGIN +
+          '/worklets/resources/empty-worklet-script-with-cors-header.js';
+        return openWindowAndExpectResult(
+          windowConfig.windowURL, kScriptURL, workletType,
+          windowConfig.crossOriginExpectation);
+      },
+      'A remote-origin worklet ' + windowConfig.message);
+
+    promise_test(t => {
+        const kScriptURL = 'import-remote-origin-empty-worklet-script.sub.js';
+        return openWindowAndExpectResult(
+          windowConfig.windowURL, kScriptURL, workletType,
+          windowConfig.crossOriginExpectation);
+      },
+      'A same-origin worklet importing a remote-origin script ' +
+      windowConfig.message);
 
-  promise_test(t => {
-    const kWindowURL = 'resources/addmodule-window.html';
-    const kScriptURL =
-        get_host_info().HTTP_ORIGIN +
-        '/worklets/resources/empty-worklet-script.js';
-    return openWindowAndExpectResult(
-        kWindowURL, kScriptURL, workletType, 'REJECTED');
-  }, 'Importing an insecure-origin worklet script should be blocked because ' +
-     'of mixed contents.');
+    promise_test(t => {
+        // A worklet on HTTPS_REMOTE_ORIGIN will import a child script on
+        // HTTPS_REMOTE_ORIGIN.
+        const kScriptURL =
+          get_host_info().HTTPS_REMOTE_ORIGIN +
+          '/worklets/resources/import-empty-worklet-script-with-cors-header.js';
+        return openWindowAndExpectResult(
+          windowConfig.windowURL, kScriptURL, workletType,
+          windowConfig.crossOriginExpectation);
+      },
+      'A remote-origin worklet importing a remote-origin script ' +
+      windowConfig.message);
+
+    promise_test(t => {
+        const kScriptURL =
+          '/common/redirect.py?location=' + encodeURIComponent(
+              get_host_info().HTTPS_REMOTE_ORIGIN +
+              '/worklets/resources/empty-worklet-script-with-cors-header.js');
+        return openWindowAndExpectResult(
+          windowConfig.windowURL, kScriptURL, workletType,
+          windowConfig.crossOriginExpectation);
+      },
+      'A remote-origin-redirected worklet ' + windowConfig.message);
+
+    promise_test(t => {
+        const kScriptURL =
+          'import-remote-origin-redirected-empty-worklet-script.sub.js';
+        return openWindowAndExpectResult(
+          windowConfig.windowURL, kScriptURL, workletType,
+          windowConfig.crossOriginExpectation);
+      },
+      'A same-origin worklet importing a remote-origin-redirected script ' +
+      windowConfig.message);
+  }
+}
 
-  promise_test(t => {
-    const kWindowURL = 'resources/addmodule-window.html?pipe=header(' +
-                       'Content-Security-Policy, upgrade-insecure-requests)';
-    // This test relies on some unintuitive cleverness due to WPT's test setup:
-    // 'Upgrade-Insecure-Requests' does not upgrade the port number, so we use
-    // URLs in the form `http://[host]:[https-port]`. If the upgrade fails, the
-    // load will fail, as we don't serve HTTP over the secure port.
-    const kHost = get_host_info().ORIGINAL_HOST;
-    const kPort = get_host_info().HTTPS_PORT;
-    const kScriptURL =
-        `http://${kHost}:${kPort}/worklets/resources/empty-worklet-script.js`;
-    return openWindowAndExpectResult(
-        kWindowURL, kScriptURL, workletType, 'RESOLVED');
-  }, 'Importing an insecure-origin worklet script should not be blocked ' +
-     'because the upgrade-insecure-requests directive translates it as the ' +
-     'secure origin.');
+// Mixed content tests.
+function runMixedContentTests(workletType) {
+  const kInsecureURL =
+      get_host_info().HTTP_ORIGIN +
+      '/worklets/resources/empty-worklet-script-with-cors-header.js';
+  const kScriptConfigs = [
+    {URL: kInsecureURL,
+     message: 'An insecure-origin worklet'},
+    {URL: '/common/redirect.py?location=' + encodeURIComponent(kInsecureURL),
+     message: 'An insecure-origin-redirected worklet'},
+    {URL: 'import-insecure-origin-empty-worklet-script.sub.js',
+     message: 'A same-origin worklet importing an insecure-origin script'},
+    {URL: 'import-insecure-origin-redirected-empty-worklet-script.sub.js',
+     message: 'A same-origin worklet ' +
+              'importing an insecure-origin-redirected script'}
+  ];
+  for (const scriptConfig of kScriptConfigs) {
+    promise_test(t => {
+        const kWindowURL = 'resources/addmodule-window.html';
+        return openWindowAndExpectResult(
+          kWindowURL, scriptConfig.URL, workletType, 'REJECTED');
+      },
+      scriptConfig.message + ' should be blocked because of mixed contents.');
+  }
+}
 
-  promise_test(t => {
-    const kWindowURL = 'resources/addmodule-window.html';
-    const kScriptURL = 'import-insecure-origin-empty-worklet-script.sub.js';
-    return openWindowAndExpectResult(
-        kWindowURL, kScriptURL, workletType, 'REJECTED');
-  }, 'Importing an insecure-origin script from a secure-origin worklet ' +
-     'script should be blocked because of mixed contents.');
+// upgrade-insecure-requests tests.
+function runUpgradeInsecureRequestsTests(workletType) {
+  // |kToBeUpgradedURL| is expected to upgraded/loaded successfully with
+  // upgrade-insecure-requests is specified.
+  // This relies on some unintuitive cleverness due to WPT's test setup:
+  // 'Upgrade-Insecure-Requests' does not upgrade the port number, so we use
+  // URLs in the form `http://[host]:[https-port]`. If the upgrade fails, the
+  // load will fail, as we don't serve HTTP over the secure port.
+  const kHost = get_host_info().ORIGINAL_HOST;
+  const kPort = get_host_info().HTTPS_PORT;
+  const kToBeUpgradedURL =
+      `http://${kHost}:${kPort}/worklets/resources/empty-worklet-script-with-cors-header.js`;
 
-  promise_test(t => {
-    const kWindowURL = 'resources/addmodule-window.html?pipe=header(' +
-                       'Content-Security-Policy, upgrade-insecure-requests)';
-    const kScriptURL = 'import-insecure-origin-empty-worklet-script.sub.js';
-    return openWindowAndExpectResult(
-        kWindowURL, kScriptURL, workletType, 'RESOLVED');
-  }, 'Importing an insecure-origin script from a secure-origin worklet ' +
-     'script should not be blocked because the upgrade-insecure-requests ' +
-     'directive translates it as the secure origin.');
+  const kScriptConfigs = [
+    {URL: kToBeUpgradedURL,
+     message: 'An insecure-origin worklet'},
+    {URL: '/common/redirect.py?location=' +
+          encodeURIComponent(kToBeUpgradedURL),
+     message: 'An insecure-origin-redirected worklet'},
+    {URL: 'import-insecure-origin-empty-worklet-script.sub.js',
+     message: 'A same-origin worklet importing an insecure-origin script'},
+    {URL: 'import-insecure-origin-redirected-empty-worklet-script.sub.js',
+     message: 'A same-origin worklet ' +
+              'importing an insecure-origin-redirected script'}
+  ];
+  for (const scriptConfig of kScriptConfigs) {
+    promise_test(t => {
+        const kWindowURL =
+          'resources/addmodule-window.html?pipe=header(' +
+          'Content-Security-Policy, upgrade-insecure-requests)';
+        return openWindowAndExpectResult(
+          kWindowURL, scriptConfig.URL, workletType, 'RESOLVED');
+      },
+      scriptConfig.message +
+      ' should not be blocked because of upgrade-insecure-requests.');
+  }
 }
--- a/testing/web-platform/tests/worklets/resources/import-insecure-origin-empty-worklet-script.sub.js
+++ b/testing/web-platform/tests/worklets/resources/import-insecure-origin-empty-worklet-script.sub.js
@@ -1,5 +1,5 @@
 // Some tests rely on some unintuitive cleverness due to WPT's test setup:
 // 'Upgrade-Insecure-Requests' does not upgrade the port number, so we use URLs
 // in the form `http://[host]:[https-port]`. If the upgrade fails, the load will
 // fail, as we don't serve HTTP over the secure port.
-import 'http://{{host}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script.js';
+import 'http://{{host}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script-with-cors-header.js';
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/worklets/resources/import-insecure-origin-redirected-empty-worklet-script.sub.js
@@ -0,0 +1,5 @@
+// Some tests rely on some unintuitive cleverness due to WPT's test setup:
+// 'Upgrade-Insecure-Requests' does not upgrade the port number, so we use URLs
+// in the form `http://[host]:[https-port]`. If the upgrade fails, the load will
+// fail, as we don't serve HTTP over the secure port.
+import '/common/redirect.py?location=http://{{host}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script-with-cors-header.js';
--- a/testing/web-platform/tests/worklets/resources/import-remote-origin-empty-worklet-script.sub.js
+++ b/testing/web-platform/tests/worklets/resources/import-remote-origin-empty-worklet-script.sub.js
@@ -1,1 +1,1 @@
-import 'https://{{domains[www1]}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script.js';
+import 'https://{{domains[www1]}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script-with-cors-header.js';
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/worklets/resources/import-remote-origin-redirected-empty-worklet-script.sub.js
@@ -0,0 +1,1 @@
+import '/common/redirect.py?location=https://{{domains[www1]}}:{{ports[https][0]}}/worklets/resources/empty-worklet-script-with-cors-header.js';
--- a/testing/web-platform/tests/worklets/resources/import-tests.js
+++ b/testing/web-platform/tests/worklets/resources/import-tests.js
@@ -109,16 +109,39 @@ function runImportTests(worklet_type) {
         // should be rejected because of disallowed cross origin access.
         const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN +
                            '/worklets/resources/empty-worklet-script.js';
         return promise_rejects(t, new DOMException('', 'AbortError'),
                                worklet.addModule(kScriptURL));
     }, 'Importing a cross origin resource without the ' +
        'Access-Control-Allow-Origin header should reject the given promise');
 
+    promise_test(() => {
+        const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN +
+                           '/worklets/resources/empty-worklet-script.js' +
+                           '?pipe=header(Access-Control-Allow-Origin, ' +
+                           location.origin + ')';
+        return worklet.addModule('/common/redirect.py?location=' +
+                                 encodeURIComponent(kScriptURL))
+          .then(undefined_arg => {
+              assert_equals(undefined_arg, undefined);
+          });
+    }, 'Importing a cross-origin-redirected resource with the ' +
+       'Access-Control-Allow-Origin header should resolve the given promise');
+
+    promise_test(t => {
+        const kScriptURL = get_host_info().HTTPS_REMOTE_ORIGIN +
+                           '/worklets/resources/empty-worklet-script.js';
+        return promise_rejects(t, new DOMException('', 'AbortError'),
+                               worklet.addModule(
+                                   '/common/redirect.py?location=' +
+                                   encodeURIComponent(kScriptURL)));
+    }, 'Importing a cross-origin-redirected resource without the ' +
+       'Access-Control-Allow-Origin header should reject the given promise');
+
     promise_test(t => {
         const kScriptURL = 'resources/syntax-error-worklet-script.js';
         return promise_rejects(t, new DOMException('', 'AbortError'),
                                worklet.addModule(kScriptURL));
     }, 'Importing a script that has a syntax error should reject the given ' +
        'promise.');
 
     promise_test(t => {