Merge mozilla-inbound to mozilla-central. a=merge
authorDaniel Varga <dvarga@mozilla.com>
Fri, 15 Feb 2019 03:41:17 +0200
changeset 459372 426ca85d23038f08ebe29ce16db8fd484062f1f9
parent 459225 b29c87add05f735b250612ca2444103652750091 (current diff)
parent 459371 1a199fcf0ef6e0c7b106e1820e8fb12c08e2dbab (diff)
child 459373 591ffe90d0edbd8190427f09a14e39a92a327aee
child 459488 1ba05f89732864e4cced12780eb9c8bcc8e9d6fd
child 459573 7fdcdef438710bd7f93ed000c397a7f6646ca975
push id78235
push userdvarga@mozilla.com
push dateFri, 15 Feb 2019 01:46:34 +0000
treeherderautoland@591ffe90d0ed [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone67.0a1
first release with
nightly linux32
426ca85d2303 / 67.0a1 / 20190215014208 / files
nightly linux64
426ca85d2303 / 67.0a1 / 20190215014208 / files
nightly mac
426ca85d2303 / 67.0a1 / 20190215014208 / files
nightly win32
426ca85d2303 / 67.0a1 / 20190215014208 / files
nightly win64
426ca85d2303 / 67.0a1 / 20190215014208 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-inbound to mozilla-central. a=merge
build/moz.configure/rust.configure
taskcluster/docker/debian-base/cloud-mirror-workaround.sh
taskcluster/docker/debian-base/setup_packages.sh
testing/web-platform/meta/js/builtins/__dir__.ini
testing/web-platform/meta/performance-timeline/case-sensitivity.any.html.ini
testing/web-platform/meta/wasm/serialization/broadcastchannel-success-and-failure.html.ini
testing/web-platform/meta/wasm/serialization/broadcastchannel-success.html.ini
testing/web-platform/meta/wasm/serialization/window-messagechannel-success.html.ini
testing/web-platform/meta/wasm/serialization/window-serviceworker-failure.https.html.ini
testing/web-platform/meta/wasm/serialization/window-sharedworker-failure.html.ini
testing/web-platform/tests/infrastructure/metadata/infrastructure/testdriver/actions/elementTiming.html.ini
testing/web-platform/tests/portals/resources/portal-activate-event-window.html
testing/web-platform/tests/wasm/serialization/broadcastchannel-success-and-failure.html
testing/web-platform/tests/wasm/serialization/broadcastchannel-success.html
testing/web-platform/tests/wasm/serialization/identity-not-preserved.html
testing/web-platform/tests/wasm/serialization/incrementer.wasm
testing/web-platform/tests/wasm/serialization/nested-worker-success.any.js
testing/web-platform/tests/wasm/serialization/no-transferring.html
testing/web-platform/tests/wasm/serialization/resources/blank.html
testing/web-platform/tests/wasm/serialization/resources/broadcastchannel-iframe.html
testing/web-platform/tests/wasm/serialization/resources/broadcastchannel-sharedworker.js
testing/web-platform/tests/wasm/serialization/resources/broadcastchannel-worker.js
testing/web-platform/tests/wasm/serialization/resources/create-empty-wasm-module.js
testing/web-platform/tests/wasm/serialization/resources/echo-iframe.html
testing/web-platform/tests/wasm/serialization/resources/echo-worker.js
testing/web-platform/tests/wasm/serialization/resources/incrementer-iframe-domain.sub.html
testing/web-platform/tests/wasm/serialization/resources/incrementer-iframe.html
testing/web-platform/tests/wasm/serialization/resources/incrementer-popup.html
testing/web-platform/tests/wasm/serialization/resources/incrementer-worker-with-channel.js
testing/web-platform/tests/wasm/serialization/resources/incrementer-worker.js
testing/web-platform/tests/wasm/serialization/resources/incrementer.wasm
testing/web-platform/tests/wasm/serialization/resources/nested-iframe-1.html
testing/web-platform/tests/wasm/serialization/resources/nested-iframe-2.html
testing/web-platform/tests/wasm/serialization/resources/nested-iframe-3.html
testing/web-platform/tests/wasm/serialization/resources/nested-iframe-4-incrementer.html
testing/web-platform/tests/wasm/serialization/resources/serviceworker-failure.js
testing/web-platform/tests/wasm/serialization/resources/sharedworker-failure.js
testing/web-platform/tests/wasm/serialization/resources/test-incrementer.js
testing/web-platform/tests/wasm/serialization/serialization-via-history.html
testing/web-platform/tests/wasm/serialization/serialization-via-idb.any.js
testing/web-platform/tests/wasm/serialization/serialization-via-notifications-api.any.js
testing/web-platform/tests/wasm/serialization/window-domain-success.sub.html
testing/web-platform/tests/wasm/serialization/window-messagechannel-success.html
testing/web-platform/tests/wasm/serialization/window-serviceworker-failure.https.html
testing/web-platform/tests/wasm/serialization/window-sharedworker-failure.html
testing/web-platform/tests/wasm/serialization/window-similar-but-cross-origin-success.sub.html
testing/web-platform/tests/wasm/serialization/window-simple-success.html
--- a/browser/components/aboutconfig/content/aboutconfig.css
+++ b/browser/components/aboutconfig/content/aboutconfig.css
@@ -52,17 +52,21 @@ body.config-warning {
   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;
   border-spacing: 0;
 }
 
-#prefs > tr:nth-child(odd) {
+#prefs > tr.hidden {
+  display: none;
+}
+
+#prefs > tr.odd {
   background-color: var(--in-content-box-background-odd);
 }
 
 #prefs > tr:hover {
   background-color: var(--in-content-item-hover);
 }
 
 #prefs > tr.has-user-value {
--- a/browser/components/aboutconfig/content/aboutconfig.js
+++ b/browser/components/aboutconfig/content/aboutconfig.js
@@ -27,52 +27,62 @@ let gFilterPrefsTask = new DeferredTask(
  * Maps the name of each preference in the back-end to its PrefRow object,
  * separating the preferences that actually exist. This is as an optimization to
  * avoid querying the preferences service each time the list is filtered.
  */
 let gExistingPrefs = new Map();
 let gDeletedPrefs = new Map();
 
 /**
- * Maps each row element currently in the table to its PrefRow object.
+ * Also cache several values to improve the performance of common use cases.
  */
-let gElementToPrefMap = new WeakMap();
+let gSortedExistingPrefs = null;
+let gSearchInput = null;
+let gPrefsTable = null;
 
 /**
  * Reference to the PrefRow currently being edited, if any.
  */
 let gPrefInEdit = null;
 
 /**
  * Lowercase substring that should be contained in the preference name.
  */
 let gFilterString = null;
 
 class PrefRow {
   constructor(name) {
     this.name = name;
     this.value = true;
+    this.hidden = false;
+    this.odd = false;
     this.editing = false;
     this.refreshValue();
   }
 
   refreshValue() {
     let prefType = Services.prefs.getPrefType(this.name);
 
     // If this preference has been deleted, we keep its last known value.
     if (prefType == Ci.nsIPrefBranch.PREF_INVALID) {
       this.hasDefaultValue = false;
       this.hasUserValue = false;
       this.isLocked = false;
-      gExistingPrefs.delete(this.name);
+      if (gExistingPrefs.has(this.name)) {
+        gExistingPrefs.delete(this.name);
+        gSortedExistingPrefs = null;
+      }
       gDeletedPrefs.set(this.name, this);
       return;
     }
 
-    gExistingPrefs.set(this.name, this);
+    if (!gExistingPrefs.has(this.name)) {
+      gExistingPrefs.set(this.name, this);
+      gSortedExistingPrefs = null;
+    }
     gDeletedPrefs.delete(this.name);
 
     try {
       this.value = gDefaultBranch[GETTERS_BY_PREF_TYPE[prefType]](this.name);
       this.hasDefaultValue = true;
     } catch (ex) {
       this.hasDefaultValue = false;
     }
@@ -112,17 +122,17 @@ class PrefRow {
    * constructing and initializing it the first time this method is called.
    */
   getElement() {
     if (this._element) {
       return this._element;
     }
 
     this._element = document.createElement("tr");
-    gElementToPrefMap.set(this._element, this);
+    this._element._pref = this;
 
     let nameCell = document.createElement("th");
     this._element.append(
       nameCell,
       this.valueCell = document.createElement("td"),
       this.editCell = document.createElement("td"),
       this.resetCell = document.createElement("td")
     );
@@ -149,19 +159,16 @@ class PrefRow {
   }
 
   refreshElement() {
     if (!this._element) {
       // No need to update if this preference was never added to the table.
       return;
     }
 
-    this._element.classList.toggle("has-user-value", !!this.hasUserValue);
-    this._element.classList.toggle("locked", !!this.isLocked);
-    this._element.classList.toggle("deleted", !this.exists);
     if (this.exists && !this.editing) {
       // We need to place the text inside a "span" element to ensure that the
       // text copied to the clipboard includes all whitespace.
       let span = document.createElement("span");
       span.textContent = this.value;
       // We additionally need to wrap this with another "span" element to convey
       // the state to screen readers without affecting the visual presentation.
       span.setAttribute("aria-hidden", "true");
@@ -252,16 +259,39 @@ class PrefRow {
         document.l10n.setAttributes(this.resetButton,
                                     "about-config-pref-reset");
         this.resetButton.className = "button-reset";
       }
     } else if (this.resetButton) {
       this.resetButton.remove();
       delete this.resetButton;
     }
+
+    this.refreshClass();
+  }
+
+  refreshClass() {
+    if (!this._element) {
+      // No need to update if this preference was never added to the table.
+      return;
+    }
+
+    let className;
+    if (this.hidden) {
+      className = "hidden";
+    } else {
+      className = (this.hasUserValue ? "has-user-value " : "") +
+                  (this.isLocked ? "locked " : "") +
+                  (this.exists ? "" : "deleted ") +
+                  (this.odd ? "odd " : "");
+    }
+
+    if (this._lastClassName !== className) {
+      this._element.className = this._lastClassName = className;
+    }
   }
 
   edit() {
     if (gPrefInEdit) {
       gPrefInEdit.endEdit();
     }
     gPrefInEdit = this;
     this.editing = true;
@@ -330,18 +360,18 @@ function onWarningButtonClick() {
 function loadPrefs() {
   document.body.className = "config-background";
   [...document.styleSheets].find(s => s.title == "infop").disabled = true;
 
   let { content } = document.getElementById("main");
   document.body.textContent = "";
   document.body.appendChild(content);
 
-  let search = document.getElementById("about-config-search");
-  let prefs = document.getElementById("prefs");
+  let search = gSearchInput = document.getElementById("about-config-search");
+  let prefs = gPrefsTable = document.getElementById("prefs");
   search.focus();
 
   for (let name of Services.prefs.getChildList("")) {
     new PrefRow(name);
   }
 
   search.addEventListener("keypress", event => {
     switch (event.key) {
@@ -359,17 +389,17 @@ function loadPrefs() {
     gFilterPrefsTask.disarm();
     gFilterPrefsTask.arm();
   });
 
   prefs.addEventListener("click", event => {
     if (event.target.localName != "button") {
       return;
     }
-    let pref = gElementToPrefMap.get(event.target.closest("tr"));
+    let pref = event.target.closest("tr")._pref;
     let button = event.target.closest("button");
     if (button.classList.contains("button-add")) {
       Preferences.set(pref.name, pref.value);
       if (pref.type != "Boolean") {
         pref.edit();
       }
     } else if (button.classList.contains("button-toggle")) {
       Services.prefs.setBoolPref(pref.name, !pref.value);
@@ -387,34 +417,89 @@ function loadPrefs() {
 }
 
 function filterPrefs() {
   if (gPrefInEdit) {
     gPrefInEdit.endEdit();
   }
   gDeletedPrefs.clear();
 
-  let searchName = document.getElementById("about-config-search").value.trim();
+  let searchName = gSearchInput.value.trim();
   gFilterString = searchName.toLowerCase();
-  let prefArray = [...gExistingPrefs.values()];
-  if (gFilterString) {
-    prefArray = prefArray.filter(pref => pref.matchesFilter);
-  }
-  prefArray.sort((a, b) => a.name > b.name);
-  if (searchName && !gExistingPrefs.has(searchName)) {
-    prefArray.push(new PrefRow(searchName));
+
+  if (!gSortedExistingPrefs) {
+    gSortedExistingPrefs = [...gExistingPrefs.values()];
+    gSortedExistingPrefs.sort((a, b) => a.name > b.name);
   }
 
-  let prefsElement = document.getElementById("prefs");
-  prefsElement.textContent = "";
-  let fragment = document.createDocumentFragment();
-  for (let pref of prefArray) {
-    fragment.appendChild(pref.getElement());
+  // The slowest operations tend to be the addition and removal of DOM nodes, so
+  // this algorithm tries to reduce removals by hiding nodes instead. This
+  // happens frequently when the set narrows while typing preference names. We
+  // iterate the nodes already in the table in parallel to those we want to
+  // show, because the two lists are sorted and they will often match already.
+  let fragment = null;
+  let indexInArray = 0;
+  let elementInTable = gPrefsTable.firstElementChild;
+  let odd = false;
+  while (indexInArray < gSortedExistingPrefs.length || elementInTable) {
+    // For efficiency, filter the array while we are iterating.
+    let prefInArray = gSortedExistingPrefs[indexInArray];
+    if (prefInArray) {
+      if (!prefInArray.matchesFilter) {
+        indexInArray++;
+        continue;
+      }
+      prefInArray.hidden = false;
+      prefInArray.odd = odd;
+    }
+
+    let prefInTable = elementInTable && elementInTable._pref;
+    if (!prefInTable) {
+      // We're at the end of the table, we just have to insert all the matching
+      // elements that remain in the array. We can use a fragment to make the
+      // insertions faster, which is useful during the initial filtering.
+      if (!fragment) {
+        fragment = document.createDocumentFragment();
+      }
+      fragment.appendChild(prefInArray.getElement());
+    } else if (prefInTable == prefInArray) {
+      // We got two matching elements, we just need to update the visibility.
+      elementInTable = elementInTable.nextElementSibling;
+    } else if (prefInArray && prefInArray.name < prefInTable.name) {
+      // The iteration in the table is ahead of the iteration in the array.
+      // Insert or move the array element, and advance the array index.
+      gPrefsTable.insertBefore(prefInArray.getElement(), elementInTable);
+    } else {
+      // The iteration in the array is ahead of the iteration in the table.
+      // Hide the element in the table, and advance to the next element.
+      let nextElementInTable = elementInTable.nextElementSibling;
+      if (!prefInTable.exists) {
+        // Remove rows for deleted preferences, or temporary addition rows.
+        elementInTable.remove();
+      } else {
+        // Keep the element for the next filtering if the preference exists.
+        prefInTable.hidden = true;
+        prefInTable.refreshClass();
+      }
+      elementInTable = nextElementInTable;
+      continue;
+    }
+
+    prefInArray.refreshClass();
+    odd = !odd;
+    indexInArray++;
   }
-  prefsElement.appendChild(fragment);
+
+  if (fragment) {
+    gPrefsTable.appendChild(fragment);
+  }
+
+  if (searchName && !gExistingPrefs.has(searchName)) {
+    gPrefsTable.appendChild((new PrefRow(searchName)).getElement());
+  }
 
   // We only start observing preference changes after the first search is done,
   // so that newly added preferences won't appear while the page is still empty.
   if (!gPrefObserverRegistered) {
     gPrefObserverRegistered = true;
     Services.prefs.addObserver("", gPrefObserver);
     window.addEventListener("unload", () => {
       Services.prefs.removeObserver("", gPrefObserver);
--- a/browser/components/aboutconfig/test/browser/browser_search.js
+++ b/browser/components/aboutconfig/test/browser/browser_search.js
@@ -62,23 +62,27 @@ add_task(async function test_search() {
 
 add_task(async function test_search_delayed() {
   await AboutConfigTest.withNewTab(async function() {
     // Prepare the table and the search field for the test.
     this.search("test.aboutconfig.a");
     Assert.equal(this.rows.length, 2);
 
     // The table is updated in a single microtask, so we don't need to wait for
-    // specific mutations, we can just continue when the children are updated.
+    // specific mutations, we can just continue when any of the children or
+    // their "hidden" attributes are updated.
     let prefsTableChanged = new Promise(resolve => {
       let observer = new MutationObserver(() => {
         observer.disconnect();
         resolve();
       });
       observer.observe(this.prefsTable, { childList: true });
+      for (let element of this.prefsTable.children) {
+        observer.observe(element, { attributes: true });
+      }
     });
 
     // Add a character and test that the table is not updated immediately.
     EventUtils.synthesizeKey("b");
     Assert.equal(this.rows.length, 2);
 
     // The table will eventually be updated after a delay.
     await prefsTableChanged;
--- a/browser/components/aboutconfig/test/browser/head.js
+++ b/browser/components/aboutconfig/test/browser/head.js
@@ -117,17 +117,17 @@ class AboutConfigTest {
   get prefsTable() {
     return this.document.getElementById("prefs");
   }
 
   /**
    * Array of AboutConfigRowTest objects, one for each row in the main table.
    */
   get rows() {
-    let elements = this.prefsTable.getElementsByTagName("tr");
+    let elements = this.prefsTable.querySelectorAll("tr:not(.hidden)");
     return Array.map(elements, element => new AboutConfigRowTest(element));
   }
 
   /**
    * Returns the AboutConfigRowTest object for the row in the main table which
    * corresponds to the given preference name, or undefined if none is present.
    */
   getRow(name) {
--- a/build/moz.configure/rust.configure
+++ b/build/moz.configure/rust.configure
@@ -49,30 +49,34 @@ def cargo_info(cargo):
             die('Could not determine cargo version from output: %s', out)
         version = m.group(1)
 
     return namespace(
         version=Version(version),
     )
 
 
-@depends(rustc_info, cargo_info)
+@depends(rustc_info, cargo_info, build_project)
 @imports(_from='textwrap', _import='dedent')
-def rust_compiler(rustc_info, cargo_info):
+def rust_compiler(rustc_info, cargo_info, build_project):
     if not rustc_info:
         die(dedent('''\
         Rust compiler not found.
         To compile rust language sources, you must have 'rustc' in your path.
         See https://www.rust-lang.org/ for more information.
 
         You can install rust by running './mach bootstrap'
         or by directly running the installer from https://rustup.rs/
         '''))
-    rustc_min_version = Version('1.32.0')
-    cargo_min_version = rustc_min_version
+    if build_project == 'tools/crashreporter':
+        rustc_min_version = Version('1.22.0')
+        cargo_min_version = Version('0.23.0')
+    else:
+        rustc_min_version = Version('1.32.0')
+        cargo_min_version = rustc_min_version
 
     version = rustc_info.version
     if version < rustc_min_version:
         die(dedent('''\
         Rust compiler {} is too old.
 
         To compile Rust language sources please install at least
         version {} of the 'rustc' toolchain and make sure it is
--- a/dom/security/nsMixedContentBlocker.cpp
+++ b/dom/security/nsMixedContentBlocker.cpp
@@ -296,29 +296,17 @@ nsMixedContentBlocker::AsyncOnChannelRed
   rv = aOldChannel->GetURI(getter_AddRefs(oldUri));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIURI> newUri;
   rv = aNewChannel->GetURI(getter_AddRefs(newUri));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get the loading Info from the old channel
-  nsCOMPtr<nsILoadInfo> loadInfo;
-  rv = aOldChannel->GetLoadInfo(getter_AddRefs(loadInfo));
-  NS_ENSURE_SUCCESS(rv, rv);
-  if (!loadInfo) {
-    // XXX: We want to have a loadInfo on all channels, but we don't yet.
-    // If an addon creates a channel, they may not set loadinfo. If that
-    // channel redirects from one page to another page, we would get caught
-    // in this code path. Hence, we have to return NS_OK. Once we have more
-    // confidence that all channels have loadinfo, we can change this to
-    // a failure. See bug 1077201.
-    return NS_OK;
-  }
-
+  nsCOMPtr<nsILoadInfo> loadInfo = aOldChannel->GetLoadInfo();
   nsCOMPtr<nsIPrincipal> requestingPrincipal = loadInfo->LoadingPrincipal();
 
   // Since we are calling shouldLoad() directly on redirects, we don't go
   // through the code in nsContentPolicyUtils::NS_CheckContentLoadPolicy().
   // Hence, we have to duplicate parts of it here.
   if (requestingPrincipal) {
     // We check to see if the loadingPrincipal is systemPrincipal and return
     // early if it is
--- a/js/src/tests/non262/TypedArray/slice-validation.js
+++ b/js/src/tests/non262/TypedArray/slice-validation.js
@@ -1,39 +1,45 @@
 /* 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/. */
 
 // Summary: Ensure typed array validation is called for TypedArray.prototype.slice.
 
-const otherGlobal = typeof newGlobal === "function" ? newGlobal({newCompartment: true}) : undefined;
+const otherGlobal = newGlobal({newCompartment: true});
 const typedArrayLengths = [0, 1, 1024];
 
+// Note: slice uses CallTypedArrayMethodIfWrapped, which results in throwing
+//       a TypeError from the wrong Realm if cross-compartment. The browser
+//       runner doesn't support the "newCompartment" option, so it can't create
+//       cross-compartment globals, which means it throws the error from the
+//       correct Realm.
+const eitherGlobalTypeError = {
+    [Symbol.hasInstance](obj) {
+        return obj instanceof TypeError || obj instanceof otherGlobal.TypeError;
+    }
+};
+
 function createTestCases(TAConstructor, constructor, constructorCrossRealm) {
     let testCases = [];
     testCases.push({
         species: constructor,
         method: TAConstructor.prototype.slice,
         error: TypeError,
     });
-    if (otherGlobal) {
-        testCases.push({
-            species: constructorCrossRealm,
-            method: TAConstructor.prototype.slice,
-            error: TypeError,
-        });
-        testCases.push({
-            species: constructor,
-            method: otherGlobal[TAConstructor.name].prototype.slice,
-            // Note: slice uses CallTypedArrayMethodIfWrapped, which results
-            //       in throwing a TypeError from the wrong Realm if
-            //       cross-compartment.
-            error: TypeError,
-        });
-    }
+    testCases.push({
+        species: constructorCrossRealm,
+        method: TAConstructor.prototype.slice,
+        error: TypeError,
+    });
+    testCases.push({
+        species: constructor,
+        method: otherGlobal[TAConstructor.name].prototype.slice,
+        error: eitherGlobalTypeError,
+    });
     return testCases;
 }
 
 // Throws TypeError when the returned value is not a typed array.
 for (const TAConstructor of anyTypedArrayConstructors) {
     let callCount = 0, expectedCallCount = 0;
     function NoTypedArrayConstructor(...args) {
         let a = [];
--- a/js/src/tests/non262/TypedArray/subarray-validation.js
+++ b/js/src/tests/non262/TypedArray/subarray-validation.js
@@ -1,39 +1,45 @@
 /* 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/. */
 
 // Summary: Ensure typed array validation is called for TypedArray.prototype.subarray.
 
-const otherGlobal = typeof newGlobal === "function" ? newGlobal({newCompartment: true}) : undefined;
+const otherGlobal = newGlobal({newCompartment: true});
 const typedArrayLengths = [0, 1, 1024];
 
+// Note: subarray uses CallTypedArrayMethodIfWrapped, which results in throwing
+//       a TypeError from the wrong Realm if cross-compartment. The browser
+//       runner doesn't support the "newCompartment" option, so it can't create
+//       cross-compartment globals, which means it throws the error from the
+//       correct Realm.
+const eitherGlobalTypeError = {
+    [Symbol.hasInstance](obj) {
+        return obj instanceof TypeError || obj instanceof otherGlobal.TypeError;
+    }
+};
+
 function createTestCases(TAConstructor, constructor, constructorCrossRealm) {
     let testCases = [];
     testCases.push({
         species: constructor,
         method: TAConstructor.prototype.subarray,
         error: TypeError,
     });
-    if (otherGlobal) {
-        testCases.push({
-            species: constructorCrossRealm,
-            method: TAConstructor.prototype.subarray,
-            error: TypeError,
-        });
-        testCases.push({
-            species: constructor,
-            method: otherGlobal[TAConstructor.name].prototype.subarray,
-            // Note: subarray uses CallTypedArrayMethodIfWrapped, which results
-            //       in throwing a TypeError from the wrong Realm if
-            //       cross-compartment.
-            error: TypeError,
-        });
-    }
+    testCases.push({
+        species: constructorCrossRealm,
+        method: TAConstructor.prototype.subarray,
+        error: TypeError,
+    });
+    testCases.push({
+        species: constructor,
+        method: otherGlobal[TAConstructor.name].prototype.subarray,
+        error: eitherGlobalTypeError,
+    });
     return testCases;
 }
 
 // Throws TypeError when the returned value is not a typed array.
 for (const TAConstructor of anyTypedArrayConstructors) {
     let callCount = 0, expectedCallCount = 0;
     function NoTypedArrayConstructor(...args) {
         let a = [];
--- a/js/src/tests/non262/regress/regress-698028-3.js
+++ b/js/src/tests/non262/regress/regress-698028-3.js
@@ -1,15 +1,15 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs Debugger
+
 // Any copyright is dedicated to the Public Domain.
 // http://creativecommons.org/licenses/publicdomain/
 
-if (typeof Debugger === 'function') {
-    var g = newGlobal({newCompartment: true});
-    var dbg = new Debugger(g);
-    dbg.onDebuggerStatement = function (frame) { frame.eval(''); };
-    var s = '{ let ';
-    for (var i = 0; i < 128; i++)
-        s += 'x' + i + ', ';
-    s += 'X = 0; debugger; }';
-    g.eval(s);
-}
+var g = newGlobal({newCompartment: true});
+var dbg = new Debugger(g);
+dbg.onDebuggerStatement = function (frame) { frame.eval(''); };
+var s = '{ let ';
+for (var i = 0; i < 128; i++)
+    s += 'x' + i + ', ';
+s += 'X = 0; debugger; }';
+g.eval(s);
 
 reportCompare(0, 0, 'ok');
--- a/js/src/wasm/WasmBaselineCompile.cpp
+++ b/js/src/wasm/WasmBaselineCompile.cpp
@@ -133,16 +133,17 @@
 #  include "jit/mips-shared/Assembler-mips-shared.h"
 #  include "jit/mips32/Assembler-mips32.h"
 #endif
 #if defined(JS_CODEGEN_MIPS64)
 #  include "jit/mips-shared/Assembler-mips-shared.h"
 #  include "jit/mips64/Assembler-mips64.h"
 #endif
 
+#include "wasm/WasmGC.h"
 #include "wasm/WasmGenerator.h"
 #include "wasm/WasmInstance.h"
 #include "wasm/WasmOpIter.h"
 #include "wasm/WasmSignalHandlers.h"
 #include "wasm/WasmStubs.h"
 #include "wasm/WasmValidate.h"
 
 #include "jit/MacroAssembler-inl.h"
@@ -957,18 +958,16 @@ using ScratchI8 = ScratchI32;
 //  - the Dynamic area, comprising the temporary storage the compiler uses for
 //    register spilling, allocated below the Local area;
 //  - the Arguments area, comprising memory allocated for outgoing calls,
 //    allocated below the Dynamic area.
 //
 //                 +============================+
 //                 |    Incoming arg            |
 //                 |    ...                     |
-//                 +----------------------------+
-//                 |    unspecified             |
 // --------------  +============================+
 //                 |    Frame (fixed size)      |
 // --------------  +============================+ <-------------------- FP
 //          ^      |    DebugFrame (optional)   |    ^                ^^
 //          |      +----------------------------+    |                ||
 //    localSize    |    Local (static size)     |    |                ||
 //          |      |    ...                     |    |        framePushed
 //          v      |    (padding)               |    |                ||
@@ -2101,28 +2100,34 @@ struct StackMapGenerator {
   // This holds masm.framePushed at entry to the function's body.  It is a
   // Maybe because createStackMap needs to know whether or not we're still
   // in the prologue.  It makes a Nothing-to-Some transition just once per
   // function.
   Maybe<uint32_t> framePushedAtEntryToBody_;
 
   // --- These can change at any point ---
 
-  // This holds masm.framePushed immediately before we move the stack
-  // pointer down so as to reserve space, in a function call, for arguments
-  // passed in memory.  To be more precise: this holds the value
-  // masm.framePushed would have had after moving the stack pointer over any
-  // alignment padding pushed before the arguments proper, but before the
-  // downward movement of the stack pointer that allocates space for the
-  // arguments proper.
+  // This holds masm.framePushed at it would be be for a function call
+  // instruction, but excluding the stack area used to pass arguments in
+  // memory.  That is, for an upcoming function call, this will hold
+  //
+  //   masm.framePushed() at the call instruction -
+  //      StackArgAreaSizeUnaligned(argumentTypes)
+  //
+  // This value denotes the lowest-addressed stack word covered by the current
+  // function's stackmap.  Words below this point form the highest-addressed
+  // area of the callee's stackmap.  Note that all alignment padding above the
+  // arguments-in-memory themselves belongs to the caller's stack map, which
+  // is why this is defined in terms of StackArgAreaSizeUnaligned() rather than
+  // StackArgAreaSizeAligned().
   //
   // When not inside a function call setup/teardown sequence, it is Nothing.
   // It can make Nothing-to/from-Some transitions arbitrarily as we progress
   // through the function body.
-  Maybe<uint32_t> framePushedBeforePushingCallArgs_;
+  Maybe<uint32_t> framePushedExcludingOutboundCallArgs_;
 
   // The number of memory-resident, ref-typed entries on the containing
   // BaseCompiler::stk_.
   size_t memRefsOnStk_;
 
   // This is a copy of mst_ that is used only within individual calls to
   // createStackMap.  It is here only to avoid possible heap allocation costs
   // resulting from making it local to createStackMap().
@@ -2224,34 +2229,41 @@ struct StackMapGenerator {
     // At this point, augmentedMst only contains entries covering the
     // incoming argument area (if any) and for the area allocated by this
     // function's prologue.  We now need to calculate how far the machine's
     // stack pointer is below where it was at the start of the body.  But we
     // must take care not to include any words pushed as arguments to an
     // upcoming function call, since those words "belong" to the stackmap of
     // the callee, not to the stackmap of this function.  Note however that
     // any alignment padding pushed prior to pushing the args *does* belong to
-    // this function.  That padding is taken into account at the point where
-    // framePushedBeforePushingCallArgs_ is set.
+    // this function.
+    //
+    // That padding is taken into account at the point where
+    // framePushedExcludingOutboundCallArgs_ is set, viz, in startCallArgs(),
+    // and comprises two components:
+    //
+    // * call->frameAlignAdjustment
+    // * the padding applied to the stack arg area itself.  That is:
+    //   StackArgAreaSize(argTys) - StackArgAreaSizeUnpadded(argTys)
     Maybe<uint32_t> framePushedExcludingArgs;
     if (framePushedAtEntryToBody_.isNothing()) {
       // Still in the prologue.  framePushedExcludingArgs remains Nothing.
-      MOZ_ASSERT(framePushedBeforePushingCallArgs_.isNothing());
+      MOZ_ASSERT(framePushedExcludingOutboundCallArgs_.isNothing());
     } else {
       // In the body.
       MOZ_ASSERT(masm_.framePushed() >= framePushedAtEntryToBody_.value());
-      if (framePushedBeforePushingCallArgs_.isSome()) {
+      if (framePushedExcludingOutboundCallArgs_.isSome()) {
         // In the body, and we've potentially pushed some args onto the stack.
         // We must ignore them when sizing the stackmap.
         MOZ_ASSERT(masm_.framePushed() >=
-                   framePushedBeforePushingCallArgs_.value());
-        MOZ_ASSERT(framePushedBeforePushingCallArgs_.value() >=
+                   framePushedExcludingOutboundCallArgs_.value());
+        MOZ_ASSERT(framePushedExcludingOutboundCallArgs_.value() >=
                    framePushedAtEntryToBody_.value());
         framePushedExcludingArgs =
-            Some(framePushedBeforePushingCallArgs_.value());
+            Some(framePushedExcludingOutboundCallArgs_.value());
       } else {
         // In the body, but not with call args on the stack.  The stackmap
         // must be sized so as to extend all the way "down" to
         // masm_.framePushed().
         framePushedExcludingArgs = Some(masm_.framePushed());
       }
     }
 
@@ -4050,34 +4062,34 @@ class BaseCompiler final : public BaseCo
             (int)func_.index);
 
     // Make a start on the stack map for this function.  Inspect the args so
     // as to determine which of them are both in-memory and pointer-typed, and
     // add entries to mst_ as appropriate.
 
     const ValTypeVector& argTys = env_.funcTypes[func_.index]->args();
 
-    size_t nStackArgBytes = stackArgAreaSize(argTys);
-    MOZ_ASSERT(nStackArgBytes % sizeof(void*) == 0);
-    smgen_.numStackArgWords_ = nStackArgBytes / sizeof(void*);
+    size_t nInboundStackArgBytes = StackArgAreaSizeUnaligned(argTys);
+    MOZ_ASSERT(nInboundStackArgBytes % sizeof(void*) == 0);
+    smgen_.numStackArgWords_ = nInboundStackArgBytes / sizeof(void*);
 
     MOZ_ASSERT(smgen_.mst_.length() == 0);
     if (!smgen_.mst_.pushNonGCPointers(smgen_.numStackArgWords_)) {
       return false;
     }
 
     for (ABIArgIter<const ValTypeVector> i(argTys); !i.done(); i++) {
       ABIArg argLoc = *i;
       const ValType& ty = argTys[i.index()];
       MOZ_ASSERT(ToMIRType(ty) != MIRType::Pointer);
       if (argLoc.kind() != ABIArg::Stack || !ty.isReference()) {
         continue;
       }
       uint32_t offset = argLoc.offsetFromArgBase();
-      MOZ_ASSERT(offset < nStackArgBytes);
+      MOZ_ASSERT(offset < nInboundStackArgBytes);
       MOZ_ASSERT(offset % sizeof(void*) == 0);
       smgen_.mst_.setGCPointer(offset / sizeof(void*));
     }
 
     GenerateFunctionPrologue(
         masm, env_.funcTypes[func_.index]->id,
         env_.mode() == CompileMode::Tier1 ? Some(func_.index) : Nothing(),
         &offsets_);
@@ -4378,59 +4390,52 @@ class BaseCompiler final : public BaseCo
     call.frameAlignAdjustment = ComputeByteAlignment(
         masm.framePushed() + sizeof(Frame), JitStackAlignment);
   }
 
   void endCall(FunctionCall& call, size_t stackSpace) {
     size_t adjustment = call.stackArgAreaSize + call.frameAlignAdjustment;
     fr.freeArgAreaAndPopBytes(adjustment, stackSpace);
 
-    MOZ_ASSERT(smgen_.framePushedBeforePushingCallArgs_.isSome());
-    smgen_.framePushedBeforePushingCallArgs_.reset();
+    MOZ_ASSERT(smgen_.framePushedExcludingOutboundCallArgs_.isSome());
+    smgen_.framePushedExcludingOutboundCallArgs_.reset();
 
     if (call.isInterModule) {
       masm.loadWasmTlsRegFromFrame();
       masm.loadWasmPinnedRegsFromTls();
       masm.switchToWasmTlsRealm(ABINonArgReturnReg0, ABINonArgReturnReg1);
     } else if (call.usesSystemAbi) {
       // On x86 there are no pinned registers, so don't waste time
       // reloading the Tls.
 #ifndef JS_CODEGEN_X86
       masm.loadWasmTlsRegFromFrame();
       masm.loadWasmPinnedRegsFromTls();
 #endif
     }
   }
 
-  // TODO / OPTIMIZE (Bug 1316821): This is expensive; let's roll the iterator
-  // walking into the walking done for passArg.  See comments in passArg.
-
-  // Note, stackArgAreaSize() must process all the arguments to get the
-  // alignment right; the signature must therefore be the complete call
-  // signature.
-
-  template <class T>
-  size_t stackArgAreaSize(const T& args) {
-    ABIArgIter<const T> i(args);
-    while (!i.done()) {
-      i++;
-    }
-    return AlignBytes(i.stackBytesConsumedSoFar(), 16u);
-  }
-
-  void startCallArgs(size_t stackArgAreaSize, FunctionCall* call) {
+  void startCallArgs(size_t stackArgAreaSizeUnaligned, FunctionCall* call) {
+    size_t stackArgAreaSizeAligned
+        = AlignStackArgAreaSize(stackArgAreaSizeUnaligned);
+    MOZ_ASSERT(stackArgAreaSizeUnaligned <= stackArgAreaSizeAligned);
+
     // Record the masm.framePushed() value at this point, before we push args
     // for the call, but including the alignment space placed above the args.
     // This defines the lower limit of the stackmap that will be created for
     // this call.
-    MOZ_ASSERT(smgen_.framePushedBeforePushingCallArgs_.isNothing());
-    smgen_.framePushedBeforePushingCallArgs_.emplace(
-        masm.framePushed() + call->frameAlignAdjustment);
-
-    call->stackArgAreaSize = stackArgAreaSize;
+    MOZ_ASSERT(smgen_.framePushedExcludingOutboundCallArgs_.isNothing());
+    smgen_.framePushedExcludingOutboundCallArgs_.emplace(
+        // However much we've pushed so far
+        masm.framePushed() +
+        // Extra space we'll push to get the frame aligned
+        call->frameAlignAdjustment +
+        // Extra space we'll push to get the outbound arg area 16-aligned
+        (stackArgAreaSizeAligned - stackArgAreaSizeUnaligned));
+
+    call->stackArgAreaSize = stackArgAreaSizeAligned;
 
     size_t adjustment = call->stackArgAreaSize + call->frameAlignAdjustment;
     fr.allocArgArea(adjustment);
   }
 
   const ABIArg reservePointerArgument(FunctionCall* call) {
     return call->abi.next(MIRType::Pointer);
   }
@@ -4439,27 +4444,27 @@ class BaseCompiler final : public BaseCo
   // (Or it was, until Luke wandered through, but that can be fixed again.)
   // I'm not saying we should manually inline it, but we could hoist the
   // dispatch into the caller and have type-specific implementations of
   // passArg: passArgI32(), etc.  Then those might be inlined, at least in PGO
   // builds.
   //
   // The bulk of the work here (60%) is in the next() call, though.
   //
-  // Notably, since next() is so expensive, stackArgAreaSize() becomes
-  // expensive too.
-  //
-  // Somehow there could be a trick here where the sequence of
-  // argument types (read from the input stream) leads to a cached
-  // entry for stackArgAreaSize() and for how to pass arguments...
-  //
-  // But at least we could reduce the cost of stackArgAreaSize() by
-  // first reading the argument types into a (reusable) vector, then
-  // we have the outgoing size at low cost, and then we can pass
-  // args based on the info we read.
+  // Notably, since next() is so expensive, StackArgAreaSizeUnaligned()
+  // becomes expensive too.
+  //
+  // Somehow there could be a trick here where the sequence of argument types
+  // (read from the input stream) leads to a cached entry for
+  // StackArgAreaSizeUnaligned() and for how to pass arguments...
+  //
+  // But at least we could reduce the cost of StackArgAreaSizeUnaligned() by
+  // first reading the argument types into a (reusable) vector, then we have
+  // the outgoing size at low cost, and then we can pass args based on the
+  // info we read.
 
   void passArg(ValType type, const Stk& arg, FunctionCall* call) {
     switch (type.code()) {
       case ValType::I32: {
         ABIArg argLoc = call->abi.next(MIRType::Int32);
         if (argLoc.kind() == ABIArg::Stack) {
           ScratchI32 scratch(*this);
           loadI32(arg, scratch);
@@ -8596,17 +8601,17 @@ bool BaseCompiler::emitReturn() {
 
   return true;
 }
 
 bool BaseCompiler::emitCallArgs(const ValTypeVector& argTypes,
                                 FunctionCall* baselineCall) {
   MOZ_ASSERT(!deadCode_);
 
-  startCallArgs(stackArgAreaSize(argTypes), baselineCall);
+  startCallArgs(StackArgAreaSizeUnaligned(argTypes), baselineCall);
 
   uint32_t numArgs = argTypes.length();
   for (size_t i = 0; i < numArgs; ++i) {
     passArg(argTypes[i], peek(numArgs - 1 - i), baselineCall);
   }
 
   masm.loadWasmTlsRegFromFrame();
   return true;
@@ -9761,17 +9766,17 @@ bool BaseCompiler::emitInstanceCall(uint
   uint32_t numArgs = sig.length() - 1 /* instance */;
   size_t stackSpace = stackConsumed(numArgs);
 
   FunctionCall baselineCall(lineOrBytecode);
   beginCall(baselineCall, UseABI::System, InterModule::True);
 
   ABIArg instanceArg = reservePointerArgument(&baselineCall);
 
-  startCallArgs(stackArgAreaSize(sig), &baselineCall);
+  startCallArgs(StackArgAreaSizeUnaligned(sig), &baselineCall);
   for (uint32_t i = 1; i < sig.length(); i++) {
     ValType t;
     switch (sig[i]) {
       case MIRType::Int32:
         t = ValType::I32;
         break;
       case MIRType::Int64:
         t = ValType::I64;
@@ -10897,17 +10902,17 @@ bool BaseCompiler::emitBody() {
     }
 
     // Going below framePushedAtEntryToBody_ would imply that we've
     // popped off the machine stack, part of the frame created by
     // beginFunction().
     MOZ_ASSERT(masm.framePushed() >= smgen_.framePushedAtEntryToBody_.value());
 
     // At this point we're definitely not generating code for a function call.
-    MOZ_ASSERT(smgen_.framePushedBeforePushingCallArgs_.isNothing());
+    MOZ_ASSERT(smgen_.framePushedExcludingOutboundCallArgs_.isNothing());
 
     switch (op.b0) {
       case uint16_t(Op::End):
         if (!emitEnd()) {
           return false;
         }
 
         if (iter_.controlStackEmpty()) {
new file mode 100644
--- /dev/null
+++ b/js/src/wasm/WasmGC.cpp
@@ -0,0 +1,25 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ *
+ * Copyright 2019 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wasm/WasmGC.h"
+
+namespace js {
+namespace wasm {
+
+}  // namespace wasm
+}  // namespace js
new file mode 100644
--- /dev/null
+++ b/js/src/wasm/WasmGC.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: set ts=8 sts=2 et sw=2 tw=80:
+ *
+ * Copyright 2019 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef wasm_gc_h
+#define wasm_gc_h
+
+#include "jit/MacroAssembler.h"
+
+namespace js {
+namespace wasm {
+
+using namespace js::jit;
+
+// StackArgAreaSizeUnaligned returns the size, in bytes, of the stack arg area
+// size needed to pass |argTypes|, excluding any alignment padding beyond the
+// size of the area as a whole.  The size is as determined by the platforms
+// native ABI.
+//
+// StackArgAreaSizeAligned returns the same, but rounded up to the nearest 16
+// byte boundary.
+//
+// Note, StackArgAreaSize{Unaligned,Aligned}() must process all the arguments
+// in order to take into account all necessary alignment constraints.  The
+// signature must include any receiver argument -- in other words, it must be
+// the complete native-ABI-level call signature.
+template <class T>
+static inline size_t StackArgAreaSizeUnaligned(const T& argTypes) {
+  ABIArgIter<const T> i(argTypes);
+  while (!i.done()) {
+     i++;
+  }
+  return i.stackBytesConsumedSoFar();
+}
+
+static inline size_t AlignStackArgAreaSize(size_t unalignedSize) {
+  return AlignBytes(unalignedSize, 16u);
+}
+
+template <class T>
+static inline size_t StackArgAreaSizeAligned(const T& argTypes) {
+  return AlignStackArgAreaSize(StackArgAreaSizeUnaligned(argTypes));
+}
+
+}  // namespace wasm
+}  // namespace js
+
+#endif  // wasm_gc_h
--- a/js/src/wasm/moz.build
+++ b/js/src/wasm/moz.build
@@ -24,16 +24,17 @@ if CONFIG['ENABLE_WASM_CRANELIFT']:
 UNIFIED_SOURCES += [
     'AsmJS.cpp',
     'WasmBaselineCompile.cpp',
     'WasmBuiltins.cpp',
     'WasmCode.cpp',
     'WasmCompile.cpp',
     'WasmDebug.cpp',
     'WasmFrameIter.cpp',
+    'WasmGC.cpp',
     'WasmGenerator.cpp',
     'WasmInstance.cpp',
     'WasmIonCompile.cpp',
     'WasmJS.cpp',
     'WasmModule.cpp',
     'WasmOpIter.cpp',
     'WasmProcess.cpp',
     'WasmRealm.cpp',
--- a/layout/reftests/scrolling/reftest.list
+++ b/layout/reftests/scrolling/reftest.list
@@ -30,19 +30,19 @@ fuzzy-if(Android,0-4,0-120) HTTP == text
 fuzzy-if(d2d,0-1,0-4) fuzzy-if(webrender,0-1,0-42) HTTP == transformed-1.html transformed-1.html?ref
 fuzzy-if(webrender,0-1,0-43) HTTP == transformed-1.html?up transformed-1.html?ref
 fuzzy-if(Android,0-5,0-20000) == uncovering-1.html uncovering-1-ref.html
 fuzzy-if(Android,0-5,0-20000) == uncovering-2.html uncovering-2-ref.html
 fuzzy-if(asyncPan&&!layersGPUAccelerated,0-149,0-4520) == less-than-scrollbar-height.html less-than-scrollbar-height-ref.html
 == huge-horizontal-overflow.html huge-horizontal-overflow-ref.html
 == huge-vertical-overflow.html huge-vertical-overflow-ref.html
 fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-6818) == iframe-scrolling-attr-1.html iframe-scrolling-attr-ref.html
-fuzzy-if(gtkWidget,0-1,0-1) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-140,0-6818) == iframe-scrolling-attr-2.html iframe-scrolling-attr-ref.html
+fuzzy-if(asyncPan&&!layersGPUAccelerated,0-140,0-6818) == iframe-scrolling-attr-2.html iframe-scrolling-attr-ref.html
 fuzzy(0-1,0-2) == frame-scrolling-attr-1.html frame-scrolling-attr-ref.html
-fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-2420) == frame-scrolling-attr-2.html frame-scrolling-attr-ref.html
+fuzzy(0-1,0-2) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-2420) == frame-scrolling-attr-2.html frame-scrolling-attr-ref.html
 == move-item.html move-item-ref.html # bug 1125750
 == fractional-scroll-area.html?top=-0.4&outerBottom=100&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
 == fractional-scroll-area.html?top=0.4&outerBottom=100&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
 == fractional-scroll-area.html?top=0&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
 == fractional-scroll-area.html?top=0&outerBottom=100.4&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
 == fractional-scroll-area.html?top=-0.4&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
 == fractional-scroll-area.html?top=-0.4&outerBottom=100.4&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
 == fractional-scroll-area.html?top=0.4&outerBottom=99.6&innerBottom=200 fractional-scroll-area.html?top=0&outerBottom=100&innerBottom=200
--- a/mfbt/WindowsVersion.h
+++ b/mfbt/WindowsVersion.h
@@ -149,16 +149,20 @@ MOZ_ALWAYS_INLINE bool IsWin10CreatorsUp
 MOZ_ALWAYS_INLINE bool IsWin10FallCreatorsUpdateOrLater() {
   return IsWindows10BuildOrLater(16299);
 }
 
 MOZ_ALWAYS_INLINE bool IsWin10April2018UpdateOrLater() {
   return IsWindows10BuildOrLater(17134);
 }
 
+MOZ_ALWAYS_INLINE bool IsWin10Sep2018UpdateOrLater() {
+  return IsWindows10BuildOrLater(17763);
+}
+
 MOZ_ALWAYS_INLINE bool IsNotWin7PreRTM() {
   return IsWin7SP1OrLater() || IsWindowsBuildOrLater(7600);
 }
 
 inline bool IsWin7AndPre2000Compatible() {
   /*
    * See Bug 1279171.
    * We'd like to avoid using WMF on specific OS version when compatibility
--- a/testing/web-platform/meta/animation-worklet/worklet-animation-with-fill-mode.https.html.ini
+++ b/testing/web-platform/meta/animation-worklet/worklet-animation-with-fill-mode.https.html.ini
@@ -1,9 +1,10 @@
 [worklet-animation-with-fill-mode.https.html]
+  expected: ERROR
   [Effect with fill mode forwards in after phase produces output that is equivalent to effect's end value.]
     expected: FAIL
 
   [Effect with local time at start point is in active phase.]
     expected: FAIL
 
   [Effect without fill mode backwards in before phase (local time before start) should deactivate the animation.]
     expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/content-security-policy/connect-src/__dir__.ini
@@ -0,0 +1,2 @@
+leak-threshold: [default:51200]
+lsan-allowed: [Alloc, CSP_CreateHostSrcFromSelfURI, Malloc, NewPage, PLDHashTable::Add, Realloc, SetPropertyAsInterface, mozilla::WeakPtr, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::nsHttpTransaction::ParseHead, nsCSPParser::host, nsCSPParser::keywordSource, nsNodeSupportsWeakRefTearoff::GetWeakReference]
--- a/testing/web-platform/meta/content-security-policy/navigation/to-javascript-parent-initiated-parent-csp.html.ini
+++ b/testing/web-platform/meta/content-security-policy/navigation/to-javascript-parent-initiated-parent-csp.html.ini
@@ -1,4 +1,5 @@
 [to-javascript-parent-initiated-parent-csp.html]
+  expected: TIMEOUT
   [Should not have executed the javascript url]
-    expected: FAIL
+    expected: NOTRUN
 
--- a/testing/web-platform/meta/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html.ini
+++ b/testing/web-platform/meta/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html.ini
@@ -1,4 +1,7 @@
 [abspos-in-block-in-inline-in-relpos-inline.html]
   [Make sure that we're sized by the right ancestor]
     expected: FAIL
 
+  [position:absolute should be sized by the right ancestor]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-backgrounds/child-move-reveals-parent-background.html.ini
@@ -0,0 +1,6 @@
+[child-move-reveals-parent-background.html]
+  expected:
+    if not debug and not webrender and e10s and (os == "win") and (version == "10.0.17134") and (processor == "x86_64") and (bits == 64): FAIL
+    if debug and not webrender and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
+    if debug and not webrender and e10s and (os == "win") and (version == "10.0.17134") and (processor == "x86_64") and (bits == 64): FAIL
+    if not debug and not webrender and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
--- a/testing/web-platform/meta/css/css-font-loading/idlharness.https.html.ini
+++ b/testing/web-platform/meta/css/css-font-loading/idlharness.https.html.ini
@@ -1,18 +1,31 @@
 [idlharness.https.html]
   [FontFace interface: attribute variationSettings]
     expected:
-      if (os == "android"): PASS
-      if (os == "mac") and (version == "OS X 10.14" or version == "OS X 10.13"): PASS
+      if os == "android": PASS
+      if ((os == "mac") and (version == "OS X 10.14")) or (version == "OS X 10.13"): PASS
       if (os == "win") and (version == "10.0.17134"): PASS
       FAIL
 
   [FontFaceSet interface object length]
     expected: FAIL
 
   [FontFace interface: new FontFace("family", "src") must inherit property "variationSettings" with the proper type]
     expected:
-      if (os == "android"): PASS
-      if (os == "mac") and (version == "OS X 10.14" or version == "OS X 10.13"): PASS
+      if os == "android": PASS
+      if ((os == "mac") and (version == "OS X 10.14")) or (version == "OS X 10.13"): PASS
       if (os == "win") and (version == "10.0.17134"): PASS
       FAIL
 
+  [FontFace interface: fontFace must inherit property "variationSettings" with the proper type]
+    expected:
+      if debug and not webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
+      if not debug and not webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
+      if debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
+      if not debug and not webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
+      if not debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
+      if debug and not webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
+      if debug and not webrender and not e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
+      if (os == "win") and (version == "6.1.7601"): FAIL
+      if debug and not webrender and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
+      if not debug and not webrender and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-syntax/urange-parsing.html.ini
@@ -0,0 +1,229 @@
+[urange-parsing.html]
+  ["u+000000?" is invalid]
+    expected: FAIL
+
+  ["u+?a" is invalid]
+    expected: FAIL
+
+  ["u+0000000" is invalid]
+    expected: FAIL
+
+  ["u+0?-0a" is invalid]
+    expected: FAIL
+
+  ["u+00a????" is invalid]
+    expected: FAIL
+
+  ["u+2?????" is invalid]
+    expected: FAIL
+
+  ["u/**/+0a/**/?" => "U+A0-AF"]
+    expected: FAIL
+
+  ["u+aa?????" is invalid]
+    expected: FAIL
+
+  ["u+aaaaaaa" is invalid]
+    expected: FAIL
+
+  ["u+aaaa???" is invalid]
+    expected: FAIL
+
+  ["u/**/+/**/?" => "U+0-F"]
+    expected: FAIL
+
+  ["u+0??????" is invalid]
+    expected: FAIL
+
+  ["u+0aaaaa" => "U+AAAAA"]
+    expected: FAIL
+
+  ["u+00000aa" is invalid]
+    expected: FAIL
+
+  ["u+000000" => "U+0"]
+    expected: FAIL
+
+  ["u+000000-0aaaaa" => "U+0-AAAAA"]
+    expected: FAIL
+
+  ["u+a?a" is invalid]
+    expected: FAIL
+
+  ["u+?" => "U+0-F"]
+    expected: FAIL
+
+  ["u+a??????" is invalid]
+    expected: FAIL
+
+  ["u+0+0a" is invalid]
+    expected: FAIL
+
+  ["u+efg" is invalid]
+    expected: FAIL
+
+  ["u+0a0000" => "U+A0000"]
+    expected: FAIL
+
+  ["u+000000-000001" => "U+0-1"]
+    expected: FAIL
+
+  ["u+0?????" => "U+0-FFFFF"]
+    expected: FAIL
+
+  ["U+0a0" => "U+A0"]
+    expected: FAIL
+
+  ["u+0-000000a" is invalid]
+    expected: FAIL
+
+  ["u-0+1" is invalid]
+    expected: FAIL
+
+  ["u+a????" => "U+A0000-AFFFF"]
+    expected: FAIL
+
+  ["u+00000a" => "U+A"]
+    expected: FAIL
+
+  ["u+0-0aaaaaa" is invalid]
+    expected: FAIL
+
+  ["u+aaaaa??" is invalid]
+    expected: FAIL
+
+  ["u+000000a" is invalid]
+    expected: FAIL
+
+  ["u+222222-22222a" is invalid]
+    expected: FAIL
+
+  ["u/**/+0/**/?" => "U+0-F"]
+    expected: FAIL
+
+  ["u+aaa????" is invalid]
+    expected: FAIL
+
+  ["u+a??" => "U+A00-AFF"]
+    expected: FAIL
+
+  ["u+0?a" is invalid]
+    expected: FAIL
+
+  ["u + abc" is invalid]
+    expected: FAIL
+
+  ["u/**/0" is invalid]
+    expected: FAIL
+
+  ["u+0a" => "U+A"]
+    expected: FAIL
+
+  ["u+00000?" => "U+0-F"]
+    expected: FAIL
+
+  ["u/**/+/**/a/**/?" => "U+A0-AF"]
+    expected: FAIL
+
+  ["u+00000" => "U+0"]
+    expected: FAIL
+
+  ["u+0000" => "U+0"]
+    expected: FAIL
+
+  ["u+ abc" is invalid]
+    expected: FAIL
+
+  ["u+0a?????" is invalid]
+    expected: FAIL
+
+  ["u+222222" is invalid]
+    expected: FAIL
+
+  ["u+a???" => "U+A000-AFFF"]
+    expected: FAIL
+
+  ["u+00000a0" is invalid]
+    expected: FAIL
+
+  ["u+???????" is invalid]
+    expected: FAIL
+
+  ["u+00" => "U+0"]
+    expected: FAIL
+
+  ["u+0a00000" is invalid]
+    expected: FAIL
+
+  ["u+?????" => "u+0-FFFFF"]
+    expected: FAIL
+
+  ["u+0000000-0a" is invalid]
+    expected: FAIL
+
+  ["u+a?????" is invalid]
+    expected: FAIL
+
+  ["u+0a????" => "U+A0000-AFFFF"]
+    expected: FAIL
+
+  ["u+aaaaaa" is invalid]
+    expected: FAIL
+
+  ["u+0+1" is invalid]
+    expected: FAIL
+
+  ["u+aaaaaa?" is invalid]
+    expected: FAIL
+
+  ["u+00000??" is invalid]
+    expected: FAIL
+
+  ["u/**/+0/**/-0a" => "U+0-A"]
+    expected: FAIL
+
+  ["u+000" => "U+0"]
+    expected: FAIL
+
+  ["u+0aaaaaa" is invalid]
+    expected: FAIL
+
+  ["u+0-222222" is invalid]
+    expected: FAIL
+
+  ["u+0aaaaa0" is invalid]
+    expected: FAIL
+
+  ["u+a?" => "U+A0-AF"]
+    expected: FAIL
+
+  ["U + a b c" is invalid]
+    expected: FAIL
+
+  ["u-0-1" is invalid]
+    expected: FAIL
+
+  ["u+??????" is invalid]
+    expected: FAIL
+
+  ["u+22222a" is invalid]
+    expected: FAIL
+
+  ["u+0-0a" => "U+0-A"]
+    expected: FAIL
+
+  ["u/**/+0/**/-1" => "U+0-1"]
+    expected: FAIL
+
+  ["u +abc" is invalid]
+    expected: FAIL
+
+  ["u+0000000-1" is invalid]
+    expected: FAIL
+
+  ["u+0-0a?" is invalid]
+    expected: FAIL
+
+  ["u+0-0000001" is invalid]
+    expected: FAIL
+
--- a/testing/web-platform/meta/css/css-text/i18n/ja/css-text-line-break-ja-po-loose.html.ini
+++ b/testing/web-platform/meta/css/css-text/i18n/ja/css-text-line-break-ja-po-loose.html.ini
@@ -3,12 +3,8 @@
     expected: FAIL
 
   [FF05  FULLWIDTH PERCENT SIGN may appear at line start if ja and loose]
     expected: FAIL
 
   [FFE0  FULLWIDTH CENT SIGN may appear at line start if ja and loose]
     expected: FAIL
 
-  [2035  REVERSED PRIME may appear at line start if ja and loose]
-    expected:
-      if (os == "win") and (version == "6.1.7601"): FAIL
-
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-values/angle-units-001.html.ini
@@ -0,0 +1,3 @@
+[angle-units-001.html]
+  expected:
+    if (os == "win") and webrender: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-values/angle-units-002.html.ini
@@ -0,0 +1,3 @@
+[angle-units-002.html]
+  expected:
+    if (os == "win") and webrender: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-values/angle-units-003.html.ini
@@ -0,0 +1,3 @@
+[angle-units-003.html]
+  expected:
+    if (os == "win") and webrender: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-values/angle-units-004.html.ini
@@ -0,0 +1,3 @@
+[angle-units-004.html]
+  expected:
+    if (os == "win") and webrender: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-values/angle-units-005.html.ini
@@ -0,0 +1,3 @@
+[angle-units-005.html]
+  expected:
+    if (os == "win") and webrender: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-values/attr-invalid-type-008.html.ini
@@ -0,0 +1,2 @@
+[attr-invalid-type-008.html]
+  expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-values/calc-numbers.html.ini
@@ -0,0 +1,28 @@
+[calc-numbers.html]
+  [testing tab-size: calc(bla) 10px]
+    expected: FAIL
+
+  [testing tab-size: calc(10px)]
+    expected: FAIL
+
+  [testing tab-size: calc(100%)]
+    expected: FAIL
+
+  [testing tab-size: calc(10px) bla]
+    expected: FAIL
+
+  [testing tab-size: calc(2 * 3)]
+    expected: FAIL
+
+  [testing tab-size: calc(2 * -4)]
+    expected: FAIL
+
+  [testing tab-size: calc(1 + 100%)]
+    expected: FAIL
+
+  [testing tab-size: calc(1 + 1px)]
+    expected: FAIL
+
+  [testing tab-size: calc(2 / 4)]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-values/ch-unit-010.html.ini
@@ -0,0 +1,2 @@
+[ch-unit-010.html]
+  expected: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-values/ch-unit-012.html.ini
@@ -0,0 +1,3 @@
+[ch-unit-012.html]
+  expected:
+    if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
--- a/testing/web-platform/meta/css/css-values/lh-rlh-on-root-001.html.ini
+++ b/testing/web-platform/meta/css/css-values/lh-rlh-on-root-001.html.ini
@@ -12,8 +12,14 @@
     expected: FAIL
 
   [2lh in font-size on root]
     expected: FAIL
 
   [2rlh in font-size on root]
     expected: FAIL
 
+  [lh in font-size on root]
+    expected: FAIL
+
+  [rlh in font-size on root]
+    expected: FAIL
+
--- a/testing/web-platform/meta/css/geometry/interfaces.worker.js.ini
+++ b/testing/web-platform/meta/css/geometry/interfaces.worker.js.ini
@@ -1,10 +1,9 @@
 [interfaces.worker.html]
-  expected: ERROR
   [DOMPointReadOnly interface: existence and properties of interface object]
     expected: FAIL
 
   [DOMPointReadOnly interface object length]
     expected: FAIL
 
   [DOMPointReadOnly interface object name]
     expected: FAIL
@@ -2719,8 +2718,26 @@
     expected: FAIL
 
   [DOMMatrixReadOnly interface: new DOMMatrixReadOnly() must inherit property "scaleNonUniform(unrestricted double, unrestricted double)" with the proper type]
     expected: FAIL
 
   [DOMMatrixReadOnly interface: operation scaleNonUniform(unrestricted double, unrestricted double)]
     expected: FAIL
 
+  [DOMPointReadOnly interface: default toJSON operation on new DOMPoint()]
+    expected: FAIL
+
+  [DOMPointReadOnly interface: default toJSON operation on new DOMPointReadOnly()]
+    expected: FAIL
+
+  [DOMRectReadOnly interface: default toJSON operation on new DOMRect()]
+    expected: FAIL
+
+  [DOMRectReadOnly interface: default toJSON operation on new DOMRectReadOnly()]
+    expected: FAIL
+
+  [DOMQuad interface: default toJSON operation on new DOMQuad()]
+    expected: FAIL
+
+  [DOMMatrixReadOnly interface: default toJSON operation on new DOMMatrixReadOnly()]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/custom-elements/reactions/HTMLModElement.html.ini
@@ -0,0 +1,7 @@
+[HTMLModElement.html]
+  [dateTime on del use HTMLModElement must enqueue an attributeChanged reaction when adding dateTime content attribute]
+    expected: FAIL
+
+  [dateTime on ins use HTMLModElement must enqueue an attributeChanged reaction when adding dateTime content attribute]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/custom-elements/reactions/HTMLTimeElement.html.ini
@@ -0,0 +1,4 @@
+[HTMLTimeElement.html]
+  [dateTime on HTMLTimeElement must enqueue an attributeChanged reaction when adding dateTime content attribute]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/element-timing/buffer-before-onload.html.ini
@@ -0,0 +1,4 @@
+[buffer-before-onload.html]
+  [Element Timing: image loads before onload.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/element-timing/image-not-fully-visible.html.ini
@@ -0,0 +1,5 @@
+[image-not-fully-visible.html]
+  expected: TIMEOUT
+  [The intersectionRect of an img element overflowing is computed correctly]
+    expected: TIMEOUT
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/element-timing/observe-child-element.html.ini
@@ -0,0 +1,5 @@
+[observe-child-element.html]
+  expected: TIMEOUT
+  [Element from same-origin iframe is observable.]
+    expected: TIMEOUT
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/element-timing/observe-elementtiming.html.ini
@@ -0,0 +1,5 @@
+[observe-elementtiming.html]
+  expected: TIMEOUT
+  [Element with elementtiming attribute is observable.]
+    expected: TIMEOUT
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/element-timing/observe-large-image.html.ini
@@ -0,0 +1,5 @@
+[observe-large-image.html]
+  expected: TIMEOUT
+  [Large img element is observable.]
+    expected: TIMEOUT
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/element-timing/observe-multiple-images.html.ini
@@ -0,0 +1,5 @@
+[observe-multiple-images.html]
+  expected: TIMEOUT
+  [PerformanceObserver can observe multiple image elements.]
+    expected: TIMEOUT
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/element-timing/progressively-loaded-image.html.ini
@@ -0,0 +1,4 @@
+[progressively-loaded-image.html]
+  [Element Timing: image render timestamp occurs after it is fully loaded.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/element-timing/supported-element-type.html.ini
@@ -0,0 +1,4 @@
+[supported-element-type.html]
+  [supportedEntryTypes contains 'element'.]
+    expected: FAIL
+
--- a/testing/web-platform/meta/html/dom/__dir__.ini
+++ b/testing/web-platform/meta/html/dom/__dir__.ini
@@ -1,1 +1,2 @@
 leak-threshold: [default:51200]
+lsan-allowed: [Alloc, Malloc, NewPage, PLDHashTable::Add, Realloc, SetPropertyAsInterface, mozilla::WeakPtr, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::nsUDPSocket::SendWithAddress, nsNodeSupportsWeakRefTearoff::GetWeakReference]
deleted file mode 100644
--- a/testing/web-platform/meta/mozilla-sync
+++ b/testing/web-platform/meta/mozilla-sync
@@ -1,2 +1,2 @@
-local: 43e3aad0ad8f7bc99b03c1871e25193e9382aa7a
-upstream: 9c5701192b581208a028144cb0fc27e462541a49
+local: 6153030f2e587bf87d8641038c687dce1fd3351a
+upstream: fab38653d3a4a8ce01db100fa049bdc72f4b8270
--- a/testing/web-platform/meta/payment-request/allowpaymentrequest/allowpaymentrequest-attribute-cross-origin-bc-containers.https.html.ini
+++ b/testing/web-platform/meta/payment-request/allowpaymentrequest/allowpaymentrequest-attribute-cross-origin-bc-containers.https.html.ini
@@ -4,13 +4,15 @@
       if not e10s: FAIL
 
   [frame]
     expected:
       if not e10s: FAIL
 
   [object]
     expected:
-      if (os == "linux") and debug and not webrender and not e10s: "FAIL"
+      if (os == "linux") and debug and not webrender and not e10s: FAIL
+      if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
 
   [embed]
     expected:
       if not e10s: FAIL
+
--- a/testing/web-platform/meta/payment-request/payment-is-showing.https.html.ini
+++ b/testing/web-platform/meta/payment-request/payment-is-showing.https.html.ini
@@ -8,48 +8,55 @@
     expected: FAIL
 
   [Navigating an nested browsing context sets 'payment request is showing boolean' back to false]
     expected: FAIL
 
   [Given multiple nested browsing contexts, and an iframe calls show() first, other nested browsing contexts can't show a request.]
     expected:
       if not debug and webrender and (os == "linux"): TIMEOUT
+      if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): NOTRUN
       FAIL
 
   [Using a popup window prevents the top-browsing context from showing a payment request]
     expected: FAIL
 
   [An iframe cannot show a payment request if the top-level window is already showing one.]
     expected: FAIL
 
   [Given multiple nested browsing contexts, and popup calls show() first, other nested browsing contexts can't show a request.]
-    expected: FAIL
+    expected:
+      if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): NOTRUN
+      FAIL
 
   [The top browsing context can only show one payment sheet at a time.]
     expected: FAIL
 
   [Navigating an iframe as a nested browsing context sets 'payment request is showing boolean' to false.]
     expected:
       if debug and e10s and (os == "linux") and (processor == "x86"): TIMEOUT
       if debug and webrender and (os == "linux"): TIMEOUT
       if debug and (os == "mac"): TIMEOUT
-      if (os == "win"): TIMEOUT
+      if os == "win": TIMEOUT
       if not debug and not webrender and e10s and (os == "linux") and (processor == "x86_64"): TIMEOUT
       if not debug and webrender and (os == "linux"): NOTRUN
       if debug and not webrender and e10s and (os == "linux") and (processor == "x86_64"): TIMEOUT
       if not debug and e10s and (os == "linux") and (processor == "x86"): TIMEOUT
       if not debug and (os == "mac"): TIMEOUT
+      if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): NOTRUN
       FAIL
 
   [Given multiple nested browsing contexts, and window calls show() first, other nested browsing contexts can't show a request.]
-    expected: FAIL
+    expected:
+      if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): TIMEOUT
+      FAIL
 
   [If an iframe shows a payment request, the top-level browsing context can't also show one.]
     expected: FAIL
 
   [Navigating a popup as a nested browsing context sets 'payment request is showing boolean' to false.]
     expected:
       if e10s and (os == "linux"): NOTRUN
-      if (os == "mac"): NOTRUN
-      if (os == "win"): NOTRUN
+      if os == "mac": NOTRUN
+      if os == "win": NOTRUN
+      if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): NOTRUN
       FAIL
 
deleted file mode 100644
--- a/testing/web-platform/meta/performance-timeline/case-sensitivity.any.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[case-sensitivity.any.html]
-  disabled:
-    if (os == "linux" and not debug): https://bugzilla.mozilla.org/show_bug.cgi?id=1513292
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/performance-timeline/po-observe-type.any.js.ini
@@ -0,0 +1,33 @@
+[po-observe-type.any.html]
+  [Calling observe() with entryTypes and then type should throw an InvalidModificationError]
+    expected: FAIL
+
+  [Calling observe() with type and then entryTypes should throw an InvalidModificationError]
+    expected: FAIL
+
+  [Calling observe() with type and entryTypes should throw a SyntaxError]
+    expected: FAIL
+
+  [Passing in unknown values to type does throw an exception.]
+    expected: FAIL
+
+  [observe() with different type values stacks.]
+    expected: FAIL
+
+
+[po-observe-type.any.worker.html]
+  [Calling observe() with entryTypes and then type should throw an InvalidModificationError]
+    expected: FAIL
+
+  [Calling observe() with type and then entryTypes should throw an InvalidModificationError]
+    expected: FAIL
+
+  [Calling observe() with type and entryTypes should throw a SyntaxError]
+    expected: FAIL
+
+  [Passing in unknown values to type does throw an exception.]
+    expected: FAIL
+
+  [observe() with different type values stacks.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/performance-timeline/po-observe.any.js.ini
@@ -0,0 +1,9 @@
+[po-observe.any.html]
+  [no 'type' or 'entryTypes' throws a SyntaxError]
+    expected: FAIL
+
+
+[po-observe.any.worker.html]
+  [no 'type' or 'entryTypes' throws a SyntaxError]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/portals/portals-activate-no-browsing-context.html.ini
@@ -0,0 +1,4 @@
+[portals-activate-no-browsing-context.html]
+  [A portal with nothing in it cannot be activated]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/portals/portals-cross-origin-load.sub.html.ini
@@ -0,0 +1,5 @@
+[portals-cross-origin-load.sub.html]
+  expected: TIMEOUT
+  [portals-cross-origin-load]
+    expected: TIMEOUT
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/portals/portals-host-exposure.sub.html.ini
@@ -0,0 +1,11 @@
+[portals-host-exposure.sub.html]
+  expected: TIMEOUT
+  [window.portalHost should be exposed in same-origin portal]
+    expected: TIMEOUT
+
+  [window.portalHost should be exposed in cross-origin portal]
+    expected: NOTRUN
+
+  [window.portalHost should be exposed in portal after cross-origin navigation]
+    expected: NOTRUN
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/portals/portals-host-hidden-after-activation.html.ini
@@ -0,0 +1,5 @@
+[portals-host-hidden-after-activation.html]
+  expected: TIMEOUT
+  [window.portalHost should be null after portal is activated]
+    expected: TIMEOUT
+
--- a/testing/web-platform/meta/resource-timing/test_resource_timing.https.html.ini
+++ b/testing/web-platform/meta/resource-timing/test_resource_timing.https.html.ini
@@ -1,3 +1,6 @@
 [test_resource_timing.https.html]
   [PerformanceEntry has correct order of timing attributes (iframe)]
-    expected: FAIL
+    expected:
+      if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): PASS
+      FAIL
+
--- a/testing/web-platform/meta/screen-capture/feature-policy.https.html.ini
+++ b/testing/web-platform/meta/screen-capture/feature-policy.https.html.ini
@@ -1,7 +1,23 @@
 [feature-policy.https.sub.html]
   [Default "display-capture" feature policy ["self"\] disallows cross-origin iframes.]
     expected: FAIL
 
+
 [feature-policy.https.html]
   [Default "display-capture" feature policy ["self"\] disallows cross-origin iframes.]
-    expected: FAIL
+    expected:
+      if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): PASS
+      FAIL
+
+  [Default "display-capture" feature policy ["self"\] allows the top-level document.]
+    expected:
+      if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
+
+  [Feature policy "display-capture" can be enabled in cross-origin iframes using "allow" attribute.]
+    expected:
+      if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
+
+  [Default "display-capture" feature policy ["self"\] allows same-origin iframes.]
+    expected:
+      if not debug and not webrender and not e10s and (os == "android") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
+
--- a/testing/web-platform/meta/screen-capture/getdisplaymedia.https.html.ini
+++ b/testing/web-platform/meta/screen-capture/getdisplaymedia.https.html.ini
@@ -1,75 +1,64 @@
 [getdisplaymedia.https.html]
   [getDisplayMedia({"video":true}) must succeed with video]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia({"video":true,"audio":false}) must succeed with video]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia({"audio":false}) must succeed with video]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia({}) must succeed with video]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia(undefined) must succeed with video]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia({"video":true,"audio":true}) must succeed with video maybe audio]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia({"audio":true}) must succeed with video maybe audio]
     expected:
-      if (os == "android"): FAIL
+      if os == "android": FAIL
       PASS
 
   [getDisplayMedia({"video":{"width":{"max":360}}}) must be constrained]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia({"video":{"height":{"max":240}}}) must be constrained]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia({"video":{"width":{"max":360},"height":{"max":240}}}) must be constrained]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia({"video":{"frameRate":{"max":4}}}) must be constrained]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia({"video":{"frameRate":{"max":4},"width":{"max":360}}}) must be constrained]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia({"video":{"frameRate":{"max":4},"height":{"max":240}}}) must be constrained]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia({"video":{"frameRate":{"max":4},"width":{"max":360},"height":{"max":240}}}) must be constrained]
     expected:
-      if (os == "android"): FAIL
-      PASS
+      if os == "android": FAIL
 
   [getDisplayMedia() with getSettings]
-    expected:
-      if (os == "android"): FAIL
-      FAIL
+    expected: FAIL
+
+  [getDisplayMedia({"audio":true}) must fail with TypeError]
+    expected: FAIL
+
--- a/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-match.https.html.ini
+++ b/testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-match.https.html.ini
@@ -1,4 +1,7 @@
 [cache-match.https.html]
   [cors-exposed header should be stored correctly.]
     expected: FAIL
 
+  [Cache.match does not support cacheName option]
+    expected: FAIL
+
--- a/testing/web-platform/meta/service-workers/cache-storage/window/cache-match.https.html.ini
+++ b/testing/web-platform/meta/service-workers/cache-storage/window/cache-match.https.html.ini
@@ -1,4 +1,7 @@
 [cache-match.https.html]
   [cors-exposed header should be stored correctly.]
     expected: FAIL
 
+  [Cache.match does not support cacheName option]
+    expected: FAIL
+
--- a/testing/web-platform/meta/service-workers/cache-storage/worker/cache-match.https.html.ini
+++ b/testing/web-platform/meta/service-workers/cache-storage/worker/cache-match.https.html.ini
@@ -1,4 +1,7 @@
 [cache-match.https.html]
   [cors-exposed header should be stored correctly.]
     expected: FAIL
 
+  [Cache.match does not support cacheName option]
+    expected: FAIL
+
--- a/testing/web-platform/meta/service-workers/service-worker/navigation-redirect.https.html.ini
+++ b/testing/web-platform/meta/service-workers/service-worker/navigation-redirect.https.html.ini
@@ -1,16 +1,16 @@
 [navigation-redirect.https.html]
   [Service Worker: Navigation redirection]
     expected: FAIL
 
 
 [navigation-redirect.https.html?client]
   disabled:
-    if (os == "mac"): true
+    if os == "mac": true
   [Redirect to same-origin out-scope with opaque redirect response.]
     expected: FAIL
 
   [SW-generated redirect to same-origin out-scope with different hash fragments.]
     expected: FAIL
 
   [Redirect to same-origin out-scope with opaque redirect response which is passed through Cache.]
     expected: FAIL
rename from testing/web-platform/meta/wasm/serialization/broadcastchannel-success-and-failure.html.ini
rename to testing/web-platform/meta/wasm/serialization/module/broadcastchannel-success-and-failure.html.ini
rename from testing/web-platform/meta/wasm/serialization/broadcastchannel-success.html.ini
rename to testing/web-platform/meta/wasm/serialization/module/broadcastchannel-success.html.ini
rename from testing/web-platform/meta/wasm/serialization/window-messagechannel-success.html.ini
rename to testing/web-platform/meta/wasm/serialization/module/window-messagechannel-success.html.ini
rename from testing/web-platform/meta/wasm/serialization/window-serviceworker-failure.https.html.ini
rename to testing/web-platform/meta/wasm/serialization/module/window-serviceworker-failure.https.html.ini
rename from testing/web-platform/meta/wasm/serialization/window-sharedworker-failure.html.ini
rename to testing/web-platform/meta/wasm/serialization/module/window-sharedworker-failure.html.ini
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/webaudio/the-audio-api/the-pannernode-interface/automation-changes.html.ini
@@ -0,0 +1,2 @@
+[automation-changes.html]
+  expected: ERROR
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/webrtc/RTCError.html.ini
@@ -0,0 +1,67 @@
+[RTCError.html]
+  [RTCError constructor with message and errorDetail]
+    expected: FAIL
+
+  [RTCError.errorDetail is readonly.]
+    expected: FAIL
+
+  [RTCError constructor throws TypeError if the errorDetail is invalid]
+    expected: FAIL
+
+  [RTCError.receivedAlert is settable by constructor]
+    expected: FAIL
+
+  [RTCError.sctpCauseCode is readonly]
+    expected: FAIL
+
+  [RTCError.code is 0]
+    expected: FAIL
+
+  [RTCError.sdpLineNumber is null by default]
+    expected: FAIL
+
+  [RTCError.httpRequestStatusCode is settable by constructor]
+    expected: FAIL
+
+  [RTCError.sentAlert is null by default]
+    expected: FAIL
+
+  [RTCError.sentAlert is settable by constructor]
+    expected: FAIL
+
+  [RTCError.receivedAlert is null by default]
+    expected: FAIL
+
+  [RTCError.httpRequestStatusCode is null by default]
+    expected: FAIL
+
+  [RTCError.receivedAlert is readonly]
+    expected: FAIL
+
+  [RTCError constructor throws TypeError if any argument is missing]
+    expected: FAIL
+
+  [RTCErrorInit.errorDetail is the only required attribute]
+    expected: FAIL
+
+  [RTCError.sdpLineNumber is settable by constructor]
+    expected: FAIL
+
+  [RTCError.sctpCauseCode is settable by constructor]
+    expected: FAIL
+
+  [RTCError.sdpLineNumber is readonly]
+    expected: FAIL
+
+  [RTCError.sentAlert is readonly]
+    expected: FAIL
+
+  [RTCError.sctpCauseCode is null by default]
+    expected: FAIL
+
+  [RTCError.httpRequestStatusCode is readonly]
+    expected: FAIL
+
+  [RTCError.name is 'RTCError']
+    expected: FAIL
+
--- a/testing/web-platform/meta/webrtc/RTCIceCandidate-constructor.html.ini
+++ b/testing/web-platform/meta/webrtc/RTCIceCandidate-constructor.html.ini
@@ -36,8 +36,14 @@
     expected: FAIL
 
   [new RTCIceCandidate({ ... }) with invalid sdpMid]
     expected: FAIL
 
   [new RTCIceCandidate({ ... }) with invalid sdpMLineIndex]
     expected: FAIL
 
+  [new RTCIceCandidate({ ... }) with nondefault values for all fields, tcp candidate]
+    expected: FAIL
+
+  [new RTCIceCandidate({ ... }) with nondefault values for all fields]
+    expected: FAIL
+
--- a/testing/web-platform/meta/webrtc/RTCIceTransport-extension.https.html.ini
+++ b/testing/web-platform/meta/webrtc/RTCIceTransport-extension.https.html.ini
@@ -81,8 +81,14 @@
     expected: FAIL
 
   [Selected candidate pair changes once the RTCIceTransports connect.]
     expected: FAIL
 
   [getSelectedCandidatePair() returns null once the RTCIceTransport is stopped.]
     expected: FAIL
 
+  [Two RTCIceTransports configured with the controlled role resolve the conflict in band and still connect.]
+    expected: FAIL
+
+  [Two RTCIceTransports configured with the controlling role resolve the conflict in band and still connect.]
+    expected: FAIL
+
--- a/testing/web-platform/meta/webrtc/idlharness.https.window.js.ini
+++ b/testing/web-platform/meta/webrtc/idlharness.https.window.js.ini
@@ -606,8 +606,11 @@
     expected: FAIL
 
   [RTCDtlsTransport interface: idlTestObjects.dtlsTransport must inherit property "iceTransport" with the proper type]
     expected: FAIL
 
   [RTCDtlsTransport interface: attribute iceTransport]
     expected: FAIL
 
+  [RTCIceCandidate interface: toJSON operation on new RTCIceCandidate({ sdpMid: 1 })]
+    expected: FAIL
+
--- a/testing/web-platform/meta/websockets/__dir__.ini
+++ b/testing/web-platform/meta/websockets/__dir__.ini
@@ -1,1 +1,2 @@
-leak-threshold: [default:51200]
+leak-threshold: [default:102400]
+lsan-allowed: [Alloc, Create, MakeUnique, NewPage, PLDHashTable::Add, Realloc, SetPropertyAsInterface, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::WeakPtr, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsHttpTransaction::ParseHead, mozilla::net::nsStandardURL::TemplatedMutator, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSupportsWeakReference::GetWeakReference]
--- a/testing/web-platform/meta/websockets/constructor/__dir__.ini
+++ b/testing/web-platform/meta/websockets/constructor/__dir__.ini
@@ -1,3 +1,3 @@
-lsan-allowed: [MakeUnique, mozilla::dom::WebSocket::ConstructorCommon, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketEventService::GetOrCreate, Alloc, Create, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::dom::nsIContentChild::GetConstructedEventTarget, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create]
+lsan-allowed: [Alloc, Create, MakeUnique, Malloc, NewPage, PLDHashTable::Add, PLDHashTable::ChangeTable, Realloc, RecvOnAcknowledge, RecvOnStop, SetPropertyAsInterface, SetSucceededCertChain, allocate, mozilla::BasePrincipal::CreateCodebasePrincipal, mozilla::SchedulerGroup::CreateEventTargetFor, mozilla::ThrottledEventQueue::Create, mozilla::WeakPtr, mozilla::dom::ScriptElement::MaybeProcessScript, mozilla::dom::WebSocket::ConstructorCommon, mozilla::dom::WebSocket::WebSocket, mozilla::dom::WorkerCSPEventListener::Create, mozilla::dom::nsIContentChild::GetConstructedEventTarget, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::BaseWebSocketChannel::InitLoadInfo, mozilla::net::WebSocketChannelChild::AsyncOpen, mozilla::net::WebSocketChannelChild::RecvOnServerClose, mozilla::net::WebSocketEventService::GetOrCreate, mozilla::net::nsHttpTransaction::ParseHead, mozilla::net::nsStandardURL::TemplatedMutator, nsAtomTable::Atomize, nsDocShell::Create, nsNSSCertificate::Create, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSSLIOLayerAddToSocket]
 lsan-max-stack-depth: 7
 leak-threshold: [tab:51200]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/websockets/opening-handshake/__dir__.ini
@@ -0,0 +1,1 @@
+lsan-allowed: [Alloc, NS_NewInterfaceRequestorAggregation, NewPage, PLDHashTable::Add, Realloc, SetPropertyAsInterface, SetSucceededCertChain, allocate, mozilla::WeakPtr, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::nsHttpTransaction::ParseHead, nsNSSCertificate::Create, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSSLIOLayerAddToSocket]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/websockets/security/__dir__.ini
@@ -0,0 +1,1 @@
+lsan-allowed: [Alloc, NewPage, PLDHashTable::Add, Realloc, SetPropertyAsInterface, SetSucceededCertChain, allocate, mozilla::WeakPtr, mozilla::extensions::ChannelWrapper::ChannelWrapper, mozilla::net::nsHttpTransaction::ParseHead, nsNSSCertificate::Create, nsNodeSupportsWeakRefTearoff::GetWeakReference, nsSSLIOLayerAddToSocket]
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/webstorage/symbol-props.window.js.ini
@@ -0,0 +1,25 @@
+[symbol-props.window.html]
+  [sessionStorage: plain set + get (loose)]
+    expected: FAIL
+
+  [localStorage: defineProperty + get]
+    expected: FAIL
+
+  [sessionStorage: plain set + get (strict)]
+    expected: FAIL
+
+  [localStorage: defineProperty not configurable]
+    expected: FAIL
+
+  [sessionStorage: defineProperty + get]
+    expected: FAIL
+
+  [sessionStorage: defineProperty not configurable]
+    expected: FAIL
+
+  [localStorage: plain set + get (strict)]
+    expected: FAIL
+
+  [localStorage: plain set + get (loose)]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/workers/SharedWorker-constructor.html.ini
@@ -0,0 +1,4 @@
+[SharedWorker-constructor.html]
+  [Test recursive worker creation results in exception.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/workers/SharedWorker-exception-propagation.html.ini
@@ -0,0 +1,4 @@
+[SharedWorker-exception-propagation.html]
+  [Uncaught error in shared worker should not propagate to window]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/workers/SharedWorker-script-error.html.ini
@@ -0,0 +1,2 @@
+[SharedWorker-script-error.html]
+  expected: ERROR
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/workers/Worker-constructor-proto.any.js.ini
@@ -0,0 +1,14 @@
+[Worker-constructor-proto.any.sharedworker.html]
+  [Tests that setting the proto of a built in constructor is not reset.]
+    expected: FAIL
+
+
+[Worker-constructor-proto.any.worker.html]
+  [Tests that setting the proto of a built in constructor is not reset.]
+    expected: FAIL
+
+
+[Worker-constructor-proto.any.serviceworker.html]
+  [Tests that setting the proto of a built in constructor is not reset.]
+    expected: FAIL
+
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/workers/Worker-location.sub.any.js.ini
@@ -0,0 +1,9 @@
+[Worker-location.sub.any.sharedworker.html]
+  [Test WorkerLocation properties.]
+    expected: FAIL
+
+
+[Worker-location.sub.any.worker.html]
+  [Test WorkerLocation properties.]
+    expected: FAIL
+
--- a/testing/web-platform/tests/.azure-pipelines.yml
+++ b/testing/web-platform/tests/.azure-pipelines.yml
@@ -8,16 +8,21 @@
 #
 # In addition to this configuration file, some setup in the Azure DevOps
 # project is required:
 #  - The "Build pull requests from forks of this repository" setting must be
 #    enabled: https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/github#validate-contributions-from-forks
 #  - A scheduled build needs to be set up for the the epochs/daily branch.
 #  - To get results from scheduled builds into wpt.fyi, a service connection
 #    named wpt.fyi with URL https://wpt.fyi is needed.
+#  - Self-hosted agents for Windows 10 are used:
+#    - 'Hosted Windows Client' is the latest Windows 10
+#    - 'Hosted Windows Client Next' is Windows 10 Insider Preview
+#    Documention for the setup of these agents:
+#    https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/v2-windows
 
 jobs:
 # The affected tests jobs are unconditional for speed, as most PRs have one or
 # more affected tests: https://github.com/web-platform-tests/wpt/issues/13936.
 - job: affected_macOS
   displayName: 'affected tests (Safari Technology Preview)'
   condition: eq(variables['Build.Reason'], 'PullRequest')
   pool:
@@ -122,16 +127,69 @@ jobs:
   - template: tools/ci/azure/install_chrome.yml
   - template: tools/ci/azure/install_firefox.yml
   - template: tools/ci/azure/update_hosts.yml
   - template: tools/ci/azure/update_manifest.yml
   - template: tools/ci/azure/tox_pytest.yml
     parameters:
       directory: tools/wpt/
 
+- job: infrastructure_win10
+  displayName: 'infrastructure/ tests (Windows 10)'
+  # This job is only triggered manually until it has been shown to be robust.
+  condition: and(eq(variables['Build.Reason'], 'Manual'), variables['run_infrastructure_win10'])
+  pool:
+    name: 'Hosted Windows Client'
+  steps:
+  - template: tools/ci/azure/system_info.yml
+  - template: tools/ci/azure/checkout.yml
+  - template: tools/ci/azure/install_python.yml
+  - template: tools/ci/azure/pip_install.yml
+    parameters:
+      packages: virtualenv
+  - template: tools/ci/azure/install_certs.yml
+  - template: tools/ci/azure/update_hosts.yml
+  - template: tools/ci/azure/update_manifest.yml
+  - script: python ./wpt run --yes --no-manifest-update --install-fonts --manifest MANIFEST.json --metadata infrastructure/metadata/ --log-tbpl $(Build.ArtifactStagingDirectory)/edge.tbpl.log --log-tbpl-level info edge_webdriver infrastructure/
+    displayName: 'Run tests (Edge)'
+  - task: PublishBuildArtifacts@1
+    displayName: 'Publish results'
+    inputs:
+      artifactName: 'infrastructure'
+    condition: succeededOrFailed()
+  - template: tools/ci/azure/cleanup_win10.yml
+
+- job: all_edge
+  displayName: 'all tests (Edge)'
+  # This job is only triggered manually until it has been shown to be robust.
+  condition: and(eq(variables['Build.Reason'], 'Manual'), variables['run_all_edge'])
+  # There are 5 agents in the pool, but use more jobs so that each takes <1h.
+  strategy:
+    parallel: 20
+  timeoutInMinutes: 360
+  pool:
+    name: 'Hosted Windows Client'
+  steps:
+  - template: tools/ci/azure/system_info.yml
+  - template: tools/ci/azure/checkout.yml
+  - template: tools/ci/azure/install_python.yml
+  - template: tools/ci/azure/pip_install.yml
+    parameters:
+      packages: virtualenv
+  - template: tools/ci/azure/install_certs.yml
+  - template: tools/ci/azure/update_hosts.yml
+  - template: tools/ci/azure/update_manifest.yml
+  - script: python ./wpt run --no-manifest-update --no-restart-on-unexpected --no-fail-on-unexpected --install-fonts --test-types reftest testharness --this-chunk $(System.JobPositionInPhase) --total-chunks $(System.TotalJobsInPhase) --chunk-type hash --log-tbpl - --log-tbpl-level info --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report_$(System.JobPositionInPhase).json edge_webdriver
+    displayName: 'Run tests'
+  - task: PublishBuildArtifacts@1
+    displayName: 'Publish results'
+    inputs:
+      artifactName: 'results'
+  - template: tools/ci/azure/cleanup_win10.yml
+
 - job: all_macOS
   displayName: 'all tests (Safari Technology Preview)'
   condition: eq(variables['Build.Reason'], 'Schedule')
   strategy:
     parallel: 4 # chosen to make runtime ~2h
   timeoutInMinutes: 360
   pool:
     vmImage: 'macOS-10.13'
@@ -146,17 +204,16 @@ jobs:
   - template: tools/ci/azure/update_hosts.yml
   - template: tools/ci/azure/update_manifest.yml
   - script: no_proxy='*' ./wpt run --no-manifest-update --no-restart-on-unexpected --no-fail-on-unexpected --this-chunk=$(System.JobPositionInPhase) --total-chunks=$(System.TotalJobsInPhase) --chunk-type hash --log-wptreport $(Build.ArtifactStagingDirectory)/wpt_report_$(System.JobPositionInPhase).json --channel preview safari
     displayName: 'Run tests'
   - task: PublishBuildArtifacts@1
     displayName: 'Publish results'
     inputs:
       artifactName: 'results'
-    condition: succeededOrFailed()
 
 # The InvokeRESTAPI task can only run in a server job.
 - job: all_post
   displayName: 'all tests (wpt.fyi hook)'
   dependsOn: all_macOS
   pool: server
   steps:
   - task: InvokeRESTAPI@1
--- a/testing/web-platform/tests/animation-worklet/worklet-animation-with-fill-mode.https.html
+++ b/testing/web-platform/tests/animation-worklet/worklet-animation-with-fill-mode.https.html
@@ -9,88 +9,151 @@
 <style>
 .target {
   width: 100px;
   height: 100px;
   background-color: green;
 }
 </style>
 
-<script>
-function CreateTest(target, effect, verify, test_name) {
-  promise_test(async function() {
-    await registerConstantLocalTimeAnimator(2000);
-    const animation = new WorkletAnimation('constant_time', effect);
-    animation.play();
-
-    await waitForAsyncAnimationFrames(1);
-    // waitTwoAnimationFrames guarantees a compositor frame that could update
-    // the opacity value in the worklet. Meanwhile, getComputedStyle needs an
-    // extra frame to fetch the updated value.
-    await waitForNextFrame();
-    verify();
-    animation.cancel();
-  }, test_name);
-}
-</script>
-
-<div id="target1" class='target'></div>
-<div id="target2" class='target'></div>
-<div id="target3" class='target'></div>
-<div id="target4" class='target'></div>
-<div id="target5" class='target'></div>
-<div id="target6" class='target'></div>
+<div id="target" class='target'></div>
 
 <script>
-  const effect_with_fill_forwards = new KeyframeEffect(
-      target1,
-      { opacity: [0.5, 0] },
-      { duration: 1000, fill: 'forwards' });
-  CreateTest(target1,
-      effect_with_fill_forwards,
-      function() { assert_equals(getComputedStyle(target1).opacity, '0'); },
-      "Effect with fill mode forwards in after phase produces output that is equivalent to effect's end value.");
+setup(setupAndRegisterTests, {explicit_done: true});
+
+function setupAndRegisterTests() {
+  registerConstantLocalTimeAnimator(2000).then(() => {
+    promise_test(
+        effect_with_fill_mode_forwards,
+        "Effect with fill mode forwards in after phase produces output that is equivalent to effect's end value.");
+
+    promise_test(
+        effect_without_fill_mode_forwards,
+        'Effect without fill mode forwards in after phase (local time beyond end) should deactivate the animation.');
+
+    promise_test(
+        effect_without_fill_forwards_at_end,
+        'Effect without fill mode in after phase (local time at end) should deactivate the animation.');
+
+    promise_test(
+        effect_with_fill_backwards,
+        "Effect with fill mode backwards in before phase produces output that is equivalent to effect's start value.");
+
+    promise_test(
+        effect_without_fill_backwards,
+        'Effect without fill mode backwards in before phase (local time before start) should deactivate the animation.');
+
+    promise_test(
+        effect_without_fill_backwards_at_start,
+        'Effect with local time at start point is in active phase.');
+
+    done();
+  });
+}
 
-  const effect_without_fill_forwards = new KeyframeEffect(
-      target2,
-      { opacity: [0.5, 0] },
-      { duration: 1000 });
-  CreateTest(target2,
-      effect_without_fill_forwards,
-      function() { assert_equals(getComputedStyle(target2).opacity, '1'); },
-      'Effect without fill mode forwards in after phase (local time beyond end) should deactivate the animation.');
+async function effect_with_fill_mode_forwards(t) {
+      const effect_with_fill_forwards = new KeyframeEffect(
+          target,
+          { opacity: [0.5, 0] },
+          { duration: 1000, fill: 'forwards' });
+      const animation = new WorkletAnimation(
+          'constant_time',
+          effect_with_fill_forwards);
+      animation.play();
+
+      await waitForAsyncAnimationFrames(1);
+      await waitForNextFrame();
+
+      assert_equals(getComputedStyle(target).opacity, '0');
+
+      animation.cancel();
+}
 
-  const effect_without_fill_forwards_at_end = new KeyframeEffect(
-      target3,
-      { opacity: [0.5, 0] },
-      { duration: 2000 });
-  CreateTest(target3,
-      effect_without_fill_forwards_at_end,
-      function() { assert_equals(getComputedStyle(target3).opacity, '1'); },
-      'Effect without fill mode in after phase (local time at end) should deactivate the animation.');
+async function effect_without_fill_mode_forwards(t) {
+      const effect_without_fill_forwards = new KeyframeEffect(
+          target,
+          { opacity: [0.5, 0] },
+          { duration: 1000 });
+      const animation = new WorkletAnimation(
+          'constant_time',
+          effect_without_fill_forwards);
+      animation.play();
+
+      await waitForAsyncAnimationFrames(1);
+      await waitForNextFrame();
+
+      assert_equals(getComputedStyle(target).opacity, '1');
+
+      animation.cancel();
+}
 
-  const effect_with_fill_backwards = new KeyframeEffect(
-      target4,
-      { opacity: [0.5, 0] },
-      { duration: 1000, delay: 2001, fill: 'backwards' });
-  CreateTest(target4,
-      effect_with_fill_backwards,
-      function() { assert_equals(getComputedStyle(target4).opacity, '0.5'); },
-      "Effect with fill mode backwards in before phase produces output that is equivalent to effect's start value.");
+async function effect_without_fill_forwards_at_end(t) {
+      const effect_without_fill_forwards_at_end = new KeyframeEffect(
+          target,
+          { opacity: [0.5, 0] },
+          { duration: 2000 });
+      const animation = new WorkletAnimation(
+          'constant_time',
+          effect_without_fill_forwards_at_end);
+      animation.play();
+
+      await waitForAsyncAnimationFrames(1);
+      await waitForNextFrame();
+
+      assert_equals(getComputedStyle(target).opacity, '1');
+
+      animation.cancel();
+}
+
+async function effect_with_fill_backwards(t) {
+      const effect_with_fill_backwards = new KeyframeEffect(
+          target,
+          { opacity: [0.5, 0] },
+          { duration: 1000, delay: 2001, fill: 'backwards' });
+      const animation = new WorkletAnimation(
+          'constant_time',
+          effect_with_fill_backwards);
+      animation.play();
+
+      await waitForAsyncAnimationFrames(1);
+      await waitForNextFrame();
+
+      assert_equals(getComputedStyle(target).opacity, '0.5');
+
+      animation.cancel();
+}
 
-  const effect_without_fill_backwards = new KeyframeEffect(
-      target5,
-      { opacity: [0.5, 0] },
-      { duration: 1000, delay: 2001 });
-  CreateTest(target5,
-      effect_without_fill_backwards,
-      function() { assert_equals(getComputedStyle(target5).opacity, '1'); },
-      'Effect without fill mode backwards in before phase (local time before start) should deactivate the animation.');
+async function effect_without_fill_backwards(t) {
+      const effect_without_fill_backwards = new KeyframeEffect(
+          target,
+          { opacity: [0.5, 0] },
+          { duration: 1000, delay: 2001 });
+      const animation = new WorkletAnimation(
+          'constant_time',
+          effect_without_fill_backwards);
+      animation.play();
+
+      await waitForAsyncAnimationFrames(1);
+      await waitForNextFrame();
+
+      assert_equals(getComputedStyle(target).opacity, '1');
+
+      animation.cancel();
+}
 
-  const effect_without_fill_backwards_at_start = new KeyframeEffect(
-      target6,
-      { opacity: [0.5, 0] },
-      { duration: 1000, delay: 2000 });
-  CreateTest(target6,
-      effect_without_fill_backwards_at_start,
-      function() { assert_equals(getComputedStyle(target6).opacity, '0.5'); },
-      'Effect with local time at start point is in active phase.');
+async function effect_without_fill_backwards_at_start(t) {
+      const effect_without_fill_backwards_at_start = new KeyframeEffect(
+          target,
+          { opacity: [0.5, 0] },
+          { duration: 1000, delay: 2000 });
+      const animation = new WorkletAnimation(
+          'constant_time',
+          effect_without_fill_backwards_at_start);
+      animation.play();
+
+      await waitForAsyncAnimationFrames(1);
+      await waitForNextFrame();
+
+      assert_equals(getComputedStyle(target).opacity, '0.5');
+
+      animation.cancel();
+}
 </script>
--- a/testing/web-platform/tests/content-security-policy/navigation/to-javascript-parent-initiated-child-csp.html
+++ b/testing/web-platform/tests/content-security-policy/navigation/to-javascript-parent-initiated-child-csp.html
@@ -3,16 +3,18 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 </head>
 <body>
 <iframe src="support/frame-with-csp.sub.html?csp=script-src%20%27self%27"></iframe>
 <div onclick="frames[0].location.href = 'javascript:parent.postMessage(\'executed\', \'*\')'" id="special_div"></div>
 <script>
   var t = async_test("Should have executed the javascript url");
-  window.onmessage = t.step_func(function(e) {
-    if (e.data == "executed")
-      t.done();
+  frames[0].addEventListener('load', () => {
+    window.onmessage = t.step_func(function(e) {
+      if (e.data == "executed")
+        t.done();
+    });
+    window.addEventListener('securitypolicyviolation', t.unreached_func("Should not have raised a violation event"));
+    document.getElementById('special_div').click();
   });
-  window.addEventListener('securitypolicyviolation', t.unreached_func("Should not have raised a violation event"));
-  document.getElementById('special_div').click();
 </script>
 </body>
--- a/testing/web-platform/tests/content-security-policy/navigation/to-javascript-parent-initiated-parent-csp.html
+++ b/testing/web-platform/tests/content-security-policy/navigation/to-javascript-parent-initiated-parent-csp.html
@@ -4,19 +4,21 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 </head>
 <body>
 <iframe src="support/frame-with-csp.sub.html"></iframe>
 <div onclick="frames[0].location.href = 'javascript:parent.postMessage(\'executed\', \'*\')'" id="special_div"></div>
 <script nonce='abc'>
   var t = async_test("Should not have executed the javascript url");
-  window.onmessage = t.step_func(function(e) {
-    if (e.data == "executed")
-      assert_true(false, "Javascript url executed");
+  frames[0].addEventListener('load', () => {
+    window.onmessage = t.step_func(function(e) {
+      if (e.data == "executed")
+        assert_true(false, "Javascript url executed");
+    });
+    window.addEventListener('securitypolicyviolation', t.step_func_done(function(e) {
+      assert_equals(e.blockedURI, 'inline');
+      assert_equals(e.violatedDirective, 'script-src-attr');
+    }));
+    document.getElementById('special_div').click();
   });
-  window.addEventListener('securitypolicyviolation', t.step_func_done(function(e) {
-    assert_equals(e.blockedURI, 'inline');
-    assert_equals(e.violatedDirective, 'script-src-attr');
-  }));
-  document.getElementById('special_div').click();
 </script>
 </body>
--- a/testing/web-platform/tests/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html
+++ b/testing/web-platform/tests/css/CSS2/abspos/abspos-in-block-in-inline-in-relpos-inline.html
@@ -1,33 +1,41 @@
 <!DOCTYPE html>
 <link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
 <link rel="help" href="https://www.w3.org/TR/CSS22/visudet.html#containing-block-details">
 <link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#anonymous-block-level">
 <style>
+  body { margin: 0px;}
   .rel { position:relative; }
   .inline-block { display:inline-block; width:100px; height:1px; }
   .inline-block.large { width:200px; }
   #target { position:absolute; width:100%; height:100px; background:green; }
+  #target-fixed { position:fixed; width:100%; height:100px; background:yellow; }
 </style>
-<p>There should be a green square below.</p>
+<p>There should be a green square, and a yellow rectangle below.</p>
 <div style="height:200px;">
   <span class="rel" id="notContainingBlockOfTarget">
     <div class="large inline-block"></div>
     <br>
     <span id="containingBlockOfTarget" class="rel">
       <div class="inline-block"></div>
       <span>
         <div>
+          <div id="target-fixed"></div>
           <div id="target"></div>
         </div>
       </span>
       <div class="inline-block"></div></span><br>
     <div class="large inline-block"></div>
   </span>
 </div>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
   test(()=> {
-      assert_equals(document.getElementById("target").offsetWidth, 100);
-  }, "Make sure that we're sized by the right ancestor");
+    assert_equals(document.getElementById("target").offsetWidth,
+      document.querySelector("#containingBlockOfTarget").offsetWidth);
+  }, "position:absolute should be sized by the right ancestor");
+  test(()=> {
+    assert_equals(document.getElementById("target-fixed").offsetWidth,
+      document.body.offsetWidth);
+  }, "position:fixed should be sized by the right ancestor");
 </script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-backgrounds/child-move-reveals-parent-background-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<style>
+  #parent {
+    width: 150px;
+    height: 150px;
+    background-color: green;
+  }
+</style>
+<p>There should be a green square below.</p>
+<div id="parent"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-backgrounds/child-move-reveals-parent-background.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Child moves and reveals previously obscured background of the parent</title>
+<link rel="match" href="child-move-reveals-parent-background-ref.html">
+<link rel="help" href="https://drafts.csswg.org/css-backgrounds">
+<script src="/common/reftest-wait.js"></script>
+<style>
+  #parent {
+    width: 150px;
+    height: 150px;
+    background-color: green;
+  }
+  #child {
+    width: 150px;
+    height: 150px;
+    background-color: white;
+    position: relative;
+  }
+</style>
+<p>There should be a green square below.</p>
+<div id="parent">
+  <div id="child"></div>
+</div>
+<script>
+  requestAnimationFrame(() => requestAnimationFrame(() => {
+    child.style.left = '150px';
+    takeScreenshot();
+  }));
+</script>
--- a/testing/web-platform/tests/css/css-env/supports-script.tentative.html
+++ b/testing/web-platform/tests/css/css-env/supports-script.tentative.html
@@ -6,14 +6,16 @@
     <script src="/resources/testharness.js"></script>
     <script src="/resources/testharnessreport.js"></script>
   </head>
   <body>
     <script>
     test(() => {
       assert_true(CSS.supports("background: env(test)"));
       assert_true(CSS.supports("background", "env(test)"));
+      assert_true(CSS.supports("background", "env(test, 10px)"));
+      assert_true(CSS.supports("background", "foobar(env(test))"));
       assert_false(CSS.supports("background", "env()"));
       assert_false(CSS.supports("background", "env(test,)"));
     });
     </script>
   </body>
 </html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-flexbox/flex-minimum-height-flex-items-012.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>CSS Flexbox: Combining 100% heights with min-height: auto should not lead to overflow</title>
+<link rel="author" title="Google LLC" href="https://www.google.com/" />
+<link rel="help" href="https://drafts.csswg.org/css-flexbox/#min-size-auto" />
+<link rel="issue" href="https://bugs.chromium.org/p/chromium/issues/detail?id=927066" />
+
+<style>
+.flexbox {
+    display: flex;
+}
+
+.column {
+    flex-flow: column;
+}
+
+.flexbox span {
+    height: 100%;
+    background: orange;
+    display: block;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<body onload="checkLayout('.flexbox')">
+<div id=log></div>
+
+<div class="flexbox column" style="height: 100px; width: 100px; background: green">
+    <div style="height: 10px; flex: 0.1;" data-expected-height="10"></div>
+    <div style="height: 100%; display: flex; background: teal; flex: 0.9;" data-expected-height="90">
+        <div style="height: 100%"></div>
+    </div>
+</div>
+
+</body>
+</html>
--- a/testing/web-platform/tests/css/css-font-loading/idlharness.https.html
+++ b/testing/web-platform/tests/css/css-font-loading/idlharness.https.html
@@ -9,15 +9,20 @@
 'use strict';
 
 idl_test(
   ['css-font-loading'],
   ['dom', 'html', 'cssom'],
   idl_array => {
     idl_array.add_objects({
       Document: ['document'],
-      FontFace: ['new FontFace("family", "src")'],
-      FontFaceSetLoadEvent: ['new FontFaceSetLoadEvent("type")'],
+      FontFace: ['fontFace'],
+      FontFaceSetLoadEvent: ['fontFaceSetLoadEvent'],
       FontFaceSet: ['document.fonts'],
     });
+    self.fontFace = new FontFace("family", "src");
+    // The `fontFace.loaded` promise will be rejected, so handle that to
+    // avoid an unhandled promise rejection manifesting as a harness error.
+    self.fontFace.loaded.catch(() => {});
+    self.fontFaceSetLoadEvent = new FontFaceSetLoadEvent("type");
   }
 );
 </script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-grid/grid-model/grid-button-001.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Grid items work inside a button</title>
+<meta name="assert" content="When a button is set to display: grid, its children should flow into its grid cells">
+<link rel="author" title="Bryan Robinson" href="bryanlrobinson@gmail.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid-1/#grid-containers">
+<style>
+  .grid { display: grid; grid-template-columns: 100px 200px; border: 2px solid purple; box-sizing: border-box; }
+  span { border: 1px dashed green; box-sizing: border-box; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+
+<button class="grid" ><span class="item1" data-expected-width="100">item 1</span> <span class="item2" data-expected-width="200">item 2</span></button>
+
+<script>
+  checkLayout("[data-expected-width]")
+</script>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-grid/layout-algorithm/grid-fit-content-percentage.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: indefinite percentage in fit-content()</title>
+<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid/#track-sizes" title="7.2.1. Track Sizes">
+<meta name="assert" content="Checks that an indefinite percentage in fit-content lets the grid container grow enough to contain the max-content contribution of its grid items.">
+<style>
+.container {
+  width: 200px;
+  margin-top: 10px;
+}
+.grid {
+  display: inline-grid;
+  background: blue;
+}
+.item {
+  background: orange;
+}
+.item::before, .item::after {
+  content: '';
+  float: left;
+  width: 50px;
+  height: 50px;
+}
+</style>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="log"></div>
+
+<script>
+"use strict";
+function clamp(value, min, max) {
+  return Math.max(min, Math.min(max, value));
+}
+const minContent = 50;
+const maxContent = 100;
+for (const percentage of [0, 50, 75, 100, 150]) {
+  const container = document.createElement("div");
+  container.className = "container";
+  document.body.appendChild(container);
+  const grid = document.createElement("div");
+  grid.className = "grid";
+  grid.style.gridTemplateColumns = `fit-content(${percentage}%)`;
+  container.appendChild(grid);
+  const item = document.createElement("div");
+  item.className = "item";
+  grid.appendChild(item);
+  test(function() {
+    const colSize = clamp(percentage * maxContent / 100, minContent, maxContent);
+    const height = colSize < maxContent ? maxContent : minContent;
+    assert_equals(item.offsetWidth, colSize, "Grid item width");
+    assert_equals(item.offsetHeight, height, "Grid item height");
+    assert_equals(grid.offsetWidth, maxContent, "Grid container width");
+    assert_equals(grid.offsetHeight, height, "Grid container height");
+    assert_equals(getComputedStyle(grid).gridTemplateColumns, colSize + "px",
+                  "Grid column size");
+  }, `fit-content(${percentage}%)`);
+}
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-position/position-absolute-crash-chrome-001.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<html>
+<head>
+  <title>Chrome crash with inline </title>
+  <link rel="help" href="https://www.w3.org/TR/css-position-3/#def-cb">
+  <link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=928224">
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+  <script>test(()=>{})</script>
+<style>
+  a {
+    position: relative;
+  }
+  a:before {
+    content: "foo";
+    position: absolute;
+    background: green;
+  }
+</style>
+</head>
+<body>
+  <div>
+    <li>
+      <a href="dummy">success if does not crash</a>
+    </li>
+  </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-sizing/block-image-percentage-max-height-inside-inline.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-sizing-3/#max-size-properties">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width:100px; height:100px; background:red;">
+  <span>
+    <!-- The image is a 1x1 transparent one. -->
+    <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" style="display:block; max-width:100px; height:1000px; max-height:100%; background:green;">
+  </span>
+</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-sizing/image-percentage-max-height-in-anonymous-block.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-sizing-3/#max-size-properties">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width:100px; height:100px; background:red;">
+  <div></div>
+  <!-- The image is a 1x1 transparent one. -->
+  <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" style="max-width:100px; height:1000px; max-height:100%; background:green;">
+</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-sizing/table-percentage-max-width-beside-float.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-sizing/#available">
+<link rel="help" href="https://drafts.csswg.org/css-sizing/#percentage-sizing">
+<p>There should be a green square below, and no red.</p>
+<div id="container" style="width:100px; background:red;">
+  <div style="float:right; width:50px; height:100px; background:green;"></div>
+  <div style="display:table; max-width:50%; height:100px; background:green;" data-expected-width="50">
+    <div style="float:left; width:20px; height:10px;"></div>
+    <div style="float:left; width:20px; height:10px;"></div>
+    <div style="float:left; width:20px; height:10px;"></div>
+  </div>
+</div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<script>
+  checkLayout("#container");
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-sizing/table-percentage-min-width-below-float.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-sizing/#available">
+<link rel="help" href="https://drafts.csswg.org/css-sizing/#percentage-sizing">
+<p>There should be a blue square below.</p>
+<div id="container" style="width:100px;">
+  <div style="float:right; width:50px; height:10px;"></div>
+  <div style="display:table; width:10px; min-width:100%; height:100px; background:blue;" data-expected-width="100"></div>
+</div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<script>
+  checkLayout("#container");
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-sizing/table-percentage-min-width-beside-float.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-sizing/#available">
+<link rel="help" href="https://drafts.csswg.org/css-sizing/#percentage-sizing">
+<p>There should be a green square below, and no red.</p>
+<div id="container" style="width:100px; background:red;">
+  <div style="float:right; width:50px; height:100px; background:green;"></div>
+  <div style="display:table; width:10px; min-width:50%; height:100px; background:green;" data-expected-width="50"></div>
+</div>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<script>
+  checkLayout("#container");
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-syntax/urange-parsing.html
@@ -0,0 +1,173 @@
+<!doctype html>
+<title>Urange Parsing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+
+@font-face {
+    font-family: foo;
+    src: url(http://example.com);
+}
+
+.error {}
+
+</style>
+
+<meta name=author title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#urange-syntax">
+
+<script>
+
+function testUrange(input, expected) {
+    test(()=>{
+        const rule = document.styleSheets[0].cssRules[0];
+        rule.style.unicodeRange = "U+1357";
+        rule.style.unicodeRange = input;
+        assert_equals(rule.style.unicodeRange.toUpperCase(), expected.toUpperCase());
+    }, `"${input}" => "${expected}"`)
+}
+function testInvalidUrange(input) {
+    test(()=>{
+        const rule = document.styleSheets[0].cssRules[0];
+        rule.style.unicodeRange = "U+1357";
+        rule.style.unicodeRange = input;
+        assert_equals(rule.style.unicodeRange.toUpperCase(), "U+1357");
+    }, `"${input}" is invalid`);
+}
+
+/* First exercise all the clauses individually */
+//<urange> =
+//  u '+' <ident-token> '?'* |
+/* comments can go between tokens */
+testUrange("u/**/+/**/a/**/?", "U+A0-AF");
+/* capitalization doesn't matter */
+testUrange("u+abc", "U+ABC");
+testUrange("U+abc", "U+ABC");
+testUrange("u+ABC", "U+ABC");
+testUrange("U+ABC", "U+ABC");
+testUrange("u+AbC", "U+ABC");
+/* only hex */
+testInvalidUrange("u+efg");
+/* no spacing */
+testInvalidUrange("u+ abc");
+testInvalidUrange("u +abc");
+testInvalidUrange("u + abc");
+testInvalidUrange("U + a b c");
+/* 1-6 characters */
+testUrange("u+a", "U+A");
+testUrange("u+aa", "U+AA");
+testUrange("u+aaa", "U+AAA");
+testUrange("u+aaaa", "U+AAAA");
+testUrange("u+aaaaa", "U+AAAAA");
+testInvalidUrange("u+aaaaaaa");
+/* Or ? at the end, still up to 6 */
+testUrange("u+a?", "U+A0-AF");
+testUrange("u+a??", "U+A00-AFF");
+testUrange("u+a???", "U+A000-AFFF");
+testUrange("u+a????", "U+A0000-AFFFF");
+testInvalidUrange("u+aaaaaa?");
+testInvalidUrange("u+aaaaa??");
+testInvalidUrange("u+aaaa???");
+testInvalidUrange("u+aaa????");
+testInvalidUrange("u+aa?????");
+testInvalidUrange("u+a??????");
+/* no characters after ? */
+testInvalidUrange("u+a?a");
+// Too large!
+testInvalidUrange("u+aaaaaa");
+testInvalidUrange("u+a?????");
+
+//  u <dimension-token> '?'* |
+testUrange("u/**/+0a/**/?", "U+A0-AF");
+testUrange("u+0a", "U+A");
+testUrange("U+0a0", "U+A0");
+testUrange("u+0aaaaa", "U+AAAAA");
+testInvalidUrange("u+0aaaaaa");
+testUrange("u+0a0000", "U+A0000");
+testInvalidUrange("u+0a00000");
+testInvalidUrange("u+0aaaaa0");
+testUrange("u+00000a", "U+A");
+testInvalidUrange("u+00000aa");
+testInvalidUrange("u+00000a0")
+testInvalidUrange("u+000000a");
+testUrange("u+0a????", "U+A0000-AFFFF");
+testInvalidUrange("u+0a?????");
+testInvalidUrange("u+00a????");
+// Too large!
+testInvalidUrange("u+22222a");
+// Scinot!
+testUrange("u+1e9a", "U+1E9A");
+
+//  u <number-token> '?'* |
+testUrange("u/**/+0/**/?", "U+0-F");
+testInvalidUrange("u/**/0");
+testUrange("u+0", "U+0");
+testUrange("u+00", "U+0");
+testUrange("u+000", "U+0");
+testUrange("u+0000", "U+0");
+testUrange("u+00000", "U+0");
+testUrange("u+000000", "U+0");
+testInvalidUrange("u+0000000");
+testUrange("u+00000?", "U+0-F");
+testUrange("u+0?????", "U+0-FFFFF");
+testInvalidUrange("u+0?a");
+testInvalidUrange("u+000000?");
+testInvalidUrange("u+00000??");
+testInvalidUrange("u+0??????");
+// Scinot!
+testUrange("u+1e3", "U+1E3");
+testUrange("u+1e-20", "U+1E-20");
+// Too large!
+testInvalidUrange("u+222222");
+testInvalidUrange("u+2?????");
+
+//  u <number-token> <dimension-token> |
+testUrange("u/**/+0/**/-0a", "U+0-A");
+testUrange("u+0-0a", "U+0-A");
+testUrange("u+000000-0aaaaa", "U+0-AAAAA");
+testInvalidUrange("u+0000000-0a");
+testInvalidUrange("u+0-0aaaaaa");
+testInvalidUrange("u+0-000000a");
+testInvalidUrange("u+0+0a");
+testInvalidUrange("u+0?-0a");
+testInvalidUrange("u+0-0a?");
+// Too large!
+testInvalidUrange("u+222222-22222a");
+
+//  u <number-token> <number-token> |
+testUrange("u/**/+0/**/-1", "U+0-1");
+testUrange("u+0-1", "U+0-1");
+testInvalidUrange("u-0-1");
+testInvalidUrange("u-0+1");
+testInvalidUrange("u+0+1");
+testUrange("u+000000-000001", "U+0-1");
+testInvalidUrange("u+0000000-1");
+testInvalidUrange("u+0-0000001");
+// Too large!
+testInvalidUrange("u+0-222222");
+
+//  u '+' '?'+
+testUrange("u/**/+/**/?", "U+0-F");
+testUrange("u+?", "U+0-F");
+testUrange("u+?????", "u+0-FFFFF");
+testInvalidUrange("u+???????");
+testInvalidUrange("u+?a");
+// U+FFFFFF is too large!
+testInvalidUrange("u+??????");
+
+
+/* Finally, verify that u+a is properly parsed
+   as IDENT(u) DELIM(+) IDENT(a) in other contexts */
+
+test(()=>{
+    const rule = document.styleSheets[0].cssRules[1];
+    // Establish that it works with whitespace...
+    rule.selectorText = "u + a";
+    assert_equals(rule.selectorText, "u + a");
+    // And then again without...
+    rule.selectorText = ".error";
+    rule.selectorText = "u+a";
+    assert_equals(rule.selectorText, "u + a");
+}, "u+a is a valid selector");
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-tables/subpixel-table-cell-height-001-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<style>
+div {
+  border: 1px solid blue;
+  width: 120px;
+  height: 37.4px;
+}
+</style>
+
+<div></div>
+<div></div>
+<div></div>
+<div></div>
+<div></div>
+<div></div>
+<div></div>
+<div></div>
+<div></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-tables/subpixel-table-cell-height-001.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-values-3/#calc-notation">
+<link rel="match" href="subpixel-table-cell-height-001-ref.html">
+<meta name="flags" content="" />
+<meta name="assert" content="When a cell has a specified calc height and a block box has the same specified calc height, their actual heights should match." />
+
+<style>
+td {
+  border: 1px solid blue;
+  width: 120px;
+  height: 37.4px;
+  padding: 0px;
+}
+</style>
+
+<table style="border-spacing:0;">
+  <tr>
+    <td></td>
+  </tr>
+  <tr>
+    <td></td>
+  </tr>
+  <tr>
+    <td></td>
+  </tr>
+  <tr>
+    <td></td>
+  </tr>
+  <tr>
+    <td></td>
+  </tr>
+  <tr>
+    <td></td>
+  </tr>
+  <tr>
+    <td></td>
+  </tr>
+  <tr>
+    <td></td>
+  </tr>
+  <tr>
+    <td></td>
+  </tr>
+</table>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-tables/subpixel-table-cell-width-001-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<style>
+  div {
+    font-size: 0; /* so I can leave spaces between the child divs */
+    height: 20px;
+  }
+  div > div {
+    display: inline-block;
+  }
+  div > div:first-child {
+    background: blue;
+  }
+  div > div:nth-child(2) {
+    background: lime;
+  }
+</style>
+
+<div>
+  <div style="width:3.6px;"></div>
+  <div style="width:3.6px;"></div>
+</div>
+
+<br><br>
+
+<div>
+  <div style="width:3.3px;"></div>
+  <div style="width:3.3px;"></div>
+</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-tables/subpixel-table-cell-width-001.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<link rel="author" title="David Grogan" href="dgrogan@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/CSS21/cascade.html#value-stages">
+<link rel="match" href="subpixel-table-cell-width-001-ref.html">
+<meta name="flags" content="" />
+<meta name="assert" content="When a cell has a specified fractional fixed width and a block has the same specified fractional width, their actual widths should match." />
+
+<style>
+.table {
+  display: table;
+  height: 20px;
+  background: red;
+}
+.cell {
+  display: table-cell;
+}
+div > div:first-child {
+  background: blue;
+}
+div > div:nth-child(2) {
+  background: lime;
+}
+</style>
+
+<div class=table>
+  <div class=cell style="width:3.6px;"></div>
+  <div class=cell style="width:3.6px;"></div>
+</div>
+
+<br><br>
+
+<div class=table>
+  <div class=cell style="width:3.3px;"></div>
+  <div class=cell style="width:3.3px;"></div>
+</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-tables/subpixel-table-cell-width-002.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<link rel="author" title="David Grogan" href="dgrogan@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/CSS21/cascade.html#value-stages">
+<link rel="match" href="subpixel-table-cell-width-001-ref.html">
+<meta name="flags" content="" />
+<meta name="assert" content="When a cell has a specified percent width that results in a fractional used width, the cell's actual width should match that of a block whose specified fixed width is the cell's used width" />
+
+<style>
+.table {
+  display: table;
+  height: 20px;
+  background: red;
+}
+.cell {
+  display: table-cell;
+}
+div > div:first-child {
+  background: blue;
+}
+div > div:nth-child(2) {
+  background: lime;
+}
+</style>
+
+
+<div class=table style="width:7.2px;">
+  <div class=cell style="width:50%;"></div>
+  <div class=cell style="width:50%;"></div>
+</div>
+
+<br><br>
+
+<div class=table style="width:6.6px;">
+  <div class=cell style="width:50%;"></div>
+  <div class=cell style="width:50%;"></div>
+</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-tables/subpixel-table-width-001-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<style>
+.parent div {
+  background: #aaa;
+  width: 100%;
+  height: 100px;
+}
+</style>
+
+There should be two grey ~squares with no red showing.
+
+<div class="parent" style="width:100.2px">
+  <div></div>
+</div>
+
+<div class="parent" style="width:100.8px">
+  <div></div>
+</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-tables/subpixel-table-width-001.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/CSS22/syndata.html#value-def-percentage">
+<link rel="match" href="subpixel-table-width-001-ref.html">
+<meta name="flags" content="" />
+<meta name="assert" content="A table with width:100% has same actual width as its parent's actual width." />
+
+<style>
+.parent {
+  background: red;
+}
+
+.parent table {
+  background: #aaa;
+  width: 100%;
+  height: 100px;
+}
+</style>
+
+There should be two grey ~squares with no red showing.
+
+<div class="parent" style="width:100.2px">
+  <table></table>
+</div>
+
+<div class="parent" style="width:100.8px">
+  <table></table>
+</div>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cj-loose.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cj-loose.html
@@ -84,27 +84,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if ja and loose');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if ja and loose');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cj-normal.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cj-normal.html
@@ -84,27 +84,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if ja and normal');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if ja and normal');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cj-strict.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cj-strict.html
@@ -84,27 +84,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if ja and strict');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if ja and strict');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cpm-loose.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cpm-loose.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if ja and loose');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if ja and loose');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cpm-normal.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cpm-normal.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if ja and normal');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if ja and normal');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cpm-strict.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-cpm-strict.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if ja and strict');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if ja and strict');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-hyphens-loose.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-hyphens-loose.html
@@ -37,27 +37,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if ja and loose');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if ja and loose');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-hyphens-normal.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-hyphens-normal.html
@@ -37,27 +37,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if ja and normal');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if ja and normal');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-hyphens-strict.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-hyphens-strict.html
@@ -37,27 +37,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if ja and strict');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if ja and strict');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-in-loose.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-in-loose.html
@@ -38,27 +38,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if ja and loose');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if ja and loose');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-in-normal.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-in-normal.html
@@ -38,27 +38,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if ja and normal');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if ja and normal');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-in-strict.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-in-strict.html
@@ -38,27 +38,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if ja and strict');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if ja and strict');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-iteration-loose.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-iteration-loose.html
@@ -39,27 +39,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if ja and loose');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if ja and loose');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-iteration-normal.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-iteration-normal.html
@@ -39,27 +39,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if ja and normal');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if ja and normal');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-iteration-strict.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-iteration-strict.html
@@ -39,27 +39,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if ja and strict');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if ja and strict');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-po-loose.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-po-loose.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if ja and loose');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if ja and loose');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-po-normal.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-po-normal.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if ja and normal');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if ja and normal');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-po-strict.html
+++ b/testing/web-platform/tests/css/css-text/i18n/ja/css-text-line-break-ja-po-strict.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="ja">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="ja">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if ja and strict');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if ja and strict');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-cpm-loose.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-cpm-loose.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if zh and loose');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if zh and loose');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-cpm-normal.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-cpm-normal.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if zh and normal');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if zh and normal');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-cpm-strict.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-cpm-strict.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if zh and strict');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if zh and strict');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-hyphens-loose.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-hyphens-loose.html
@@ -37,27 +37,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if zh and loose');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if zh and loose');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-hyphens-normal.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-hyphens-normal.html
@@ -37,27 +37,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if zh and normal');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if zh and normal');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-hyphens-strict.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-hyphens-strict.html
@@ -37,27 +37,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if zh and strict');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if zh and strict');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-in-loose.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-in-loose.html
@@ -38,27 +38,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if zh and loose');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if zh and loose');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-in-normal.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-in-normal.html
@@ -38,27 +38,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if zh and normal');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if zh and normal');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-in-strict.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-in-strict.html
@@ -38,27 +38,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if zh and strict');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if zh and strict');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-iteration-loose.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-iteration-loose.html
@@ -39,27 +39,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if zh and loose');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if zh and loose');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-iteration-normal.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-iteration-normal.html
@@ -39,27 +39,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if zh and normal');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if zh and normal');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-iteration-strict.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-iteration-strict.html
@@ -39,27 +39,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if zh and strict');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if zh and strict');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-po-loose.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-po-loose.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文文<br/>&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may appear at line start if zh and loose');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may appear at line start if zh and loose');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-po-normal.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-po-normal.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if zh and normal');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if zh and normal');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-po-strict.html
+++ b/testing/web-platform/tests/css/css-text/i18n/zh/css-text-line-break-zh-po-strict.html
@@ -43,27 +43,36 @@ for (var i=0;i<lines.length;i++) {
 	var hex = lines[i].substr(0,firstSpace)
 	var name = lines[i].substr(firstSpace)
 	// make a test
 	out +=  '<div class="wrapper"><div>'+hex+'</div>' +
 	'<div class="test" id="test'+i+'" lang="zh">文文文文文文&#x'+hex+';字<span id="testSpan'+i+'">字</span></div>' +
 	 '<div class="ref" id="ref'+i+'" lang="zh">文文文文文<br/>文&#x'+hex+';字<span id="refSpan'+i+'">字</span></div>' +
 	 '</div>'
 	}
+function spansNearEnough(counter) {
+  return Math.abs( document.getElementById('testSpan'+counter).getBoundingClientRect().left
+           - document.getElementById('refSpan'+counter).getBoundingClientRect().left ) < 1;
+}
+
 document.querySelector('body').innerHTML = out
-// hide successful tests
-for (i=0;i<lines.length;i++) {
-    if (document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft) document.getElementById('test'+i).parentNode.style.display = 'none'
-    }
-// run the test framework
- for (i=0;i<lines.length;i++) {
-   test(function() {
-        assert_true(document.getElementById('testSpan'+i).offsetLeft === document.getElementById('refSpan'+i).offsetLeft);
-        }, lines[i]+' may NOT appear at line start if zh and strict');
-   }
+setup({explicit_done: true});
+
+document.fonts.ready.then(validate);
+
+function validate() {
+  for (i=0;i<lines.length;i++) {
+    test(function() {
+      assert_true(spansNearEnough(i));
+    }, lines[i]+' may NOT appear at line start if zh and strict');
+    // Hide successful tests.
+    if (spansNearEnough(i)) document.getElementById('test'+i).parentNode.style.display = 'none'
+  }
+  done();
+}
 </script>
 <!--Notes:
 The test creates a box with room for 6 characters, causing wrapping to occur either between the 6th and the 7th character, or before the 6th if the breaks after the 6th or before the 7th are prohibited.
 
 It also creates the expected behaviour with a ref instance, using <br/>. Each line ends with a span. The test then checks whether the left edge of the span is in the same place in test and ref instance.
 -->
 </body>
 </html>
--- a/testing/web-platform/tests/css/css-transforms/animation/list-interpolation.html
+++ b/testing/web-platform/tests/css/css-transforms/animation/list-interpolation.html
@@ -104,16 +104,34 @@ test_interpolation(
   },
   [{ at: 0.25, expect: 'rotateX(67.5deg) translate(75px, 50px)' }],
   'Match on rotation due to 0deg angle'
 );
 
 test_interpolation(
   {
     property: 'transform',
+    from: 'rotate3d(1, 1, 1, -60deg) translateX(100px)',
+    to: 'rotate3d(2, 2, 2, 60deg) translateY(200px)',
+  }, [{ at: 0.25, expect: 'rotate3d(1, 1, 1, -30deg) translate(75px, 50px)' }],
+  'Match on rotation using collinear rotation axes'
+);
+
+test_interpolation(
+  {
+    property: 'transform',
+    from: 'rotate3d(1, 0, 0, 360deg) translateX(100px)',
+    to: 'rotate3d(0, 1, 0, -720deg) translateY(200px)',
+  }, [{ at: 0.25, expect: 'rotate3d(0, 0, 1, 0deg) translate(75px, 50px)' }],
+  'Match on rotation with spherical interpolation'
+);
+
+test_interpolation(
+  {
+    property: 'transform',
     from: 'rotate(0deg) translate(100px)',
     to: 'rotate(720deg) scale(2) translate(200px)',
   },
   [{ at: 0.25, expect: 'rotate(180deg) matrix(1.25, 0, 0, 1.25, 175, 0)' }],
   'Common prefix'
 );
 
 test_interpolation(
--- a/testing/web-platform/tests/css/css-transforms/transform-2d-getComputedStyle-001.html
+++ b/testing/web-platform/tests/css/css-transforms/transform-2d-getComputedStyle-001.html
@@ -58,17 +58,25 @@
 	<div id="scale" class="block"></div>
 	<div id="scaleX" class="block"></div>
 	<div id="scaleY" class="block"></div>
 	<div id="skewX" class="block"></div>
 	<div id="skewY" class="block"></div>
 	<div id="matrix" class="block"></div>
     <script type="text/javascript">
     function getTransformFor(id) {
-    	return window.getComputedStyle(document.getElementById(id)).getPropertyValue("transform");
+      let transform =
+        window.getComputedStyle(document.getElementById(id)).getPropertyValue("transform");
+      // Round matrix arguments to allow for small errors in numerical precision.
+      transform = transform.replace(/matrix\(([^\)]*)\)/g, function(match, arguments) {
+        let parts = arguments.split(",");
+        parts = parts.map(str => parseFloat(parseFloat(str).toFixed(6)));
+        return 'matrix(' + parts.join(", ") + ')';
+      });
+      return transform;
     }
     function clear(id) {
     	document.getElementById(id).style.display = 'none';
     }
 
     test(function() {
     	assert_equals(getTransformFor("translate"), "matrix(1, 0, 0, 1, 10, 20)", "Incorrect matrix for translate()");
     	clear("translate");
--- a/testing/web-platform/tests/css/css-transitions/event-dispatch.tentative.html
+++ b/testing/web-platform/tests/css/css-transitions/event-dispatch.tentative.html
@@ -4,22 +4,30 @@
 <link rel="help" href="https://drafts.csswg.org/css-transitions-2/#event-dispatch">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="support/helper.js"></script>
 <div id="log"></div>
 <script>
 'use strict';
 
+// All transition events should be received on the next animation frame. If
+// two animation frames pass before receiving the expected events then we
+// can immediately fail the current test.
+const transitionEventsTimeout = () => {
+  return waitForAnimationFrames(2);
+};
+
 const setupTransition = (t, transitionStyle) => {
   const div = addDiv(t, { style: 'transition: ' + transitionStyle });
   const watcher = new EventWatcher(t, div, [ 'transitionrun',
                                              'transitionstart',
                                              'transitionend',
-                                             'transitioncancel' ]);
+                                             'transitioncancel' ],
+                                   transitionEventsTimeout);
   getComputedStyle(div).marginLeft;
 
   div.style.marginLeft = '100px';
   const transition = div.getAnimations()[0];
 
   return { transition, watcher, div };
 };
 
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/angle-units-001.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: invalid angle units</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-values-3/#angles">
+  <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+
+  <meta name="flags" content="invalid">
+
+  <style>
+  div
+    {
+      height: 100px;
+      width: 100px;
+    }
+
+  div#test-overlapping-green
+    {
+      background-image: linear-gradient(green, green);
+      background-image: linear-gradient(90degree, red, red);   /* invalid; 90deg is valid */
+      background-image: linear-gradient(100gradian, red, red); /* invalid; 100grad is valid */
+      background-image: linear-gradient(1.57radian, red, red); /* invalid; 1.57rad is valid */
+      background-image: linear-gradient(0.25turns, red, red);  /* invalid; 0.25turn is valid */
+    }
+
+  div#reference-overlapped-red
+    {
+      background-color: red;
+      bottom: 100px;
+      position: relative;
+      z-index: -1;
+    }
+  </style>
+
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.
+
+  <div id="test-overlapping-green"></div>
+
+  <div id="reference-overlapped-red"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/angle-units-002.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: degree angle unit with mixed case</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-values-3/#angles">
+  <link rel="help" href="https://www.w3.org/TR/CSS22/syndata.html#characters">
+  <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+
+  <meta content="This test checks that 'deg' angle unit is case-insensitive." name="assert">
+  <meta name="flags" content="">
+
+  <style>
+  div
+    {
+      height: 100px;
+      width: 100px;
+    }
+
+  div#test-overlapping-green
+    {
+      background-color: red;
+      background-image: linear-gradient(90DeG, green, green);
+    }
+
+  div#reference-overlapped-red
+    {
+      background-color: red;
+      bottom: 100px;
+      position: relative;
+      z-index: -1;
+    }
+  </style>
+
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.
+
+  <div id="test-overlapping-green"></div>
+
+  <div id="reference-overlapped-red"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/angle-units-003.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: grad angle unit with mixed case</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-values-3/#angles">
+  <link rel="help" href="https://www.w3.org/TR/CSS22/syndata.html#characters">
+  <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+
+  <meta content="This test checks that 'grad' angle unit is case-insensitive." name="assert">
+  <meta name="flags" content="">
+
+  <style>
+  div
+    {
+      height: 100px;
+      width: 100px;
+    }
+
+  div#test-overlapping-green
+    {
+      background-color: red;
+      background-image: linear-gradient(100gRaD, green, green);
+    }
+
+  div#reference-overlapped-red
+    {
+      background-color: red;
+      bottom: 100px;
+      position: relative;
+      z-index: -1;
+    }
+  </style>
+
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.
+
+  <div id="test-overlapping-green"></div>
+
+  <div id="reference-overlapped-red"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/angle-units-004.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: rad angle unit with mixed case</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-values-3/#angles">
+  <link rel="help" href="https://www.w3.org/TR/CSS22/syndata.html#characters">
+  <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+
+  <meta content="This test checks that 'rad' angle unit is case-insensitive." name="assert">
+  <meta name="flags" content="">
+
+  <style>
+  div
+    {
+      height: 100px;
+      width: 100px;
+    }
+
+  div#test-overlapping-green
+    {
+      background-color: red;
+      background-image: linear-gradient(1.57rAd, green, green);
+    }
+
+  div#reference-overlapped-red
+    {
+      background-color: red;
+      bottom: 100px;
+      position: relative;
+      z-index: -1;
+    }
+  </style>
+
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.
+
+  <div id="test-overlapping-green"></div>
+
+  <div id="reference-overlapped-red"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/angle-units-005.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: turn angle unit with mixed case</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-values-3/#angles">
+  <link rel="help" href="https://www.w3.org/TR/CSS22/syndata.html#characters">
+  <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+
+  <meta content="This test checks that 'turn' angle unit is case-insensitive." name="assert">
+  <meta name="flags" content="">
+
+  <style>
+  div
+    {
+      height: 100px;
+      width: 100px;
+    }
+
+  div#test-overlapping-green
+    {
+      background-color: red;
+      background-image: linear-gradient(0.25tUrN, green, green);
+    }
+
+  div#reference-overlapped-red
+    {
+      background-color: red;
+      bottom: 100px;
+      position: relative;
+      z-index: -1;
+    }
+  </style>
+
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.
+
+  <div id="test-overlapping-green"></div>
+
+  <div id="reference-overlapped-red"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/attr-invalid-type-008.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: attr() function with valid and invalid data types</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link href="http://www.w3.org/TR/css3-values/#attr-notation" rel="help">
+  <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+
+  <meta name="flags" content="invalid">
+  <meta content="When the data type of an attr() function is invalid or when the fallback value does not match the data type, then the attr() function generates an invalid declaration." name="assert">
+
+  <style>
+  div
+    {
+      height: 50px;
+      position: relative;
+      width: 50px;
+    }
+
+  div#valid1
+    {
+      background-color: green;
+      width: attr(attr-test-valid1 length);
+    }
+
+  div#invalid1
+    {
+      background-color: green;
+      width: 100px;
+      width: attr(attr-test-invalid1 number, 0);
+    }
+
+    /*
+    '0' can be both a number and a length. But here,
+    in this sub-test, the width CSS property requires
+    a length type and not a number type. So, the
+    attr() function generates an invalid declaration.
+    */
+
+  div#reference-overlapped-red
+    {
+      background-color: red;
+      bottom: 100px;
+      height: 100px;
+      width: 100px;
+      z-index: -1;
+    }
+
+  div#invalid2
+    {
+      background-color: red;
+      bottom: 100px;
+      width: 0px;
+      width: attr(attr-test-invalid2 length, 100);
+    }
+
+    /*
+    '100' is not a valid length value.
+    So, the attr() function generates an invalid
+    declaration.
+    */
+
+  div#invalid3
+    {
+      background-color: red;
+      bottom: 100px;
+      width: 0px;
+      width: attr(attr-test-invalid3 number, 100px);
+    }
+
+    /*
+    number type is not a valid length value.
+    So, the attr() function generates an invalid
+    declaration.
+    */
+  </style>
+
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.
+
+  <div id="valid1" attr-test-valid1="100px"></div>
+
+  <div id="invalid1" attr-test-invalid1="foo"></div>
+
+  <div id="reference-overlapped-red"></div>
+
+  <div id="invalid2" attr-test-invalid2="bar"></div>
+
+  <div id="invalid3" attr-test-invalid3="baz"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/calc-numbers.html
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: computed value of 'tab-size' and 'opacity' when specified with calc() function</title>
+
+  <!--
+
+  Original test is:
+
+https://chromium.googlesource.com/chromium/src/+/c825d655f6aaf73484f9d56e9012793f5b9668cc/third_party/WebKit/LayoutTests/css3/calc/calc-numbers.html
+
+  -->
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-color-3/#transparency">
+  <link rel="help" href="https://www.w3.org/TR/css-text-3/#tab-size-property">
+  <link rel="help" href="https://www.w3.org/TR/css3-values/#calc-computed-value">
+  <link rel="help" href="https://www.w3.org/TR/css3-values/#calc-range">
+
+  <meta name="flags" content="invalid">
+  <meta content="This test verifies how 11 calc() functions are computed for 'opacity' and 'tab-size'." name="assert">
+
+  <script src="/resources/testharness.js"></script>
+
+  <script src="/resources/testharnessreport.js"></script>
+
+  <div id="target"></div>
+
+  <script>
+  function startTesting()
+  {
+
+    function verifyComputedStyle(property_name, initial_value, specified_value, expected_value, description)
+    {
+
+    var elemTarget = document.getElementById("target");
+
+    test(function()
+      {
+
+      elemTarget.style.setProperty(property_name, initial_value);
+
+      /*
+      In exactly 6 out of the 11 sub-tests, the initial_value will
+      act as a fallback value because the specified value generates
+      an invalid value. Since we are running 11 consecutive tests
+      on the same element, then it is necessary to 'reset' its
+      property to an initial value.
+      */
+
+      elemTarget.style.setProperty(property_name, specified_value);
+
+      assert_equals(getComputedStyle(elemTarget)[property_name], expected_value, specified_value + ' should compute to ' + expected_value);
+
+      }, description);
+    }
+
+ /* verifyComputedStyle(property_name, initial_value, specified_value, expected_value, description) */
+
+    verifyComputedStyle("tab-size", "initial", "calc(2 * 3)", "6", "testing tab-size: calc(2 * 3)");
+
+    verifyComputedStyle("tab-size", "12345", "calc(2 * -4)", "0", "testing tab-size: calc(2 * -4)");
+    /*
+    an out-of-range value inside a calc() does not cause
+    the declaration to become invalid. The value resulting
+    from an expression must be clamped to the range
+    allowed in the target context.
+    https://www.w3.org/TR/css-values-3/#calc-range
+    */
+
+    verifyComputedStyle("opacity", "initial", "calc(2 / 4)", "0.5", "testing opacity: calc(2 / 4)");
+
+    verifyComputedStyle("tab-size", "12345", "calc(2 / 4)", "0.5", "testing tab-size: calc(2 / 4)");
+    /*
+    'tab-size' accepts <number> values.
+    */
+
+    verifyComputedStyle("opacity", "0.9", "calc(2 / 4) * 1px", "0.9", "testing opacity: calc(2 / 4) * 1px");
+
+    verifyComputedStyle("tab-size", "12345", "calc(1 + 1px)", "12345", "testing tab-size: calc(1 + 1px)");
+
+    verifyComputedStyle("tab-size", "12345", "calc(1 + 100%)", "12345", "testing tab-size: calc(1 + 100%)");
+
+    verifyComputedStyle("tab-size", "12345", "calc(100%)", "12345", "testing tab-size: calc(100%)");
+
+    verifyComputedStyle("tab-size", "12345", "calc(10px) bla", "12345", "testing tab-size: calc(10px) bla");
+
+    verifyComputedStyle("tab-size", "12345", "calc(bla) 10px", "12345", "testing tab-size: calc(bla) 10px");
+
+    verifyComputedStyle("tab-size", "initial", "calc(10px)", "10px", "testing tab-size: calc(10px)");
+
+ /* verifyComputedStyle(property_name, initial_value, specified_value, expected_value, description) */
+  }
+
+  startTesting();
+
+  </script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/calc-positive-fraction-001.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Test: calc() with positive fraction halfway between adjacent integers</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-values-4/#combine-integers">
+  <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+  <meta name="flags" content="">
+
+  <style>
+  div
+    {
+      height: 100px;
+      position: absolute;
+      width: 100px;
+    }
+
+  div#red-overlapped
+    {
+      background-color: red;
+      z-index: 2;
+    }
+
+  div#green-overlapping
+    {
+      background-color: green;
+      z-index: calc(3 / 2);
+      /*
+      should resolve to 'z-index: 2' since "values
+      halfway between adjacent integers rounded
+      towards positive infinity" and since
+      div#green-overlapping is last in document
+      tree order, then it should overlap
+      div#red-overlapped
+      */
+    }
+  </style>
+
+  <p>Test passes if there is a filled green square and <strong>no red</strong>.
+
+  <div id="red-overlapped"></div>
+
+  <div id="green-overlapping"></div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/ch-unit-008.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: ch unit in width (basic)</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-values-3/#font-relative-lengths">
+  <link rel="match" href="reference/ch-unit-008-ref.html">
+
+  <meta name="flags" content="">
+
+  <style>
+  div
+    {
+      font-size: 80px; /* arbitrary font size */
+    }
+
+  div#test-blue
+    {
+      background-color: blue;
+      height: 1.8em;
+      width: 5ch;
+    }
+
+  div#reference-orange
+    {
+      background-color: orange;
+      color: orange;
+      float: left;
+      line-height: 1.8; /* arbitrary line-height */
+    }
+  </style>
+
+  <p>Test passes if there is a blue rectangle with the <strong>same width</strong> as an orange rectangle.
+
+  <div id="test-blue"></div>
+
+  <div id="reference-orange">00000</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/ch-unit-009.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: ch unit in height (basic)</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-values-3/#font-relative-lengths">
+  <link rel="match" href="reference/ch-unit-009-ref.html">
+
+  <meta name="flags" content="">
+
+  <style>
+  div
+    {
+      float: left;
+      font-size: 80px; /* arbitrary font size */
+    }
+
+  div#test-blue
+    {
+      background-color: blue;
+      height: 5ch;
+      width: 1.8em;
+    }
+
+  div#reference-orange
+    {
+      background-color: orange;
+      color: orange;
+      line-height: 1.8; /* arbitrary line-height */
+      writing-mode: vertical-rl;
+    }
+  </style>
+
+  <p>Test passes if there is a blue rectangle with the <strong>same height</strong> as an orange rectangle.
+
+  <div id="test-blue"></div>
+
+  <div id="reference-orange">00000</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/ch-unit-010.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: ch unit in height with 'text-orientation: mixed'</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-values-3/#font-relative-lengths">
+  <link rel="match" href="reference/ch-unit-009-ref.html">
+
+  <meta name="flags" content="">
+  <meta name="assert" content="In this test, the ch unit is the advance width measure of the 0 (ZERO, U+0030) glyph.">
+
+  <style>
+  div
+    {
+      float: left;
+      font-size: 80px; /* arbitrary font size */
+      text-orientation: mixed;
+      writing-mode: vertical-rl;
+    }
+
+  div#test-blue
+    {
+      background-color: blue;
+      height: 5ch;
+      width: 1.8em;
+    }
+
+  div#reference-orange
+    {
+      background-color: orange;
+      color: orange;
+      line-height: 1.8; /* arbitrary line-height */
+    }
+  </style>
+
+  <p>Test passes if there is a blue rectangle with the <strong>same height</strong> as an orange rectangle.
+
+  <div id="test-blue"></div>
+
+  <div id="reference-orange">00000</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/ch-unit-011.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: ch unit in height with 'text-orientation: upright'</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-values-3/#font-relative-lengths">
+  <link rel="match" href="reference/ch-unit-011-ref.html">
+
+  <meta name="flags" content="">
+  <meta name="assert" content="In this test, the ch unit is the advance height measure of the 0 (ZERO, U+0030) glyph.">
+
+  <style>
+  div
+    {
+      float: left;
+      font-size: 80px; /* arbitrary font size */
+      text-orientation: upright;
+      writing-mode: vertical-rl;
+    }
+
+  div#test-blue
+    {
+      background-color: blue;
+      height: 5ch;
+      width: 1.8em;
+    }
+
+  div#reference-orange
+    {
+      background-color: orange;
+      color: orange;
+      line-height: 1.8; /* arbitrary line-height */
+    }
+  </style>
+
+  <p>Test passes if there is a blue rectangle with the <strong>same height</strong> as an orange rectangle.
+
+  <div id="test-blue"></div>
+
+  <div id="reference-orange">00000</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/ch-unit-012.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test: ch unit in height with 'text-orientation: sideways'</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+  <link rel="help" href="https://www.w3.org/TR/css-values-3/#font-relative-lengths">
+  <link rel="match" href="reference/ch-unit-009-ref.html">
+
+  <meta name="flags" content="">
+  <meta name="assert" content="In this test, the ch unit is the advance width measure of the 0 (ZERO, U+0030) glyph.">
+
+  <style>
+  div
+    {
+      float: left;
+      font-size: 80px; /* arbitrary font size */
+      text-orientation: sideways;
+      writing-mode: vertical-rl;
+    }
+
+  div#test-blue
+    {
+      background-color: blue;
+      height: 5ch;
+      width: 1.8em;
+    }
+
+  div#reference-orange
+    {
+      background-color: orange;
+      color: orange;
+      line-height: 1.8; /* arbitrary line-height */
+    }
+  </style>
+
+  <p>Test passes if there is a blue rectangle with the <strong>same height</strong> as an orange rectangle.
+
+  <div id="test-blue"></div>
+
+  <div id="reference-orange">00000</div>
--- a/testing/web-platform/tests/css/css-values/lh-rlh-on-root-001.html
+++ b/testing/web-platform/tests/css/css-values/lh-rlh-on-root-001.html
@@ -40,23 +40,23 @@
     window.document.documentElement.style="font-size: 142px; line-height: 1rlh;";
     l_h = get_root_line_height();
     assert_approx_equals( l_h, initial_l_h, 1, "the rlh unit on the root element's line-height property uses font metrics corresponding to the initial values of the font or line-height properties");
   }, "rlh in line-height on root");
 
   test(function() {
     window.document.documentElement.style="font-size: 1lh; line-height: 142px;";
     f_s = get_root_font_size();
-    assert_approx_equals( f_s, initial_f_s, 1, "the lh unit on the root element's font-size property uses font metrics corresponding to the initial values of the font or line-height properties");
+    assert_approx_equals( f_s, initial_l_h, 1, "the lh unit on the root element's font-size property uses font metrics corresponding to the initial values of the font or line-height properties");
   }, "lh in font-size on root");
 
   test(function() {
     window.document.documentElement.style="font-size: 1rlh; line-height: 142px;";
     f_s = get_root_font_size();
-    assert_approx_equals( f_s, initial_f_s, 1, "the rlh unit on the root element's font-size property uses font metrics corresponding to the initial values of the font or line-height properties");
+    assert_approx_equals( f_s, initial_l_h, 1, "the rlh unit on the root element's font-size property uses font metrics corresponding to the initial values of the font or line-height properties");
 
   }, "rlh in font-size on root");
 
 
   test(function() {
     window.document.documentElement.style="font-size: 142px; line-height: 2lh;";
     l_h = get_root_line_height();
     assert_approx_equals( l_h, initial_l_h * 2, 1, "the lh unit on the root element's line-height property actually works as a unit and doesn't merely cause a fallback that doesn't take the number of units into account");
@@ -66,17 +66,17 @@
     window.document.documentElement.style="font-size: 142px; line-height: 2rlh;";
     l_h = get_root_line_height();
     assert_approx_equals( l_h, initial_l_h * 2, 1, "the rlh unit on the root element's line-height property actually works as a unit and doesn't merely cause a fallback that doesn't take the number of units into account");
   }, "2rlh in line-height on root");
 
   test(function() {
     window.document.documentElement.style="font-size: 2lh; line-height: 142px;";
     f_s = get_root_font_size();
-    assert_approx_equals( f_s, initial_f_s * 2, 1, "the lh unit on the root element's font-size property actually works as a unit and doesn't merely cause a fallback that doesn't take the number of units into account");
+    assert_approx_equals( f_s, initial_l_h * 2, 1, "the lh unit on the root element's font-size property actually works as a unit and doesn't merely cause a fallback that doesn't take the number of units into account");
   }, "2lh in font-size on root");
 
   test(function() {
     window.document.documentElement.style="font-size: 2rlh; line-height: 142px;";
     f_s = get_root_font_size();
     assert_approx_equals( f_s, initial_f_s * 2, 1, "the rlh unit on the root element's font-size property actually works as a unit and doesn't merely cause a fallback that doesn't take the number of units into account");
 
   }, "2rlh in font-size on root");
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/reference/ch-unit-008-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test Reference File</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+
+  <style>
+  div
+    {
+      float: left;
+      font-size: 80px; /* arbitrary font size */
+      line-height: 1.8; /* arbitrary line-height */
+    }
+
+  div#blue
+    {
+      background-color: blue;
+      color: blue;
+    }
+
+  div#orange
+    {
+      background-color: orange;
+      color: orange;
+      clear: left;
+    }
+  </style>
+
+  <p>Test passes if there is a blue rectangle with the <strong>same width</strong> as an orange rectangle.
+
+  <div id="blue">00000</div>
+
+  <div id="orange">00000</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/reference/ch-unit-009-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test Reference File</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+
+  <style>
+  div
+    {
+      float: left;
+      font-size: 80px; /* arbitrary font size */
+      line-height: 1.8; /* arbitrary line-height */
+      writing-mode: vertical-rl;
+    }
+
+  div#blue
+    {
+      background-color: blue;
+      color: blue;
+    }
+
+  div#orange
+    {
+      background-color: orange;
+      color: orange;
+    }
+  </style>
+
+  <p>Test passes if there is a blue rectangle with the <strong>same height</strong> as an orange rectangle.
+
+  <div id="blue">00000</div>
+
+  <div id="orange">00000</div>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-values/reference/ch-unit-011-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+
+  <meta charset="UTF-8">
+
+  <title>CSS Values and Units Test Reference File</title>
+
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+
+  <style>
+  div
+    {
+      float: left;
+      font-size: 80px; /* arbitrary font size */
+      line-height: 1.8; /* arbitrary line-height */
+      text-orientation: upright;
+      writing-mode: vertical-rl;
+    }
+
+  div#blue
+    {
+      background-color: blue;
+      color: blue;
+    }
+
+  div#orange
+    {
+      background-color: orange;
+      color: orange;
+    }
+  </style>
+
+  <p>Test passes if there is a blue rectangle with the <strong>same height</strong> as an orange rectangle.
+
+  <div id="blue">00000</div>
+
+  <div id="orange">00000</div>
--- a/testing/web-platform/tests/css/cssom/CSS.html
+++ b/testing/web-platform/tests/css/cssom/CSS.html
@@ -21,16 +21,18 @@
         assert_equals(CSS.escape("--0foo"), "--0foo", "CSS.escape: Numbers at the beginning of an ident after multiple hyphens do not get unicode escaped");
     }, "CSS.escape");
     test(function () {
         // https://drafts.csswg.org/css-conditional/#dom-css-supports
         // https://drafts.csswg.org/css-conditional/#typedef-supports-condition
         assert_equals(CSS.supports("color: red"), true, "CSS.supports: Single-argument form allows for declarations without enclosing parentheses");
         assert_equals(CSS.supports("(color: red) and (color: blue)"), true, "CSS.supports: Complex conditions allowed");
         assert_equals(CSS.supports("not (foobar)"), true, "CSS.supports: general_enclosed still parses");
+        assert_equals(CSS.supports("color: something-pointless var(--foo)"), true, "Variable references always parse");
+        assert_equals(CSS.supports("color: something-pointless(var(--foo))"), true, "Variable references in an unknown function always parse");
     }, "CSS.supports, one argument form");
     test(function () {
         // https://drafts.csswg.org/css-conditional/#dom-css-supports
         // https://drafts.csswg.org/css-conditional/#dfn-support
         assert_equals(CSS.supports("color", "red"), true, "CSS.supports: two argument form succeeds for known property");
         assert_equals(CSS.supports("unknownproperty", "blah"), false, "CSS.supports: two argument form fails for unknown property");
         assert_equals(CSS.supports("width", "blah"), false, "CSS.supports: two argument form fails for invalid value");
         assert_equals(CSS.supports("--foo", "blah"), true, "CSS.supports: two argument form succeeds for custom property");
--- a/testing/web-platform/tests/css/filter-effects/backdrop-filter-border-radius-ref.html
+++ b/testing/web-platform/tests/css/filter-effects/backdrop-filter-border-radius-ref.html
@@ -1,16 +1,16 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>backdrop-filter: Should clip using border radius.</title>
 <link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org">
 
 
 
-<div style="opacity: 0.9999;">
+<div>
   <div class="circle outside"></div>
   <div class="circle inside"></div>
 </div>
 
 
 <style>
 div {
   position: absolute;
@@ -19,21 +19,18 @@ div {
   top: 10px;
   left: 10px;
   background: green;
 }
 .circle {
   top: 30px;
   left: 30px;
   border-radius: 50px;
-  background: yellow;
-  will-change: transform;
+  background: #ffff0060;
 }
 .inside {
-  background: #ffd94d;
+  background: #ffaf9f;
   clip-path: inset(0px 30px 30px 0px);
-  will-change: transform;
 }
 .outside {
-  background: #ffff4d;
-  will-change: transform;
+  background: #ffff9f;
 }
 </style>
--- a/testing/web-platform/tests/css/filter-effects/backdrop-filter-border-radius.html
+++ b/testing/web-platform/tests/css/filter-effects/backdrop-filter-border-radius.html
@@ -19,16 +19,14 @@ div {
   top: 10px;
   left: 10px;
   background: green;
 }
 .circle {
   top: 30px;
   left: 30px;
   border-radius: 50px;
-  background: yellow;
-  will-change: transform;
+  background: #ffff0060;
 }
 .filter {
-  opacity: 0.7;
   backdrop-filter: invert(1);
 }
 </style>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/reactions/HTMLCanvasElement.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLCanvasElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="width, height of HTMLCanvasElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-canvas-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('width', 'width', '15', '20', 'width on HTMLCanvasElement', 'canvas', HTMLCanvasElement);
+testReflectAttribute('height', 'height', '23', '45', 'height on HTMLCanvasElement', 'canvas', HTMLCanvasElement);
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/reactions/HTMLDataElement.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLDataElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="value of HTMLDataElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-data-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('value', 'value', '1234', '2345', 'name on HTMLDataElement', 'data', HTMLDataElement);
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/reactions/HTMLDetailsElement.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLDetailsElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="open of HTMLDetailsElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-details-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectBooleanAttribute('open', 'open', 'open on HTMLDetailsElement', 'details', HTMLDetailsElement);
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/reactions/HTMLMapElement.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLMapElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="name of HTMLMapElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-map-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<img usemap="#yellow" src="/images/yellow.png" alt="yellow pic">
+<img usemap="#green" src="/images/green.png" alt="green pic">
+<script>
+
+testReflectAttribute('name', 'name', 'yellow', 'green', 'name on HTMLMapElement', 'map', HTMLMapElement);
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/reactions/HTMLModElement.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLModElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="cite, dateTime of HTMLModElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#attributes-common-to-ins-and-del-elements">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('cite', 'cite', '../resources/custom-elements-helpers.js', './resources/reactions.js', 'cite on ins use HTMLModElement', 'ins', HTMLModElement);
+testReflectAttribute('dateTime', 'datetime', '2018-12-19 00:00Z', '2018-12-20 00:00Z', 'dateTime on ins use HTMLModElement', 'ins', HTMLModElement);
+testReflectAttribute('cite', 'cite', '../resources/custom-elements-helpers.js', './resources/reactions.js', 'cite on del use HTMLModElement', 'del', HTMLModElement);
+testReflectAttribute('dateTime', 'datetime', '2018-10-11T01:25-07:00', '2018-10-12T01:25-07:00', 'dateTime on del use HTMLModElement', 'del', HTMLModElement);
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/reactions/HTMLOListElement.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLOListElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="reversed, start, type of HTMLOListElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-ol-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectBooleanAttribute('reversed', 'reversed', 'reversed on HTMLOListElement', 'ol', HTMLOListElement);
+testReflectAttribute('start', 'start', '2', '5', 'start on HTMLOListElement', 'ol', HTMLOListElement);
+testReflectAttribute('type', 'type', '1', 'a', 'type on HTMLOListElement', 'ol', HTMLOListElement);
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/reactions/HTMLQuoteElement.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLQuoteElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="cite of HTMLQuoteElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-blockquote-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('cite', 'cite', '../resources/custom-elements-helpers.js', './resources/reactions.js', 'cite on blockquote use HTMLQuoteElement', 'blockquote', HTMLQuoteElement);
+testReflectAttribute('cite', 'cite', '../resources/custom-elements-helpers.js', './resources/reactions.js', 'cite on q use HTMLQuoteElement', 'q', HTMLQuoteElement);
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/reactions/HTMLSlotElement.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLSlotElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="name of HTMLSlotElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-slot-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('name', 'name', 'slot1', 'slot2', 'name on HTMLSlotElement', 'slot', HTMLSlotElement);
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/reactions/HTMLTimeElement.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>Custom Elements: CEReactions on HTMLTimeElement interface</title>
+<link rel="author" title="Intel" href="http://www.intel.com">
+<meta name="assert" content="name of HTMLTimeElement interface must have CEReactions">
+<meta name="help" content="https://html.spec.whatwg.org/#the-time-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+<script src="./resources/reactions.js"></script>
+
+<script>
+
+testReflectAttribute('dateTime', 'datetime', '2018-12-10', '2018-12-12', 'dateTime on HTMLTimeElement', 'time', HTMLTimeElement);
+
+</script>
--- a/testing/web-platform/tests/custom-elements/reactions/resources/reactions.js
+++ b/testing/web-platform/tests/custom-elements/reactions/resources/reactions.js
@@ -159,18 +159,18 @@ function testReflectAttributeWithContent
         assert_attribute_log_entry(logEntries.last(), {name: contentAttributeName, oldValue: contentValue1, newValue: contentValue2, namespace: null});
     }, name + ' must enqueue an attributeChanged reaction when replacing an existing attribute');
 }
 
 function testReflectAttribute(jsAttributeName, contentAttributeName, validValue1, validValue2, name, elementName, interfaceName) {
     testReflectAttributeWithContentValues(jsAttributeName, contentAttributeName, validValue1, validValue1, validValue2, validValue2, name, elementName, interfaceName);
 }
 
-function testReflectBooleanAttribute(jsAttributeName, contentAttributeName, name) {
-    testReflectAttributeWithContentValues(jsAttributeName, contentAttributeName, true, '', false, null, name);
+function testReflectBooleanAttribute(jsAttributeName, contentAttributeName, name, elementName, interfaceName) {
+    testReflectAttributeWithContentValues(jsAttributeName, contentAttributeName, true, '', false, null, name, elementName, interfaceName);
 }
 
 function testAttributeAdder(testFunction, name) {
     test(function () {
         var element = define_new_custom_element(['id']);
         var instance = document.createElement(element.name);
         assert_array_equals(element.takeLog().types(), ['constructed']);
         testFunction(instance, 'id', 'foo');
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/buffer-before-onload.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<meta charset=utf-8 />
+<title>Element Timing: buffer elements before onload</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="resources/element-timing-helpers.js"></script>
+<body>
+<img src=resources/slow-image.py?name=square20.png&sleep=500>
+<script>
+  /*
+  In this test, a slow image is added to the frame to delay onload. The entry
+  for the other image should be available before onload, and thus delivered to
+  the performance timeline.
+  */
+  async_test(function(t) {
+    beforeRender = performance.now();
+    const img = document.createElement('img');
+    img.src = 'resources/square20.jpg';
+    img.setAttribute('elementtiming', 'my_image');
+    document.body.appendChild(img);
+    window.onload = t.step_func_done( () => {
+      const entries = performance.getEntriesByName('my_image');
+      assert_equals(entries.length, 1);
+      assert_greater_than_equal(performance.getEntriesByType('element').length, 1);
+      assert_equals(performance.getEntries().filter(e => e.name === 'my_image').length, 1);
+      const entry = entries[0];
+      checkElement(entry, 'my_image', beforeRender);
+    });
+  }, "Element Timing: image loads before onload.");
+
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/cross-origin-element.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Element Timing: do NOT observe cross-origin images</title>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/element-timing-helpers.js"></script>
+<script>
+  async_test((t) => {
+    const observer = new PerformanceObserver(
+      t.step_func_done((entryList) => {
+        assert_unreached("We should not observe a cross origin element.");
+      })
+    );
+    observer.observe({entryTypes: ['element']});
+    // We add the image during onload to be sure that the observer is registered
+    // in time for it to observe the element timing.
+    // TODO(npm): change observer to use buffered flag.
+    window.onload = () => {
+      // Add a cross origin image resource.
+      const img = document.createElement('img');
+      img.src =
+        'http://localhost:8000/resources/square100.png';
+      document.body.appendChild(img);
+    };
+    t.step_timeout( () => {
+      // After some wait, assume observer did not receive the entry, so the test passes.
+      t.done();
+    }, 100);
+  }, 'Cross-origin image element is NOT observable.');
+</script>
+
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/cross-origin-iframe-element.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Element Timing: do NOT observe elements from cross-origin iframes</title>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/element-timing-helpers.js"></script>
+<script>
+  async_test((t) => {
+    const observer = new PerformanceObserver(
+      t.step_func_done((entryList) => {
+        assert_unreached("We should not observe a cross origin element.");
+      })
+    );
+    observer.observe({entryTypes: ['element']});
+    // We add the iframe during onload to be sure that the observer is registered
+    // in time for it to observe the element timing.
+    // TODO(npm): change observer to use buffered flag.
+    window.onload = () => {
+      // Add a cross origin iframe with an image.
+      const iframe = document.createElement('iframe');
+      iframe.src =
+        'http://localhost:8000/performance-timing/element-resources/iframe-with-square.html';
+      document.body.appendChild(iframe);
+    };
+    t.step_timeout( () => {
+      // After some wait, assume observer did not receive the entry, so the test passes.
+      t.done();
+    }, 300);
+  }, 'Element from cross origin iframe is NOT observable.');
+</script>
+
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/image-not-fully-visible.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Element Timing: intersectionRect when image overflows</title>
+<body>
+<style>
+body {
+  margin: 200px 100px;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/element-timing-helpers.js"></script>
+<script>
+  let beforeRender;
+  async_test(function (t) {
+    const observer = new PerformanceObserver(
+      t.step_func_done(function(entryList) {
+        assert_equals(entryList.getEntries().length, 1);
+        const entry = entryList.getEntries()[0];
+        checkElement(entry, 'not_fully_visible', beforeRender);
+        // Image will not be fully visible. It should start from the top left part
+        // of the document, excluding the margin, and then overflow.
+        checkRect(entry,
+          [100, document.documentElement.clientWidth, 200, document.documentElement.clientHeight]);
+      })
+    );
+    observer.observe({entryTypes: ['element']});
+    // We add the image during onload to be sure that the observer is registered
+    // in time for it to observe the element timing.
+    window.onload = () => {
+      // Add an image setting width and height equal to viewport.
+      const img = document.createElement('img');
+      img.src = 'resources/square20.png';
+      img.setAttribute('elementtiming', 'not_fully_visible');
+      img.width = document.documentElement.clientWidth;
+      img.height = document.documentElement.clientHeight;
+      document.body.appendChild(img);
+      beforeRender = performance.now();
+    };
+  }, 'The intersectionRect of an img element overflowing is computed correctly');
+</script>
+
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/observe-child-element.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Element Timing: observe elements from same-origin iframes</title>
+<body>
+<style>
+body {
+  margin: 0;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/element-timing-helpers.js"></script>
+<script>
+  let beforeRender;
+  async_test((t) => {
+    const observer = new PerformanceObserver(
+      t.step_func_done((entryList) => {
+        assert_equals(entryList.getEntries().length, 1);
+        const entry = entryList.getEntries()[0];
+        checkElement(entry, 'my_image', beforeRender);
+        // Assume viewport has size at least 100, so the element is fully visible.
+        checkRect(entry, [0, 100, 0, 100]);
+      })
+    );
+    observer.observe({entryTypes: ['element']});
+    // We add the iframe during onload to be sure that the observer is registered
+    // in time for it to observe the element timing.
+    // TODO(npm): change observer to use buffered flag.
+    window.onload = () => {
+      // Add iframe with an image of width and height equal to 100.
+      const iframe = document.createElement('iframe');
+      iframe.src = 'resources/iframe-with-square.html';
+      document.body.appendChild(iframe);
+      beforeRender = performance.now();
+    };
+  }, 'Element from same-origin iframe is observable.');
+</script>
+
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/observe-elementtiming.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Element Timing: observe elements with elementtiming attribute</title>
+<body>
+<style>
+body {
+  margin: 0;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/element-timing-helpers.js"></script>
+<script>
+  let beforeRender;
+  async_test(function (t) {
+    const observer = new PerformanceObserver(
+      t.step_func_done(function(entryList) {
+        assert_equals(entryList.getEntries().length, 1);
+        const entry = entryList.getEntries()[0];
+        checkElement(entry, 'my_image', beforeRender);
+        // Assume viewport has size at least 100, so the element is fully visible.
+        checkRect(entry, [0, 100, 0, 100]);
+      })
+    );
+    observer.observe({entryTypes: ['element']});
+    // We add the image during onload to be sure that the observer is registered
+    // in time for it to observe the element timing.
+    window.onload = () => {
+      // Add image of width and height equal to 100.
+      const img = document.createElement('img');
+      img.src = 'resources/square100.png';
+      img.setAttribute('elementtiming', 'my_image');
+      document.body.appendChild(img);
+      beforeRender = performance.now();
+    };
+  }, 'Element with elementtiming attribute is observable.');
+</script>
+
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/observe-large-image.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Element Timing: observe large elements</title>
+<body>
+<style>
+body {
+  margin: 0;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/element-timing-helpers.js"></script>
+<script>
+  let beforeRender;
+  async_test(function (t) {
+    const observer = new PerformanceObserver(
+      t.step_func_done(function(entryList) {
+        assert_equals(entryList.getEntries().length, 1);
+        const entry = entryList.getEntries()[0];
+        checkElement(entry, 'img', beforeRender)
+        // Assume viewport hasn't changed, so the element occupies all of it.
+        checkRect(entry,
+          [0, document.documentElement.clientWidth, 0, document.documentElement.clientHeight]);
+      })
+    );
+    observer.observe({entryTypes: ['element']});
+    // We add the image during onload to be sure that the observer is registered
+    // in time for it to observe the element timing.
+    window.onload = () => {
+      // Add an image setting width and height equal to viewport.
+      const img = document.createElement('img');
+      img.src = 'resources/square20.jpg';
+      img.width = document.documentElement.clientWidth;
+      img.height = document.documentElement.clientHeight;
+      document.body.appendChild(img);
+      beforeRender = performance.now();
+    };
+  }, 'Large img element is observable.');
+</script>
+
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/observe-multiple-images.html
@@ -0,0 +1,110 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<title>Element Timing: multiple images</title>
+<body>
+<style>
+body {
+  margin: 0;
+}
+#img1 {
+  display: block;
+  margin-left: auto;
+  margin-right: auto;
+}
+#img2 {
+  margin-top:150px;
+  margin-left:50px;
+}
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/element-timing-helpers.js"></script>
+<script>
+  let beforeRender, image1Observed=0, image2Observed=0, image3Observed=0;
+  async_test(function (t) {
+    const observer = new PerformanceObserver(
+      t.step_func(function(entryList) {
+        entryList.getEntries().forEach( entry => {
+          if (entry.name === 'image1') {
+            if (image1Observed) {
+              assert_unreached("Observer received image1 more than once");
+              t.done();
+            }
+            image1Observed = 1;
+            checkElement(entry, 'image1', beforeRender);
+            // This image is horizontally centered.
+            // Using abs and comparing to 1 because the viewport sizes could be odd.
+            // If a size is odd, then image cannot be in the pure center, but left
+            // and right should still be very close to their estimated coordinates.
+            assert_less_than_equal(Math.abs(entry.intersectionRect.left -
+              (document.documentElement.clientWidth / 2 - 50)), 1,
+              'left of rect for image1');
+            assert_less_than_equal(Math.abs(entry.intersectionRect.right -
+              (document.documentElement.clientWidth / 2 + 50)), 1,
+              'right of rect for image1');
+            assert_equals(entry.intersectionRect.top, 0, 'top of rect for image1');
+            assert_equals(entry.intersectionRect.bottom,
+              100, 'bottom of rect for image1');
+          }
+          else if (entry.name === 'image2') {
+            if (image2Observed) {
+              assert_unreached("Observer received image2 more than once");
+              t.done();
+            }
+            image2Observed = 1;
+            checkElement(entry, 'image2', beforeRender);
+            // This image should be below image 1, and should respect the margin.
+            checkRect(entry, [50, 250, 250, 450], "of image2");
+          }
+          else if (entry.name === 'image3') {
+            if (image3Observed) {
+              assert_unreached("Observer received image3 more than once");
+              t.done();
+            }
+            image3Observed = 1;
+            checkElement(entry, 'image3', beforeRender);
+            // This image is just to the right of image2.
+            checkRect(entry, [250, 450, 250, 450], "of image3");
+          }
+          else {
+            assert_unreached("Received an unexpected name.");
+            t.done();
+          }
+          if (image1Observed && image2Observed && image3Observed) {
+            t.done();
+          }
+        });
+      })
+    );
+    observer.observe({entryTypes: ['element']});
+    function addImage(number, source, width=0) {
+      const img = document.createElement('img');
+      img.src = source;
+      img.id = 'img' + number;
+      img.setAttribute('elementtiming', 'image' + number);
+      if (width !== 0)
+        img.width = width;
+      document.body.appendChild(img);
+    }
+    // Add the images during onload to be sure that the observer is registered in
+    // time to observe the element timing.
+    window.onload = () => {
+      addImage(1, 'resources/square100.png');
+      // Use requestAnimationFrame and a timeout to ensure that the images are
+      // processed in the order we want.
+      requestAnimationFrame( () => {
+        t.step_timeout( () => {
+          // Set the size equal to that of image3 to make positioning easier.
+          addImage(2, 'resources/square20.png', 200);
+          requestAnimationFrame( () => {
+            t.step_timeout( () => {
+              addImage(3, 'resources/circle.svg');
+            }, 0);
+          });
+        }, 0);
+      });
+      beforeRender = performance.now();
+    };
+  }, 'PerformanceObserver can observe multiple image elements.');
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/progressively-loaded-image.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<meta charset=utf-8 />
+<title>Element Timing: buffer elements before onload</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="resources/element-timing-helpers.js"></script>
+<body>
+<script>
+  let beforeRender;
+  // Number of characters to be read on the initial read, before sleeping.
+  // Should be sufficient to do at least a first scan.
+  let numInitial = 75;
+  let sleep = 500;
+  async_test(function(t) {
+    const observer = new PerformanceObserver(
+      t.step_func_done(function(entryList) {
+        assert_equals(entryList.getEntries().length, 1);
+        const entry = entryList.getEntries()[0];
+        // Since the image is only fully loaded after the sleep, the render timestamp
+        // must be greater than |beforeRender| + |sleep|.
+        checkElement(entry, 'my_image', beforeRender + sleep);
+      })
+    );
+    observer.observe({entryTypes: ['element']});
+
+    const img = document.createElement('img');
+    img.src = 'resources/progressive-image.py?name=square20.jpg&numInitial='
+      + numInitial + '&sleep=' + sleep;
+    img.setAttribute('elementtiming', 'my_image');
+    document.body.appendChild(img);
+    beforeRender = performance.now();
+    t.step_timeout(() => {assert_true(0);}, 2000);
+  }, "Element Timing: image render timestamp occurs after it is fully loaded.");
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/resources/circle.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
+              "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
+    <circle cx="50%" cy="50%" r="80" style="fill:blue;" />
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/resources/element-timing-helpers.js
@@ -0,0 +1,21 @@
+// Checks that this is an ElementTiming entry with name |expectedName|. It also
+// does a very basic check on |startTime|: after |beforeRender| and before now().
+function checkElement(entry, expectedName, beforeRender) {
+  assert_equals(entry.entryType, 'element');
+  assert_equals(entry.name, expectedName);
+  assert_equals(entry.duration, 0);
+  assert_greater_than_equal(entry.startTime, beforeRender);
+  assert_greater_than_equal(performance.now(), entry.startTime);
+}
+
+// Checks that the rect matches the desired values [left right top bottom]
+function checkRect(entry, expected, description="") {
+  assert_equals(entry.intersectionRect.left, expected[0],
+    'left of rect ' + description);
+  assert_equals(entry.intersectionRect.right, expected[1],
+    'right of rect ' + description);
+  assert_equals(entry.intersectionRect.top, expected[2],
+    'top of rect ' + description);
+  assert_equals(entry.intersectionRect.bottom, expected[3],
+    'bottom of rect ' + description);
+}
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/resources/iframe-with-square.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<meta charset=utf-8>
+<body>
+<style>
+body {
+  margin: 0;
+}
+</style>
+<img src='square100.png' elementtiming="my_image">
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/resources/progressive-image.py
@@ -0,0 +1,26 @@
+import os.path
+import time
+
+def main(request, response):
+    name = request.GET.first("name")
+    sleepTime = float(request.GET.first("sleep")) / 1E3
+    numInitial = int(request.GET.first("numInitial"))
+
+    path = os.path.join(os.path.dirname(__file__), name)
+    body = open(path, "rb").read()
+
+    response.headers.set("Content-Type", "image")
+    response.headers.set("Content-Length", len(body))
+    response.headers.set("Cache-control", "no-cache, must-revalidate")
+    response.write_status_headers()
+
+    # Read from the beginning, |numInitial| bytes.
+    first = body[:numInitial]
+    response.writer.write_content(first)
+    response.writer.flush()
+
+    time.sleep(sleepTime)
+
+    # Read the remainder after having slept.
+    second = body[numInitial:]
+    response.writer.write_content(second)
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/resources/slow-image.py
@@ -0,0 +1,17 @@
+import os.path
+import time
+
+def main(request, response):
+    name = request.GET.first("name")
+    sleepTime = float(request.GET.first("sleep")) / 1E3
+
+    time.sleep(sleepTime)
+
+    path = os.path.join(os.path.dirname(__file__), name)
+    body = open(path, "rb").read()
+
+    response.headers.set("Content-Type", "image")
+    response.headers.set("Content-Length", len(body))
+    response.headers.set("Cache-control", "no-cache, must-revalidate")
+
+    response.content = body;
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..567babb96d1ec3e1032d476f8f7ee1fcb2aa4875
GIT binary patch
literal 12940
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
C5AA;d
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..83ed4914bbb52d097107bd6a128ae8e149b5be86
GIT binary patch
literal 529
zc$}q<F%H5o5CnI90uqVBmJDq~O~VgdAVt8J_ydnZJOV<)H>i$t0a6geMb4Gi<Gs<V
zKHv}Sz6D9_>_G3>=G&;rC1X3NXM_q7Q5fI?B~UL|m>l|3TfEFa`thvR4s#)#7Z31s
ze6B4vIQs93jiHqlaN?Q_gx`RWi9>+<0Do6ZlN$z@R?XWSVh<*dl9ex6`O;DYZZ9c6
BJ9Pj6
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..4d51ac4b4633f0a24155f331ee63035e62b6dbe1
GIT binary patch
literal 150
zc%17D@N?(olHy`uVBq!ia0vp^A|TAc1SFYWcSQjy&H|6fVg?3oVGw3ym^DWND9B#o
z>FdgVkCB&~Rr_1XkusnVPi9C&iF1B#Zfaf$0|@L{w`nGjlJ#_P46!(!oRaY4yn|js
m(gKE_EV-*Tt13f`pUz@bn8&DYSaD=0NQ0-VpUXO@geCwk5GIQN
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/element-timing/supported-element-type.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<head>
+<title>PerformanceObserver.supportedEntryTypes contains "element"</title>
+</head>
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(() => {
+  if (typeof PerformanceObserver.supportedEntryTypes === "undefined")
+    assert_unreached("supportedEntryTypes is not supported.");
+  assert_greater_than(PerformanceObserver.supportedEntryTypes.indexOf("element"), -1,
+    "There should be an entry 'element' in PerformanceObserver.supportedEntryTypes");
+}, "supportedEntryTypes contains 'element'.");
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/fetch/sec-metadata/iframe.tentative.sub.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/fetch/sec-metadata/resources/helper.js></script>
+<body>
+<script>
+  async_test(t => {
+    let i = document.createElement('iframe');
+    i.src = "http://{{host}}:{{ports[http][0]}}/fetch/sec-metadata/resources/post-to-owner.py";
+    window.addEventListener('message', t.step_func(e => {
+      if (e.source != i.contentWindow)
+        return;
+
+      assert_header_equals(e.data, {
+        "dest": "",
+        "site": "",
+        "user": ""
+      });
+      t.done();
+    }));
+
+    document.body.appendChild(i);
+  }, "Non-secure same-origin iframe => No headers");
+
+  async_test(t => {
+    let i = document.createElement('iframe');
+    i.src = "http://{{hosts[][www]}}:{{ports[http][0]}}/fetch/sec-metadata/resources/post-to-owner.py";
+    window.addEventListener('message', t.step_func(e => {
+      if (e.source != i.contentWindow)
+        return;
+
+      assert_header_equals(e.data, {
+        "dest": "",
+        "site": "",
+        "user": ""
+      });
+      t.done();
+    }));
+
+    document.body.appendChild(i);
+  }, "Non-secure same-site iframe => No headers");
+
+  async_test(t => {
+    let i = document.createElement('iframe');
+    i.src = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/fetch/sec-metadata/resources/post-to-owner.py";
+    window.addEventListener('message', t.step_func(e => {
+      if (e.source != i.contentWindow)
+        return;
+
+      assert_header_equals(e.data, {
+        "dest": "",
+        "site": "",
+        "user": ""
+      });
+      t.done();
+    }));
+
+    document.body.appendChild(i);
+  }, "Non-secure cross-site iframe => No headers.");
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/fetch/sec-metadata/script.tentative.sub.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/fetch/sec-metadata/resources/helper.js></script>
+
+<!-- Same-origin script -->
+<script src="http://{{host}}:{{ports[http][0]}}/fetch/sec-metadata/resources/echo-as-script.py"></script>
+<script>
+  test(t => {
+    t.add_cleanup(_ => { header = null; });
+
+    assert_header_equals(header, {
+      "dest": "",
+      "site": "",
+      "user": ""
+    });
+  }, "Non-secure same-origin script => No headers");
+</script>
+
+<!-- Same-site script -->
+<script src="http://{{hosts[][www]}}:{{ports[http][0]}}/fetch/sec-metadata/resources/echo-as-script.py"></script>
+<script>
+  test(t => {
+    t.add_cleanup(_ => { header = null; });
+
+    assert_header_equals(header, {
+      "dest": "",
+      "site": "",
+      "user": ""
+    });
+  }, "Non-secure same-site script => No headers");
+</script>
+
+<!-- Cross-site script -->
+<script src="http://{{hosts[alt][www]}}:{{ports[http][0]}}/fetch/sec-metadata/resources/echo-as-script.py"></script>
+<script>
+  test(t => {
+    t.add_cleanup(_ => { header = null; });
+
+    assert_header_equals(header, {
+      "dest": "",
+      "site": "",
+      "user": ""
+    });
+  }, "Non-secure cross-site script => No headers");
+</script>
new file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..e34e5474377e4e29679669d4039efe560ac57fa6
GIT binary patch
literal 39764
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
new file mode 100755
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..780661ba1ca55c7ba73a8dabe0716c066b8cc7ca
GIT binary patch
literal 7724
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
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/windows/embedded-opener-a-form.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>opener and embedded documents; using a and form</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<iframe name=matchesastring></iframe>
+<a href=/common/blank.html target=matchesastring>&lt;a></a>
+<form action=/common/blank.html target=matchesastring><input type=submit value="<form>"></form>
+<script>
+async_test(t => {
+  const frame = document.querySelector("iframe");
+  let counter = 0;
+  frame.onload = t.step_func(() => {
+    // Firefox and Chrome/Safari load differently
+    if (frame.contentWindow.location.href === "about:blank") {
+      return;
+    }
+
+    // Test bits
+    assert_equals(frame.contentWindow.opener, null);
+    if (counter === 0) {
+      document.querySelector("input").click();
+    } else {
+      t.done();
+    }
+    counter++;
+  });
+  document.querySelector("a").click();
+});
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/windows/embedded-opener.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<title>opener and embedded documents; using window.open()</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<iframe name=matchesastring></iframe>
+<script>
+async_test(t => {
+  const frame = document.querySelector("iframe");
+  frame.onload = t.step_func(() => {
+    // Firefox and Chrome/Safari load differently
+    if (frame.contentWindow.location.href === "about:blank") {
+      return;
+    }
+
+    // Test bits
+    assert_equals(frame.contentWindow.opener, window, "opener before setting it to null");
+
+    const openerDesc = Object.getOwnPropertyDescriptor(frame.contentWindow, "opener"),
+          openerGet = openerDesc.get;
+
+    assert_equals(openerGet(), window, "opener before setting it to null via directly invoking the getter");
+    frame.contentWindow.opener = null;
+    frame.contentWindow.opener = "immaterial";
+    assert_equals(openerGet(), null, "opener after setting it to null via directly invoking the getter");
+    assert_equals(frame.contentWindow.opener, "immaterial");
+
+    t.done();
+  });
+  window.open("/common/blank.html", "matchesastring");
+});
+</script>
--- a/testing/web-platform/tests/html/dom/elements/global-attributes/dataset-delete.html
+++ b/testing/web-platform/tests/html/dom/elements/global-attributes/dataset-delete.html
@@ -27,18 +27,25 @@
       test(function() { assert_true(testDelete('data-foo', 'foo')); },
         "Deleting element.dataset['foo'] should also remove an attribute with name 'data-foo' should it exist.");
       test(function() { assert_true(testDelete('data-foo-bar', 'fooBar')); },
         "Deleting element.dataset['fooBar'] should also remove an attribute with name 'data-foo-bar' should it exist.");
       test(function() { assert_true(testDelete('data--', '-')); },
         "Deleting element.dataset['-'] should also remove an attribute with name 'data--' should it exist.");
       test(function() { assert_true(testDelete('data--foo', 'Foo')); },
         "Deleting element.dataset['Foo'] should also remove an attribute with name 'data--foo' should it exist.");
-      test(function() { assert_true(testDeleteNoAdd('data--foo', '-foo')); },
-        "Deleting element.dataset['-foo'] should also remove an attribute with name 'data--foo' should it exist.");
+      test(function() {
+        var d = document.createElement("div");
+        d.setAttribute('data--foo', "value");
+        assert_equals(d.dataset['-foo'], undefined);
+        assert_false('-foo' in d.dataset);
+        delete d.dataset['-foo'];
+        assert_true(d.hasAttribute('data--foo'));
+        assert_equals(d.getAttribute('data--foo'), "value");
+      }, "Deleting element.dataset['-foo'] should not remove an attribute with name 'data--foo' should it exist.");
       test(function() { assert_true(testDelete('data---foo', '-Foo')); },
         "Deleting element.dataset['-Foo'] should also remove an attribute with name 'data---foo' should it exist.");
       test(function() { assert_true(testDelete('data-', '')); },
         "Deleting element.dataset[''] should also remove an attribute with name 'data-' should it exist.");
       test(function() { assert_true(testDelete('data-\xE0', '\xE0')); },
         "Deleting element.dataset['\xE0'] should also remove an attribute with name 'data-\xE0' should it exist.");
       test(function() { assert_true(testDeleteNoAdd('foo')); },
         "Deleting element.dataset['foo'] should not throw if even if the element does now have an attribute with the name data-foo.");
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-multiple-error-events.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<link rel="author" title="Dom Farolino" href="mailto:dom@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-link-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link id=link rel=stylesheet id=style_test
+      onload="t.unreached_func('Sheet should fail to load')">
+<script>
+  var t = async_test("Check if the <link>'s error event fires for each style " +
+                     "sheet it fails to load");
+
+  link.onerror = t.step_func(() => {
+    link.onerror = t.step_func_done(() => {});
+    link.href = 'nonexistent.css?second';
+  });
+
+  link.href = 'nonexistent.css?first';
+</script>
+
+</head>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-multiple-load-events.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<link rel="author" title="Dom Farolino" href="mailto:dom@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-link-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link id=link rel=stylesheet id=style_test
+      onerror="t.unreached_func('Sheet should load successfully')">
+<script>
+  var t = async_test("Check if the <link>'s load event fires for each style " +
+                     "sheet it loads");
+
+  link.onload = t.step_func(() => {
+    link.onload = t.step_func_done(() => {});
+    link.href = 'style.css?second';
+  });
+
+  link.href = 'style.css?first';
+</script>
+
+</head>
+</html>
--- a/testing/web-platform/tests/html/semantics/forms/the-select-element/select-selectedOptions.html
+++ b/testing/web-platform/tests/html/semantics/forms/the-select-element/select-selectedOptions.html
@@ -29,16 +29,22 @@
 </select>
 
 <select multiple id="multiple-select-two-selected">
   <option>One</option>
   <option selected>Two</option>
   <option selected>Three</option>
 </select>
 
+<select id="select-named-selected">
+  <option>One</option>
+  <option>Two</option>
+  <option id="named-option" selected>Three</option>
+</select>
+
 <select id="invalid-select">
   <option selected>One</option>
   <option selected>Two</option>
   <option>Three</option>
 </select>
 
 <select id="select-same-object">
   <option>One</option>
@@ -99,16 +105,23 @@ test(() => {
 
   assert_array_equals(select.selectedOptions, [select.children[1]]);
   assert_equals(select.selectedOptions.length, 1);
 
 }, ".selectedOptions without the 'multiple' attribute but " +
    "more than one selected option should return the last one");
 
 test(() => {
+  const select = document.getElementById("select-named-selected");
+
+  assert_equals(select.selectedOptions.constructor, HTMLCollection);
+  assert_equals(select.selectedOptions.namedItem("named-option"), select.children[2]);
+}, ".selectedOptions should return `HTMLCollection` instance");
+
+test(() => {
   const select = document.getElementById("select-same-object");
   const selectAgain = document.getElementById("select-same-object");
 
   assert_equals(select.selectedOptions, selectAgain.selectedOptions);
 
 }, ".selectedOptions should always return the same value - [SameObject]");
 
 test(() => {
--- a/testing/web-platform/tests/html/syntax/serializing-html-fragments/serializing.html
+++ b/testing/web-platform/tests/html/syntax/serializing-html-fragments/serializing.html
@@ -10,16 +10,17 @@
 <span><a></a></span>
 <span><a b=c></a></span>
 <span><a b='c'></a></span>
 <span><a b='&'></a></span>
 <span><a b='&nbsp;'></a></span>
 <span><a b='"'></a></span>
 <span><a b="<"></a></span>
 <span><a b=">"></a></span>
+<span><a href="javascript:&quot;&lt;>&quot;"></a></span>
 <span><svg xlink:href="a"></svg></span>
 <span><svg xmlns:svg="test"></svg></span>
 <span>a</span>
 <span>&amp;</span>
 <span>&nbsp;</span>
 <span>&lt;</span>
 <span>&gt;</span>
 <span>&quot;</span>
@@ -44,16 +45,17 @@ var expected = [
 ["<a></a>", "<span><a></a></span>"],
 ["<a b=\"c\"></a>", "<span><a b=\"c\"></a></span>"],
 ["<a b=\"c\"></a>", "<span><a b=\"c\"></a></span>"],
 ["<a b=\"&amp;\"></a>", "<span><a b=\"&amp;\"></a></span>"],
 ["<a b=\"&nbsp;\"></a>", "<span><a b=\"&nbsp;\"></a></span>"],
 ["<a b=\"&quot;\"></a>", "<span><a b=\"&quot;\"></a></span>"],
 ["<a b=\"<\"></a>", "<span><a b=\"<\"></a></span>"],
 ["<a b=\">\"></a>", "<span><a b=\">\"></a></span>"],
+["<a href=\"javascript:&quot;<>&quot;\"></a>", "<span><a href=\"javascript:&quot;<>&quot;\"></a></span>"],
 ["<svg xlink:href=\"a\"></svg>", "<span><svg xlink:href=\"a\"></svg></span>"],
 ["<svg xmlns:svg=\"test\"></svg>", "<span><svg xmlns:svg=\"test\"></svg></span>"],
 ["a", "<span>a</span>"],
 ["&amp;", "<span>&amp;</span>"],
 ["&nbsp;", "<span>&nbsp;</span>"],
 ["&lt;", "<span>&lt;</span>"],
 ["&gt;", "<span>&gt;</span>"],
 ["\"", "<span>\"</span>"],
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/document-open-cancels-javascript-url-navigation.html
@@ -0,0 +1,17 @@
+<body>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(t => {
+  window.onload = t.step_func_done(() => assert_equals(i.contentDocument.body.innerText, "PASS"));
+
+  var i = document.createElement('iframe');
+  i.id ='i';
+  i.src = "javascript:'FAIL'";
+  document.body.appendChild(i);
+  i.contentDocument.open();
+  i.contentDocument.write("PASS")
+  i.contentDocument.close();
+});
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/images/fyi-logo/fyi_color.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+     viewBox="0 0 440 440" style="enable-background:new 0 0 440 440;" xml:space="preserve">
+<style type="text/css">
+  .st0{fill:#7ED2EE;}
+  .st1{fill:#003C57;}
+</style>
+<g>
+  <rect x="61.2" y="255.3" class="st0" width="30.4" height="28.3"/>
+  <path class="st1" d="M159.3,103.8c-28.5,0-51.7,23.2-51.7,51.7V284H138v-60.5h28.6v-30.4H138v-37.5c0-11.8,9.6-21.4,21.4-21.4
+    c11.5,0,20.8,9.1,21.3,20.4h30.4C210.6,126.5,187.6,103.8,159.3,103.8z"/>
+  <rect x="302" y="126.3" class="st1" width="30.4" height="28.3"/>
+  <polygon class="st1" points="302.1,176.1 301.9,284 332.3,284 332.4,176.1"/>
+  <path class="st1" d="M284.1,208.4l0-15.5l0-1l0-15.8h-30.4l-0.1,33.8c-0.8,11.1-10.1,19.9-21.3,19.9c-11.8,0-21.4-9.6-21.4-21.4
+    v-32.3h-30.4v32.3c0,28.5,23.2,51.7,51.7,51.7c6.9,0,13.6-1.3,19.9-4l1.3-0.6l0,23.1h0.2v5.8c0,11.8-9.6,21.4-21.4,21.4
+    c-11.5,0-20.8-9.1-21.3-20.4h-30.4c0.5,28.1,23.5,50.8,51.7,50.8c28.5,0,51.7-23.2,51.7-51.7v-3.8H284l0.1-69.9
+    C284.1,209.9,284.1,209.1,284.1,208.4z"/>
+</g>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/images/fyi-logo/fyi_color_bg.svg
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+   viewBox="0 0 440.7 440" style="enable-background:new 0 0 440.7 440;" xml:space="preserve">
+<style type="text/css">
+  .st0{fill:#003C57;}
+  .st1{fill:#7ED2EE;}
+  .st2{fill:#FFFFFF;}
+</style>
+<g>
+  <g>
+    <rect x="0" class="st0" width="440" height="440"/>
+  </g>
+  <g>
+    <rect x="61.2" y="255.3" class="st1" width="30.4" height="28.3"/>
+    <path class="st2" d="M159.3,103.8c-28.5,0-51.7,23.2-51.7,51.7V284H138v-60.5h28.6v-30.4H138v-37.5c0-11.8,9.6-21.4,21.4-21.4
+      c11.5,0,20.8,9.1,21.3,20.4h30.4C210.6,126.5,187.6,103.8,159.3,103.8z"/>
+    <rect x="302" y="126.3" class="st2" width="30.4" height="28.3"/>
+    <polygon class="st2" points="302.1,176.1 301.9,284 332.3,284 332.4,176.1"/>
+    <path class="st2" d="M284.1,208.4l0-15.5l0-1l0-15.8h-30.4l-0.1,33.8c-0.8,11.1-10.1,19.9-21.3,19.9c-11.8,0-21.4-9.6-21.4-21.4
+      v-32.3h-30.4v32.3c0,28.5,23.2,51.7,51.7,51.7c6.9,0,13.6-1.3,19.9-4l1.3-0.6l0,23.1h0.2v5.8c0,11.8-9.6,21.4-21.4,21.4
+      c-11.5,0-20.8-9.1-21.3-20.4h-30.4c0.5,28.1,23.5,50.8,51.7,50.8c28.5,0,51.7-23.2,51.7-51.7v-3.8H284l0.1-69.9
+      C284.1,209.9,284.1,209.1,284.1,208.4z"/>
+  </g>
+</g>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/images/fyi-logo/fyi_monochromatic.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+   viewBox="0 0 440 440" style="enable-background:new 0 0 440 440;" xml:space="preserve">
+<g>
+  <g>
+    <rect x="61.2" y="255.3" width="30.4" height="28.3"/>
+    <path d="M159.3,103.8c-28.5,0-51.7,23.2-51.7,51.7V284H138v-60.5h28.6v-30.4H138v-37.5c0-11.8,9.6-21.4,21.4-21.4
+      c11.5,0,20.8,9.1,21.3,20.4h30.4C210.6,126.5,187.6,103.8,159.3,103.8z"/>
+    <rect x="302" y="126.3" width="30.4" height="28.3"/>
+    <polygon points="302.1,176.1 301.9,284 332.3,284 332.4,176.1     "/>
+    <path d="M284.1,208.4l0-15.5l0-1l0-15.8h-30.4l-0.1,33.8c-0.8,11.1-10.1,19.9-21.3,19.9c-11.8,0-21.4-9.6-21.4-21.4v-32.3h-30.4
+      v32.3c0,28.5,23.2,51.7,51.7,51.7c6.9,0,13.6-1.3,19.9-4l1.3-0.6l0,23.1h0.2v5.8c0,11.8-9.6,21.4-21.4,21.4
+      c-11.5,0-20.8-9.1-21.3-20.4h-30.4c0.5,28.1,23.5,50.8,51.7,50.8c28.5,0,51.7-23.2,51.7-51.7v-3.8H284l0.1-69.9
+      C284.1,209.9,284.1,209.1,284.1,208.4z"/>
+  </g>
+</g>
+</svg>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/images/fyi-logo/fyi_monochromatic_bg.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 22.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+   viewBox="0 0 440.7 440" style="enable-background:new 0 0 440.7 440;" xml:space="preserve">
+<style type="text/css">
+  .st0{fill:#FFFFFF;}
+</style>
+<g>
+  <g>
+    <rect x="0.3" width="440" height="440"/>
+  </g>
+  <g>
+    <rect x="61.5" y="255.3" class="st0" width="30.4" height="28.3"/>
+    <path class="st0" d="M159.7,103.8c-28.5,0-51.7,23.2-51.7,51.7V284h30.4v-60.5h28.6v-30.4h-28.6v-37.5c0-11.8,9.6-21.4,21.4-21.4
+      c11.5,0,20.8,9.1,21.3,20.4h30.4C210.9,126.5,187.9,103.8,159.7,103.8z"/>
+    <rect x="302.3" y="126.3" class="st0" width="30.4" height="28.3"/>
+    <polygon class="st0" points="302.4,176.1 302.2,284 332.6,284 332.8,176.1     "/>
+    <path class="st0" d="M284.5,208.4l0-15.5l0-1l0-15.8h-30.4l-0.1,33.8c-0.8,11.1-10.1,19.9-21.3,19.9c-11.8,0-21.4-9.6-21.4-21.4
+      v-32.3H181v32.3c0,28.5,23.2,51.7,51.7,51.7c6.9,0,13.6-1.3,19.9-4l1.3-0.6l0,23.1h0.2v5.8c0,11.8-9.6,21.4-21.4,21.4
+      c-11.5,0-20.8-9.1-21.3-20.4H181c0.5,28.1,23.5,50.8,51.7,50.8c28.5,0,51.7-23.2,51.7-51.7v-3.8h-0.2l0.1-69.9
+      C284.4,209.9,284.5,209.1,284.5,208.4z"/>
+  </g>
+</g>
+</svg>
--- a/testing/web-platform/tests/infrastructure/metadata/infrastructure/assumptions/allowed-to-play.html.ini
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/assumptions/allowed-to-play.html.ini
@@ -1,8 +1,10 @@
 [allowed-to-play.html]
   expected:
+    if product == "edge_webdriver": TIMEOUT
     if product == "safari": ERROR # https://bugs.webkit.org/show_bug.cgi?id=190775
 
 
   [<audio> autoplay]
     expected:
+      if product == "edge_webdriver": TIMEOUT
       if product == "safari": FAIL # https://bugs.webkit.org/show_bug.cgi?id=190775
--- a/testing/web-platform/tests/infrastructure/metadata/infrastructure/assumptions/html-elements.html.ini
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/assumptions/html-elements.html.ini
@@ -1,9 +1,14 @@
 [html-elements.html]
+  [(pre-req for comparison tests) all CSS short-hand supported]
+    expected:
+      if product == "edge_webdriver": FAIL
+
+
   [Compare CSS span definitions (only valid if pre-reqs pass)]
     expected:
       if product == "safari": FAIL # https://webkit.org/show_bug.cgi?id=187052
 
 
   [Compare CSS div definitions (only valid if pre-reqs pass)]
     expected:
       if product == "safari": FAIL # https://webkit.org/show_bug.cgi?id=187052
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/reftest/size.html.ini
@@ -0,0 +1,4 @@
+[size.html]
+  type: reftest
+  expected:
+    if product == "edge_webdriver": FAIL # https://github.com/web-platform-tests/wpt/issues/15159
--- a/testing/web-platform/tests/infrastructure/metadata/infrastructure/server/context.any.js.ini
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/server/context.any.js.ini
@@ -1,4 +1,5 @@
 [context.any.sharedworker.html]
   [context]
     expected:
+      if product == "edge_webdriver": FAIL
       if product == "safari": FAIL # https://bugs.webkit.org/show_bug.cgi?id=149850
--- a/testing/web-platform/tests/infrastructure/metadata/infrastructure/server/order-of-metas.any.js.ini
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/server/order-of-metas.any.js.ini
@@ -1,4 +1,27 @@
+[order-of-metas.any.worker.html]
+  expected:
+    if product == "edge_webdriver": TIMEOUT
+
+
+[order-of-metas.any.html]
+  [<meta name=timeout> exists]
+    expected:
+      if product == "edge_webdriver": FAIL
+
+
 [order-of-metas.any.sharedworker.html]
+  [foo\n]
+    expected:
+      if product == "edge_webdriver": FAIL
+
+
   [foo]
     expected:
+      if product == "edge_webdriver": FAIL
       if product == "safari": FAIL # https://bugs.webkit.org/show_bug.cgi?id=149850
+
+
+[order-of-metas.window.html]
+  [<meta name=timeout> exists]
+    expected:
+      if product == "edge_webdriver": FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/server/order-of-metas.window.js.ini
@@ -0,0 +1,4 @@
+[order-of-metas.window.html]
+  [<meta name=timeout> exists]
+    expected:
+      if product == "edge_webdriver": FAIL
--- a/testing/web-platform/tests/infrastructure/metadata/infrastructure/server/secure-context.https.any.js.ini
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/server/secure-context.https.any.js.ini
@@ -1,4 +1,5 @@
 [secure-context.https.any.sharedworker.html]
   [secure-context]
     expected:
+      if product == "edge_webdriver": FAIL
       if product == "safari": FAIL # https://bugs.webkit.org/show_bug.cgi?id=149850
--- a/testing/web-platform/tests/infrastructure/metadata/infrastructure/server/title.any.js.ini
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/server/title.any.js.ini
@@ -1,4 +1,20 @@
+[title.any.html]
+  [foobar\n]
+    expected:
+      if product == "edge_webdriver": FAIL
+
+
 [title.any.sharedworker.html]
+  [foobar\n]
+    expected:
+      if product == "edge_webdriver": FAIL
+
+
   [foobar]
     expected:
       if product == "safari": FAIL # https://bugs.webkit.org/show_bug.cgi?id=149850
+
+
+[title.any.worker.html]
+  expected:
+    if product == "edge_webdriver": TIMEOUT
deleted file mode 100644
--- a/testing/web-platform/tests/infrastructure/metadata/infrastructure/testdriver/actions/elementTiming.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[elementTiming.html]
-  [TestDriver actions: element timing]
-    expected:
-      if product == "chrome": 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,7 +1,3 @@
 [eventOrder.html]
   expected:
     if product == "safari": ERROR
-
-  [TestDriver actions: event order]
-    expected:
-      if product == "chrome": FAIL
--- a/testing/web-platform/tests/infrastructure/metadata/infrastructure/testdriver/actions/multiDevice.html.ini
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/testdriver/actions/multiDevice.html.ini
@@ -1,3 +1,3 @@
 [multiDevice.html]
   expected:
-    if product == "chrome" or product == "safari": ERROR
+    if product == "safari": ERROR
--- a/testing/web-platform/tests/infrastructure/metadata/infrastructure/testdriver/actions/pause.html.ini
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/testdriver/actions/pause.html.ini
@@ -1,7 +1,3 @@
 [pause.html]
   expected:
     if product == "safari": ERROR
-
-  [TestDriver actions: pause]
-    expected:
-      if product == "chrome": FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/infrastructure/metadata/infrastructure/testdriver/file_upload.sub.html.ini
@@ -0,0 +1,3 @@
+[file_upload.sub.html]
+  expected:
+    if product == "edge_webdriver": ERROR
--- a/testing/web-platform/tests/interfaces/html.idl
+++ b/testing/web-platform/tests/interfaces/html.idl
@@ -1091,18 +1091,18 @@ typedef (CanvasRenderingContext2D or Ima
 [Exposed=Window,
  HTMLConstructor]
 interface HTMLCanvasElement : HTMLElement {
   [CEReactions] attribute unsigned long width;
   [CEReactions] attribute unsigned long height;
 
   RenderingContext? getContext(DOMString contextId, optional any options = null);
 
-  USVString toDataURL(optional DOMString type, optional any quality);
-  void toBlob(BlobCallback _callback, optional DOMString type, optional any quality);
+  USVString toDataURL(optional DOMString type = "image/png", optional any quality);
+  void toBlob(BlobCallback _callback, optional DOMString type = "image/png", optional any quality);
   OffscreenCanvas transferControlToOffscreen();
 };
 
 callback BlobCallback = void (Blob? blob);
 
 typedef (HTMLImageElement or
          SVGImageElement) HTMLOrSVGImageElement;
 
@@ -1352,17 +1352,17 @@ interface ImageBitmapRenderingContext {
 dictionary ImageBitmapRenderingContextSettings {
   boolean alpha = true;
 };
 
 typedef (OffscreenCanvasRenderingContext2D or WebGLRenderingContext or WebGL2RenderingContext) OffscreenRenderingContext;
 
 dictionary ImageEncodeOptions {
   DOMString type = "image/png";
-  unrestricted double quality = 1.0;
+  unrestricted double quality;
 };
 
 enum OffscreenRenderingContextId { "2d", "webgl", "webgl2" };
 
 [Constructor([EnforceRange] unsigned long long width, [EnforceRange] unsigned long long height), Exposed=(Window,Worker), Transferable]
 interface OffscreenCanvas : EventTarget {
   attribute [EnforceRange] unsigned long long width;
   attribute [EnforceRange] unsigned long long height;
--- a/testing/web-platform/tests/interfaces/mediasession.idl
+++ b/testing/web-platform/tests/interfaces/mediasession.idl
@@ -16,17 +16,17 @@ enum MediaSessionPlaybackState {
 
 enum MediaSessionAction {
   "play",
   "pause",
   "seekbackward",
   "seekforward",
   "previoustrack",
   "nexttrack",
-  "skip-ad",
+  "skipad",
 };
 
 callback MediaSessionActionHandler = void();
 
 [Exposed=Window]
 interface MediaSession {
   attribute MediaMetadata? metadata;
 
--- a/testing/web-platform/tests/interfaces/netinfo.idl
+++ b/testing/web-platform/tests/interfaces/netinfo.idl
@@ -17,17 +17,16 @@ enum ConnectionType {
 
 enum EffectiveConnectionType {
   "2g",
   "3g",
   "4g",
   "slow-2g"
 };
 
-[NoInterfaceObject, Exposed=(Window,Worker)]
 interface mixin NavigatorNetworkInformation {
   readonly attribute NetworkInformation connection;
 };
 
 Navigator includes NavigatorNetworkInformation;
 WorkerNavigator includes NavigatorNetworkInformation;
 
 [Exposed=(Window,Worker)]
--- a/testing/web-platform/tests/interfaces/proximity.idl
+++ b/testing/web-platform/tests/interfaces/proximity.idl
@@ -4,8 +4,14 @@
 // Source: Proximity Sensor (https://w3c.github.io/proximity/)
 
 [Constructor(optional SensorOptions sensorOptions), SecureContext, Exposed=Window]
 interface ProximitySensor : Sensor {
   readonly attribute double? distance;
   readonly attribute double? max;
   readonly attribute boolean? near;
 };
+
+dictionary ProximityReadingValues {
+  required double? distance;
+  required double? max;
+  required boolean? near;
+};
--- a/testing/web-platform/tests/interfaces/webrtc.idl
+++ b/testing/web-platform/tests/interfaces/webrtc.idl
@@ -623,16 +623,16 @@ enum RTCErrorDetailType {
               "idp-token-invalid",
               "sctp-failure",
               "sdp-syntax-error",
               "hardware-encoder-not-available",
               "hardware-encoder-error"
           };
 
 [Exposed=Window,
- Constructor(DOMString type, RTCErrorEventInit eventInitDict)]
+ Constructor(DOMString type, optional RTCErrorEventInit eventInitDict)]
 interface RTCErrorEvent : Event {
     readonly        attribute RTCError? error;
 };
 
 dictionary RTCErrorEventInit : EventInit {
              RTCError? error = null;
 };
--- a/testing/web-platform/tests/interfaces/webxr.idl
+++ b/testing/web-platform/tests/interfaces/webxr.idl
@@ -88,33 +88,30 @@ callback XRFrameRequestCallback = void (
 };
 
 enum XRReferenceSpaceType {
   "stationary",
   "bounded",
   "unbounded"
 };
 
-dictionary XRReferenceSpaceOptions {
-  required XRReferenceSpaceType type;
-};
-
-[SecureContext, Exposed=Window] interface XRReferenceSpace : XRSpace {
-  attribute XRRigidTransform originOffset;
-  attribute EventHandler onreset;
-};
-
 enum XRStationaryReferenceSpaceSubtype {
   "eye-level",
   "floor-level",
   "position-disabled"
 };
 
-dictionary XRStationaryReferenceSpaceOptions : XRReferenceSpaceOptions {
-  required XRStationaryReferenceSpaceSubtype subtype;
+dictionary XRReferenceSpaceOptions {
+  required XRReferenceSpaceType type;
+  XRStationaryReferenceSpaceSubtype subtype;
+};
+
+[SecureContext, Exposed=Window] interface XRReferenceSpace : XRSpace {
+  attribute XRRigidTransform originOffset;
+  attribute EventHandler onreset;
 };
 
 [SecureContext, Exposed=Window]
 interface XRStationaryReferenceSpace : XRReferenceSpace {
   readonly attribute XRStationaryReferenceSpaceSubtype subtype;
 };
 
 [SecureContext, Exposed=Window]
--- a/testing/web-platform/tests/lint.whitelist
+++ b/testing/web-platform/tests/lint.whitelist
@@ -795,9 +795,9 @@ LAYOUTTESTS APIS: css/css-regions/intera
 LAYOUTTESTS APIS: resources/chromium/generic_sensor_mocks.js
 
 # Gecko additons to remove
 CSS-COLLIDING-REF-NAME: css/css-contain/reference/contain-size-fieldset-001-ref.html
 CSS-COLLIDING-REF-NAME: css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-size-fieldset-001-ref.html
 
 # Signed Exchange files have hard-coded URLs in the certUrl field
 WEB-PLATFORM.TEST:signed-exchange/resources/*.sxg
-WEB-PLATFORM.TEST:signed-exchange/resources/generate-test-sxgs.sh
+WEB-PLATFORM.TEST:signed-exchange/resources/generate-test-sxgs.sh
\ No newline at end of file
--- a/testing/web-platform/tests/media-capabilities/encodingInfo.html
+++ b/testing/web-platform/tests/media-capabilities/encodingInfo.html
@@ -282,17 +282,29 @@ promise_test(t => {
     type: 'record',
     video: minimalVideoConfiguration,
     audio: minimalAudioConfiguration,
   }).then(ability => {
     assert_equals(typeof ability.supported, "boolean");
     assert_equals(typeof ability.smooth, "boolean");
     assert_equals(typeof ability.powerEfficient, "boolean");
   });
-}, "Test that encodingInfo returns a valid MediaCapabilitiesInfo objects");
+}, "Test that encodingInfo returns a valid MediaCapabilitiesInfo objects for record type");
+
+promise_test(t => {
+  return navigator.mediaCapabilities.encodingInfo({
+    type: 'transmission',
+    video: minimalVideoConfiguration,
+    audio: minimalAudioConfiguration,
+  }).then(ability => {
+    assert_equals(typeof ability.supported, "boolean");
+    assert_equals(typeof ability.smooth, "boolean");
+    assert_equals(typeof ability.powerEfficient, "boolean");
+  });
+}, "Test that encodingInfo returns a valid MediaCapabilitiesInfo objects for transmission type");
 
 async_test(t => {
   var validTypes = [ 'record', 'transmission' ];
   var invalidTypes = [ undefined, null, '', 'foobar', 'mse', 'MediaSource',
                        'file', 'media-source', ];
 
   var validPromises = [];
   var invalidCaught = 0;
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/performance-timeline/po-observe-type.any.js
@@ -0,0 +1,54 @@
+// META: script=performanceobservers.js
+
+test(() => {
+  const obs = new PerformanceObserver(() =>{});
+  obs.observe({entryTypes: ["mark"]});
+  assert_throws('InvalidModificationError', function () {
+    obs.observe({type: "measure"});
+  });
+}, "Calling observe() with entryTypes and then type should throw an InvalidModificationError");
+
+test(() => {
+  const obs = new PerformanceObserver(() =>{});
+  obs.observe({type: "mark"});
+  assert_throws('InvalidModificationError', function () {
+    obs.observe({entryTypes: ["measure"]});
+  });
+}, "Calling observe() with type and then entryTypes should throw an InvalidModificationError");
+
+test(() => {
+  const obs = new PerformanceObserver(() =>{});
+  assert_throws(new SyntaxError(), function () {
+    obs.observe({type: "mark", entryTypes: ["measure"]});
+  });
+}, "Calling observe() with type and entryTypes should throw a SyntaxError");
+
+test(function () {
+  const obs = new PerformanceObserver(() =>{});
+  // Definitely not an entry type.
+  obs.observe({type: "this-cannot-match-an-entryType"});
+  // Close to an entry type, but not quite.
+  obs.observe({type: "marks"});
+}, "Passing in unknown values to type does throw an exception.");
+
+async_test(function (t) {
+  let observedMark = false;
+  let observedMeasure = false;
+  const observer = new PerformanceObserver(
+    t.step_func(function (entryList, obs) {
+      observedMark |= entryList.getEntries().filter(
+        entry => entry.entryType === 'mark').length;
+      observedMeasure |= entryList.getEntries().filter(
+        entry => entry.entryType === 'measure').length
+      // Only conclude the test once we receive both entries!
+      if (observedMark && observedMeasure) {
+        observer.disconnect();
+        t.done();
+      }
+    })
+  );
+  observer.observe({type: "mark"});
+  observer.observe({type: "measure"});
+  self.performance.mark("mark1");
+  self.performance.measure("measure1");
+}, "observe() with different type values stacks.");
--- a/testing/web-platform/tests/performance-timeline/po-observe.any.js
+++ b/testing/web-platform/tests/performance-timeline/po-observe.any.js
@@ -1,36 +1,36 @@
 // META: script=performanceobservers.js
 
   test(function () {
     var obs = new PerformanceObserver(function () { return true; });
-    assert_throws(new TypeError(), function () {
+    assert_throws(new SyntaxError(), function () {
       obs.observe({});
     });
-    assert_throws(new TypeError(), function () {
+    assert_throws(new SyntaxError(), function () {
       obs.observe({entryType: []});
     });
-  }, "no entryTypes throws a TypeError");
+  }, "no 'type' or 'entryTypes' throws a SyntaxError");
   test(function () {
     var obs = new PerformanceObserver(function () { return true; });
     assert_throws(new TypeError(), function () {
       obs.observe({entryTypes: "mark"});
     });
   }, "entryTypes must be a sequence or throw a TypeError");
 
   test(function () {
     var obs = new PerformanceObserver(function () { return true; });
     obs.observe({entryTypes: []});
-  }, "Empty sequence entryTypes is a no-op");
+  }, "Empty sequence entryTypes does not throw an exception.");
 
   test(function () {
     var obs = new PerformanceObserver(function () { return true; });
     obs.observe({entryTypes: ["this-cannot-match-an-entryType"]});
     obs.observe({entryTypes: ["marks","navigate", "resources"]});
-  }, "Unknown entryTypes are no-op");
+  }, "Unknown entryTypes do not throw an exception.");
 
   test(function () {
     var obs = new PerformanceObserver(function () { return true; });
     obs.observe({entryTypes: ["mark","this-cannot-match-an-entryType"]});
     obs.observe({entryTypes: ["this-cannot-match-an-entryType","mark"]});
     obs.observe({entryTypes: ["mark"], others: true});
   }, "Filter unsupported entryType entryType names within the entryTypes sequence");
 
--- a/testing/web-platform/tests/pointerevents/pointerevent_suppress_compat_events_on_click.html
+++ b/testing/web-platform/tests/pointerevents/pointerevent_suppress_compat_events_on_click.html
@@ -22,28 +22,28 @@
       function end_of_test() {
           showLoggedEvents();
           showPointerTypes();
       }
 
       function end_of_interaction() {
           test(function () {
               assert_equals(event_log.join(", "),
-                  "mousedown@target1, mouseup@target1");
+                  "click@target0, mousedown@target1, mouseup@target1, click@target1");
           }, "Event log");
 
           test_pointerEvent.done(); // complete test
       }
 
       function run() {
           on_event(document.getElementById("done"), "click", end_of_interaction);
 
           var target_list = ["target0", "target1"];
           var pointer_event_list = ["pointerdown"];
-          var mouse_event_list = ["mousedown", "mouseup"];
+          var mouse_event_list = ["mousedown", "mouseup", "click"];
 
           target_list.forEach(function(targetId) {
               var target = document.getElementById(targetId);
 
               pointer_event_list.forEach(function(eventName) {
                   on_event(target, eventName, function (event) {
                       detected_pointertypes[event.pointerType] = true;
                       var label = event.type + "@" + targetId;
@@ -90,17 +90,17 @@
         margin: 20px;
         border: 2px solid black;
       }
     </style>
   </head>
   <body onload="run()">
     <h1>Pointer Event: Suppress compatibility mouse events on click</h1>
     <h4>
-      When a pointerdown is canceled, a click/tap shouldn't fire any compatibility mouse events.
+      When a pointerdown is canceled, a click/tap shouldn't fire any compatibility mouse events except click event.
     </h4>
     <ol>
       <li> Click or tap on Target0.</li>
       <li> Click or tap on Target1.</li>
       <li> Click Done.</li>
     </ol>
     <div id="target0">
       Target0
--- a/testing/web-platform/tests/portals/portal-activate-event.html
+++ b/testing/web-platform/tests/portals/portal-activate-event.html
@@ -1,32 +1,38 @@
 <!DOCTYPE html>
 <title>Tests that the PortalActivateEvent is dispatched when a portal is activated</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script>
   async_test(function(t) {
-    var bc = new BroadcastChannel("test-eventlistener");
+    let test = "eventlistener";
+    var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
       assert_equals(e.data, "passed");
       bc.close();
     });
-    window.open("resources/portal-activate-event-window.html?test=eventlistener");
+    const portalUrl = encodeURIComponent(`portal-activate-event-portal.html?test=${test}`);
+    window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}&channelName=portal-${test}`);
   }, "Tests that the PortalActivateEvent is dispatched when a portal is activated.");
 
   async_test(function(t) {
-    var bc = new BroadcastChannel("test-eventhandler");
+    let test = "eventhandler";
+    var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
       assert_equals(e.data, "passed");
       bc.close();
     });
-    window.open("resources/portal-activate-event-window.html?test=eventhandler");
+    const portalUrl = encodeURIComponent(`portal-activate-event-portal.html?test=${test}`);
+    window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}&channelName=portal-${test}`);
   }, "Tests that the portalactivate event handler is dispatched when a portal is activated.");
 
   async_test(function(t) {
-    var bc = new BroadcastChannel("test-bodyeventhandler");
+    let test = "bodyeventhandler";
+    var bc = new BroadcastChannel(`test-${test}`);
     bc.onmessage = t.step_func_done(function(e) {
       assert_equals(e.data, "passed");
       bc.close();
     });
-    window.open("resources/portal-activate-event-window.html?test=bodyeventhandler");
+    const portalUrl = encodeURIComponent(`portal-activate-event-portal.html?test=${test}`);
+    window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}&channelName=portal-${test}`);
   }, "Tests that the HTMLBodyElement has the portalactivate event handler.");
 </script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/portals/portals-activate-no-browsing-context.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+promise_test(async t => {
+  let activatePromise = document.createElement('portal').activate();
+  await promise_rejects(t, 'InvalidStateError', activatePromise);
+}, "A portal with nothing in it cannot be activated");
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/portals/portals-cross-origin-load.sub.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+  promise_test(async () => {
+    var bc = new BroadcastChannel("portals-cross-origin-load");
+    var receiveMessage = new Promise((resolve, reject) => {
+      bc.onmessage = e => {
+        bc.close();
+        resolve();
+      }
+    });
+    var portal = document.createElement("portal");
+    portal.src = "http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/portal-cross-origin.sub.html";
+    document.body.appendChild(portal);
+    return receiveMessage;
+  });
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/portals/portals-host-exposure.sub.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+  let channelIndex = 0;
+  async function openPortalAndReceiveMessage(portalSrc) {
+    let channelName = `portals-host-exposure-${channelIndex++}`
+    let broadcastChannel = new BroadcastChannel(channelName);
+    try {
+      let received = new Promise((resolve, reject) => {
+        broadcastChannel.addEventListener('message', e => {
+          resolve(e.data);
+        }, {once: true})
+      });
+      let portal = document.createElement('portal');
+      portal.src = `${portalSrc}?broadcastchannel=${channelName}`;
+      document.body.appendChild(portal);
+      return await received;
+    } finally {
+      broadcastChannel.close();
+    }
+  }
+
+  promise_test(async t => {
+    let {hasHost} = await openPortalAndReceiveMessage(
+        'resources/portal-host.html');
+    assert_true(hasHost, "window.portalHost should be defined");
+  }, "window.portalHost should be exposed in same-origin portal");
+
+  promise_test(async t => {
+    let {hasHost} = await openPortalAndReceiveMessage(
+        'http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/portal-host-cross-origin.sub.html');
+    assert_true(hasHost, "window.portalHost should be defined");
+  }, "window.portalHost should be exposed in cross-origin portal");
+
+  promise_test(async t => {
+    let {hasHost} = await openPortalAndReceiveMessage(
+        'resources/portal-host-cross-origin-navigate.sub.html');
+    assert_true(hasHost, "window.portalHost should be defined");
+  }, "window.portalHost should be exposed in portal after cross-origin navigation");
+
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/portals/portals-host-hidden-after-activation.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<script>
+  // Waits for 2 messages from portal, one before activation and one after.
+  function waitForMessages() {
+    return new Promise((resolve, reject) => {
+      var results = [];
+      var bc = new BroadcastChannel("portals-host-hidden-after-activation");
+      bc.onmessage = e => {
+        results.push(e.data.hasHost);
+        if (results.length == 2) {
+          bc.close();
+          resolve(results);
+        }
+      };
+    });
+  }
+
+  promise_test(async () => {
+    const portalUrl = encodeURIComponent("portal-host-hidden-after-activation-portal.html");
+    window.open(`resources/portal-embed-and-activate.html?url=${portalUrl}`);
+    var results = await waitForMessages();
+    assert_true(results[0], "portalHost exposed before calling activate()");
+    assert_false(results[1], "portalHost hidden after receiving portalactivate event");
+  }, "window.portalHost should be null after portal is activated");
+</script>
+</body>
deleted file mode 100644
--- a/testing/web-platform/tests/portals/resources/portal-activate-event-window.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<script>
-  window.onload = function(e) {
-    var test = (new URL(location)).searchParams.get("test");
-    var portal = document.createElement("portal");
-    portal.src = "portal-activate-event-portal.html" + location.search;
-    document.body.appendChild(portal);
-
-    var bc = new BroadcastChannel("portal-" + test);
-    bc.onmessage = function(e) {
-      document.querySelector("portal").activate();
-      bc.close();
-    }
-  }
-</script>
-<body>
-</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/portals/resources/portal-cross-origin.sub.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<body>
+  <script>
+    var iframe = document.createElement("iframe");
+    iframe.src = "http://{{host}}:{{ports[http][0]}}/portals/resources/portal-forward-with-broadcast.html?broadcastchannel=portals-cross-origin-load";
+    iframe.onload = e => {
+      iframe.contentWindow.postMessage("loaded", "*");
+    }
+    document.body.appendChild(iframe);
+  </script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/portals/resources/portal-embed-and-activate.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<!--
+  Embeds a portal (src specified by query parameter "url") and activates it after
+  receiving a message from the portal. Use query parameter "channelName" to
+  specify the name of the channel used by the portal src send a message
+  indicating that it is ready for activation (default name used is "portal").
+-->
+</title>
+<body>
+  <script>
+    var searchParams = new URL(location).searchParams;
+
+    // TODO(adithyas): Replace this with postmessage once it's implemented for
+    // portals.
+    var channelName = searchParams.get("channelName") || "portal";
+    var bc = new BroadcastChannel(channelName);
+    bc.onmessage = function(e) {
+      document.querySelector("portal").activate();
+      bc.close();
+    }
+
+    let portal = document.createElement("portal");
+    portal.src = searchParams.get("url");
+    document.body.appendChild(portal);
+  </script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/portals/resources/portal-forward-with-broadcast.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<body>
+  <script>
+    function forwardMessage(e) {
+      let broadcastChannel = new BroadcastChannel(new URL(location).searchParams.get('broadcastchannel'));
+      try {
+        broadcastChannel.postMessage(e.data);
+      } finally {
+        broadcastChannel.close();
+      }
+    }
+    window.addEventListener("message", forwardMessage);
+  </script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/portals/resources/portal-host-cross-origin-navigate.sub.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<body>
+  <script>
+    let channelName = new URL(location).searchParams.get('broadcastchannel');
+    window.location.href = `http://{{hosts[alt][www]}}:{{ports[http][0]}}/portals/resources/portal-host-cross-origin.sub.html?broadcastchannel=${channelName}`;
+  </script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/portals/resources/portal-host-cross-origin.sub.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<body>
+  <script>
+    let forwardingIframe = document.createElement('iframe');
+    let channelName = new URL(location).searchParams.get('broadcastchannel');
+    forwardingIframe.src = `http://{{host}}:{{ports[http][0]}}/portals/resources/portal-forward-with-broadcast.html?broadcastchannel=${channelName}`;
+    forwardingIframe.onload = () => {
+      let message = {
+        hasHost: !!window.portalHost
+      };
+      forwardingIframe.contentWindow.postMessage(message, '*');
+    }
+    document.body.appendChild(forwardingIframe);
+  </script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/portals/resources/portal-host-hidden-after-activation-portal.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<script>
+  window.addEventListener("portalactivate", function(e) {
+    var bc = new BroadcastChannel("portals-host-hidden-after-activation");
+    bc.postMessage({ hasHost: !!window.portalHost });
+    bc.close();
+  });
+
+  var bc = new BroadcastChannel("portals-host-hidden-after-activation");
+  bc.postMessage({hasHost: !!window.portalHost });
+  bc.close();
+
+  bc = new BroadcastChannel("portal");
+  bc.postMessage("loaded");
+  bc.close();
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/portals/resources/portal-host.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<body>
+  <script>
+    let message = {
+      hasHost: !!window.portalHost
+    };
+    let broadcastChannel = new BroadcastChannel(new URL(location).searchParams.get('broadcastchannel'));
+    try {
+      broadcastChannel.postMessage(message);
+    } finally {
+      broadcastChannel.close();
+    }
+  </script>
+</body>
--- a/testing/web-platform/tests/resources/idlharness.js
+++ b/testing/web-platform/tests/resources/idlharness.js
@@ -2304,38 +2304,38 @@ IdlInterface.prototype.do_member_operati
         // interface.  (Have to be sure to get inheritance right.)
         throwOrReject(a_test, member, memberHolderObject[member.name], {}, args,
                       "calling operation with this = {} didn't throw TypeError", cb);
     } else {
         done();
     }
 }
 
-IdlInterface.prototype.test_to_json_operation = function(memberHolderObject, member) {
+IdlInterface.prototype.test_to_json_operation = function(desc, memberHolderObject, member) {
     var instanceName = memberHolderObject && memberHolderObject.constructor.name
         || member.name + " object";
     if (member.has_extended_attribute("Default")) {
         subsetTestByKey(this.name, test, function() {
             var map = this.default_to_json_operation();
             var json = memberHolderObject.toJSON();
             map.forEach(function(type, k) {
                 assert_true(k in json, "property " + JSON.stringify(k) + " should be present in the output of " + this.name + ".prototype.toJSON()");
                 var descriptor = Object.getOwnPropertyDescriptor(json, k);
                 assert_true(descriptor.writable, "property " + k + " should be writable");
                 assert_true(descriptor.configurable, "property " + k + " should be configurable");
                 assert_true(descriptor.enumerable, "property " + k + " should be enumerable");
                 this.array.assert_type_is(json[k], type);
                 delete json[k];
             }, this);
-        }.bind(this), "Test default toJSON operation of " + instanceName);
+        }.bind(this), this.name + " interface: default toJSON operation on " + desc);
     } else {
         subsetTestByKey(this.name, test, function() {
             assert_true(this.array.is_json_type(member.idlType), JSON.stringify(member.idlType) + " is not an appropriate return value for the toJSON operation of " + instanceName);
             this.array.assert_type_is(memberHolderObject.toJSON(), member.idlType);
-        }.bind(this), "Test toJSON operation of " + instanceName);
+        }.bind(this), this.name + " interface: toJSON operation on " + desc);
     }
 };
 
 IdlInterface.prototype.test_member_iterable = function(member)
 {
     subsetTestByKey(this.name, test, function()
     {
         var isPairIterator = member.idlType.length === 2;
@@ -2717,17 +2717,17 @@ IdlInterface.prototype.test_interface_of
                 }
                 if (minLength === 0) {
                     cb();
                 }
             }.bind(this));
         }
 
         if (member.is_to_json_regular_operation()) {
-            this.test_to_json_operation(obj, member);
+            this.test_to_json_operation(desc, obj, member);
         }
     }
 };
 
 IdlInterface.prototype.has_stringifier = function()
 {
     if (this.name === "DOMException") {
         // toString is inherited from Error, so don't assume we have the
--- a/testing/web-platform/tests/resources/test/tests/functional/idlharness/IdlInterface/test_to_json_operation.html
+++ b/testing/web-platform/tests/resources/test/tests/functional/idlharness/IdlInterface/test_to_json_operation.html
@@ -24,156 +24,156 @@
             return this._obj;
         }
         Object.defineProperty(F, 'name', { value: member.name });
         return new F(obj);
     }
 
     var i, obj;
     i = interfaceFrom("interface A { [Default] object toJSON(); attribute long foo; };");
-    i.test_to_json_operation(wrap(i, { foo: 123 }), i.members[0]);
+    i.test_to_json_operation("object", wrap(i, { foo: 123 }), i.members[0]);
 
     // should fail (wrong type)
     i = interfaceFrom("interface B { [Default] object toJSON(); attribute long foo; };");
-    i.test_to_json_operation(wrap(i, { foo: "a value" }), i.members[0]);
+    i.test_to_json_operation("object", wrap(i, { foo: "a value" }), i.members[0]);
 
     // should handle extraneous attributes (e.g. from an extension specification)
     i = interfaceFrom("interface C { [Default] object toJSON(); attribute long foo; };");
-    i.test_to_json_operation(wrap(i, { foo: 123, bar: 456 }), i.members[0]);
+    i.test_to_json_operation("object", wrap(i, { foo: 123, bar: 456 }), i.members[0]);
 
     // should fail (missing property)
     i = interfaceFrom("interface D { [Default] object toJSON(); attribute long foo; };");
-    i.test_to_json_operation(wrap(i, { }), i.members[0]);
+    i.test_to_json_operation("object", wrap(i, { }), i.members[0]);
 
     // should fail (should be writable)
     obj = Object.defineProperties({}, { foo: {
         writable: false,
         enumerable: true,
         configurable: true,
         value: 123
     }});
     i = interfaceFrom("interface F { [Default] object toJSON(); attribute long foo; };");
-    i.test_to_json_operation(wrap(i, obj), i.members[0]);
+    i.test_to_json_operation("object", wrap(i, obj), i.members[0]);
 
     // should fail (should be enumerable)
     obj = Object.defineProperties({}, { foo: {
         writable: true,
         enumerable: false,
         configurable: true,
         value: 123
     }});
     i = interfaceFrom("interface G { [Default] object toJSON(); attribute long foo; };");
-    i.test_to_json_operation(wrap(i, obj), i.members[0]);
+    i.test_to_json_operation("object", wrap(i, obj), i.members[0]);