summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/mozilla/tests/dom
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/mozilla/tests/dom
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/mozilla/tests/dom')
-rw-r--r--testing/web-platform/mozilla/tests/dom/classList.html526
-rw-r--r--testing/web-platform/mozilla/tests/dom/delayed_window_print.html39
-rw-r--r--testing/web-platform/mozilla/tests/dom/dispatch_select_event.html35
-rw-r--r--testing/web-platform/mozilla/tests/dom/focus-invalid-uri-link.html63
-rw-r--r--testing/web-platform/mozilla/tests/dom/fs/fs-writable_unlocked_on_tab_close.https.window.js70
-rw-r--r--testing/web-platform/mozilla/tests/dom/fs/support/fs-open_writable_after_trigger.sub.html45
-rw-r--r--testing/web-platform/mozilla/tests/dom/fs/support/fs-open_writable_then_close_tab.sub.html20
-rw-r--r--testing/web-platform/mozilla/tests/dom/fs/support/testHelpers.js15
-rw-r--r--testing/web-platform/mozilla/tests/dom/range-in-two-selections.html34
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/resources/test.html5
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/resources/throttling.js136
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/resources/ws.sub.js3
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-1.window.js10
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-2.window.js11
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-3.window.js11
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-4.window.js11
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-indexeddb.window.js35
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-webaudio.window.js35
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-webrtc.window.js35
-rw-r--r--testing/web-platform/mozilla/tests/dom/throttling/throttling-ws.window.js37
20 files changed, 1176 insertions, 0 deletions
diff --git a/testing/web-platform/mozilla/tests/dom/classList.html b/testing/web-platform/mozilla/tests/dom/classList.html
new file mode 100644
index 0000000000..21d79f49e3
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/classList.html
@@ -0,0 +1,526 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test for the classList element attribute</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id="content"></div>
+<script>
+// This should be the same as dom/nodes/Element-classlist.html in the upstream
+// tests! We have a couple of bits changed, which are marked with comments
+// "LOCAL MODIFICATION". Do not change this without changing the upstream test
+// as well! Merging upstream changes here occasionally might also be nice.
+
+const SVG_NS = "http://www.w3.org/2000/svg";
+const XHTML_NS = "http://www.w3.org/1999/xhtml"
+const MATHML_NS = "http://www.w3.org/1998/Math/MathML";
+
+// BEGIN LOCAL MODIFICATION: The spec does not have the onAttrModified event
+// and does not want it, but we still support it.
+var gMutationEvents = [];
+
+function onAttrModified(event) {
+ assert_equals(event.attrName, "class", "mutation on unexpected attribute");
+
+ gMutationEvents.push({
+ attrChange: event.attrChange,
+ prevValue: event.prevValue,
+ newValue: event.newValue,
+ });
+}
+// END LOCAL MODIFICATION
+
+function setClass(e, newVal) {
+ if (newVal === null) {
+ e.removeAttribute("class");
+ } else {
+ e.setAttribute("class", newVal);
+ }
+}
+
+function checkModification(e, funcName, args, expectedRes, before, after,
+ expectedException, desc) {
+ if (!Array.isArray(args)) {
+ args = [args];
+ }
+
+ test(function() {
+ var shouldThrow = typeof(expectedException) === "string";
+ if (shouldThrow) {
+ // If an exception is thrown, the class attribute shouldn't change.
+ after = before;
+ }
+ setClass(e, before);
+
+ // BEGIN LOCAL MODIFICATION
+ gMutationEvents = [];
+ e.addEventListener("DOMAttrModified", onAttrModified);
+ // END LOCAL MODIFICATION
+ var obs;
+ // If we have MutationObservers available, do some checks to make
+ // sure attribute sets are happening at sane times.
+ if (self.MutationObserver) {
+ obs = new MutationObserver(() => {});
+ obs.observe(e, { attributes: true });
+ }
+ if (shouldThrow) {
+ assert_throws_dom(expectedException, function() {
+ var list = e.classList;
+ var res = list[funcName].apply(list, args);
+ });
+ } else {
+ var list = e.classList;
+ var res = list[funcName].apply(list, args);
+ }
+ if (obs) {
+ var mutationRecords = obs.takeRecords();
+ obs.disconnect();
+ if (shouldThrow) {
+ assert_equals(mutationRecords.length, 0,
+ "There should have been no mutation");
+ } else if (funcName == "replace") {
+ assert_equals(mutationRecords.length == 1,
+ expectedRes,
+ "Should have a mutation exactly when replace() returns true");
+ } else {
+ // For other functions, would need to check when exactly
+ // mutations are supposed to happen.
+ }
+ }
+ // BEGIN LOCAL MODIFICATION
+ e.removeEventListener("DOMAttrModified", onAttrModified);
+ // END LOCAL MODIFICATION
+ if (!shouldThrow) {
+ assert_equals(res, expectedRes, "wrong return value");
+ }
+
+ var expectedAfter = after;
+
+ assert_equals(e.getAttribute("class"), expectedAfter,
+ "wrong class after modification");
+ // BEGIN LOCAL MODIFICATION
+ var expectedMutation = before != after;
+ assert_equals(gMutationEvents.length, expectedMutation ? 1 : 0,
+ "unexpected mutation event count");
+ if (expectedMutation && gMutationEvents.length) {
+ assert_equals(gMutationEvents[0].attrChange,
+ before == null ? MutationEvent.ADDITION
+ : MutationEvent.MODIFICATION,
+ "wrong type of attribute change");
+ // If there wasn't any previous attribute, prevValue will return an empty
+ // string.
+ var expectedPrevValue = before === null ? "" : before;
+ assert_equals(gMutationEvents[0].prevValue, expectedPrevValue,
+ "wrong previous value");
+ assert_equals(gMutationEvents[0].newValue, after, "wrong new value");
+ }
+ // END LOCAL MODIFICATION
+ }, "classList." + funcName + "(" + args.map(format_value).join(", ") +
+ ") with attribute value " + format_value(before) + desc);
+}
+
+function assignToClassListStrict(e) {
+ "use strict";
+ e.classList = "foo";
+ e.removeAttribute("class");
+}
+
+function assignToClassList(e) {
+ var expect = e.classList;
+ e.classList = "foo";
+ assert_equals(e.classList, expect,
+ "classList should be unchanged after assignment");
+ e.removeAttribute("class");
+}
+
+function testClassList(e, desc) {
+
+ // assignment
+
+ test(function() {
+ assignToClassListStrict(e);
+ assignToClassList(e);
+ }, "Assigning to classList" + desc);
+
+ // supports
+ test(function() {
+ assert_throws_js(TypeError, function() {
+ e.classList.supports("a");
+ })
+ }, ".supports() must throw TypeError" + desc);
+
+ // length attribute
+
+ function checkLength(value, length) {
+ test(function() {
+ setClass(e, value);
+ assert_equals(e.classList.length, length);
+ }, "classList.length when " +
+ (value === null ? "removed" : "set to " + format_value(value)) + desc);
+ }
+
+ checkLength(null, 0);
+ checkLength("", 0);
+ checkLength(" \t \f", 0);
+ checkLength("a", 1);
+ checkLength("a A", 2);
+ checkLength("\r\na\t\f", 1);
+ checkLength("a a", 1);
+ checkLength("a a a a a a", 1);
+ checkLength("a a b b", 2);
+ checkLength("a A B b", 4);
+ checkLength("a b c c b a a b c c", 3);
+ checkLength(" a a b", 2);
+ checkLength("a\tb\nc\fd\re f", 6);
+
+ // [Stringifies]
+
+ function checkStringifier(value, expected) {
+ test(function() {
+ setClass(e, value);
+ assert_equals(e.classList.toString(), expected);
+ }, "classList.toString() when " +
+ (value === null ? "removed" : "set to " + format_value(value)) + desc);
+ }
+
+ checkStringifier(null, "");
+ checkStringifier("foo", "foo");
+ checkStringifier(" a a b", " a a b");
+
+ // item() method
+
+ function checkItems(attributeValue, expectedValues) {
+ function checkItemFunction(index, expected) {
+ assert_equals(e.classList.item(index), expected,
+ "classList.item(" + index + ")");
+ }
+
+ function checkItemArray(index, expected) {
+ assert_equals(e.classList[index], expected, "classList[" + index + "]");
+ }
+
+ test(function() {
+ setClass(e, attributeValue);
+
+ checkItemFunction(-1, null);
+ checkItemArray(-1, undefined);
+
+ var i = 0;
+ while (i < expectedValues.length) {
+ checkItemFunction(i, expectedValues[i]);
+ checkItemArray(i, expectedValues[i]);
+ i++;
+ }
+
+ checkItemFunction(i, null);
+ checkItemArray(i, undefined);
+
+ checkItemFunction(0xffffffff, null);
+ checkItemArray(0xffffffff, undefined);
+
+ checkItemFunction(0xfffffffe, null);
+ checkItemArray(0xfffffffe, undefined);
+ }, "classList.item() when set to " + format_value(attributeValue) + desc);
+ }
+
+ checkItems(null, []);
+ checkItems("a", ["a"]);
+ checkItems("aa AA aa", ["aa", "AA"]);
+ checkItems("a b", ["a", "b"]);
+ checkItems(" a a b", ["a", "b"]);
+ checkItems("\t\n\f\r a\t\n\f\r b\t\n\f\r ", ["a", "b"]);
+
+ // contains() method
+
+ function checkContains(attributeValue, args, expectedRes) {
+ if (!Array.isArray(expectedRes)) {
+ expectedRes = Array(args.length).fill(expectedRes);
+ }
+ setClass(e, attributeValue);
+ for (var i = 0; i < args.length; i++) {
+ test(function() {
+ assert_equals(e.classList.contains(args[i]), expectedRes[i],
+ "classList.contains(\"" + args[i] + "\")");
+ }, "classList.contains(" + format_value(args[i]) + ") when set to " +
+ format_value(attributeValue) + desc);
+ }
+ }
+
+ checkContains(null, ["a", "", " "], false);
+ checkContains("", ["a"], false);
+
+ checkContains("a", ["a"], true);
+ checkContains("a", ["aa", "b", "A", "a.", "a)",, "a'", 'a"', "a$", "a~",
+ "a?", "a\\"], false);
+
+ // All "ASCII whitespace" per spec, before and after
+ checkContains("a", ["a\t", "\ta", "a\n", "\na", "a\f", "\fa", "a\r", "\ra",
+ "a ", " a"], false);
+
+ checkContains("aa AA", ["aa", "AA", "aA"], [true, true, false]);
+ checkContains("a a a", ["a", "aa", "b"], [true, false, false]);
+ checkContains("a b c", ["a", "b"], true);
+
+ checkContains("null undefined", [null, undefined], true);
+ checkContains("\t\n\f\r a\t\n\f\r b\t\n\f\r ", ["a", "b"], true);
+
+ // add() method
+
+ function checkAdd(before, argument, after, expectedException) {
+ checkModification(e, "add", argument, undefined, before, after,
+ expectedException, desc);
+ // Also check force toggle
+ // XXX https://github.com/whatwg/dom/issues/443
+ //if (!Array.isArray(argument)) {
+ // checkModification(e, "toggle", [argument, true], true, before, after,
+ // expectedException);
+ //}
+ }
+
+ checkAdd(null, "", null, "SyntaxError");
+ checkAdd(null, ["a", ""], null, "SyntaxError");
+ checkAdd(null, " ", null, "InvalidCharacterError");
+ checkAdd(null, "\ta", null, "InvalidCharacterError");
+ checkAdd(null, "a\t", null, "InvalidCharacterError");
+ checkAdd(null, "\na", null, "InvalidCharacterError");
+ checkAdd(null, "a\n", null, "InvalidCharacterError");
+ checkAdd(null, "\fa", null, "InvalidCharacterError");
+ checkAdd(null, "a\f", null, "InvalidCharacterError");
+ checkAdd(null, "\ra", null, "InvalidCharacterError");
+ checkAdd(null, "a\r", null, "InvalidCharacterError");
+ checkAdd(null, " a", null, "InvalidCharacterError");
+ checkAdd(null, "a ", null, "InvalidCharacterError");
+ checkAdd(null, ["a", " "], null, "InvalidCharacterError");
+ checkAdd(null, ["a", "aa "], null, "InvalidCharacterError");
+
+ checkAdd("a", "a", "a");
+ checkAdd("aa", "AA", "aa AA");
+ checkAdd("a b c", "a", "a b c");
+ checkAdd("a a a b", "a", "a b");
+ checkAdd(null, "a", "a");
+ checkAdd("", "a", "a");
+ checkAdd(" ", "a", "a");
+ checkAdd(" \f", "a", "a");
+ checkAdd("a", "b", "a b");
+ checkAdd("a b c", "d", "a b c d");
+ checkAdd("a b c ", "d", "a b c d");
+ checkAdd(" a a b", "c", "a b c");
+ checkAdd(" a a b", "a", "a b");
+ checkAdd("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "c", "a b c");
+
+ // multiple add
+ checkAdd("a b c ", ["d", "e"], "a b c d e");
+ checkAdd("a b c ", ["a", "a"], "a b c");
+ checkAdd("a b c ", ["d", "d"], "a b c d");
+ checkAdd("a b c a ", [], "a b c");
+ checkAdd(null, ["a", "b"], "a b");
+ checkAdd("", ["a", "b"], "a b");
+
+ checkAdd(null, null, "null");
+ checkAdd(null, undefined, "undefined");
+
+ // remove() method
+
+ function checkRemove(before, argument, after, expectedException) {
+ checkModification(e, "remove", argument, undefined, before, after,
+ expectedException, desc);
+ // Also check force toggle
+ // XXX https://github.com/whatwg/dom/issues/443
+ //if (!Array.isArray(argument)) {
+ // checkModification(e, "toggle", [argument, false], false, before, after,
+ // expectedException);
+ //}
+ }
+
+ checkRemove(null, "", null, "SyntaxError");
+ checkRemove(null, " ", null, "InvalidCharacterError");
+ checkRemove("\ta", "\ta", "\ta", "InvalidCharacterError");
+ checkRemove("a\t", "a\t", "a\t", "InvalidCharacterError");
+ checkRemove("\na", "\na", "\na", "InvalidCharacterError");
+ checkRemove("a\n", "a\n", "a\n", "InvalidCharacterError");
+ checkRemove("\fa", "\fa", "\fa", "InvalidCharacterError");
+ checkRemove("a\f", "a\f", "a\f", "InvalidCharacterError");
+ checkRemove("\ra", "\ra", "\ra", "InvalidCharacterError");
+ checkRemove("a\r", "a\r", "a\r", "InvalidCharacterError");
+ checkRemove(" a", " a", " a", "InvalidCharacterError");
+ checkRemove("a ", "a ", "a ", "InvalidCharacterError");
+ checkRemove("aa ", "aa ", null, "InvalidCharacterError");
+
+ checkRemove(null, "a", null);
+ checkRemove("", "a", "");
+ checkRemove("a b c", "d", "a b c");
+ checkRemove("a b c", "A", "a b c");
+ checkRemove(" a a a ", "a", "");
+ checkRemove("a b", "a", "b");
+ checkRemove("a b ", "a", "b");
+ checkRemove("a a b", "a", "b");
+ checkRemove("aa aa bb", "aa", "bb");
+ checkRemove("a a b a a c a a", "a", "b c");
+
+ checkRemove("a b c", "b", "a c");
+ checkRemove("aaa bbb ccc", "bbb", "aaa ccc");
+ checkRemove(" a b c ", "b", "a c");
+ checkRemove("a b b b c", "b", "a c");
+
+ checkRemove("a b c", "c", "a b");
+ checkRemove(" a b c ", "c", "a b");
+ checkRemove("a b c c c", "c", "a b");
+
+ checkRemove("a b a c a d a", "a", "b c d");
+ checkRemove("AA BB aa CC AA dd aa", "AA", "BB aa CC dd");
+
+ checkRemove("\ra\na\ta\f", "a", "");
+ checkRemove("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "a", "b");
+
+ // multiple remove
+ checkRemove("a b c ", ["d", "e"], "a b c");
+ checkRemove("a b c ", ["a", "b"], "c");
+ checkRemove("a b c ", ["a", "c"], "b");
+ checkRemove("a b c ", ["a", "a"], "b c");
+ checkRemove("a b c ", ["d", "d"], "a b c");
+ checkRemove("a b c ", [], "a b c");
+ checkRemove(null, ["a", "b"], null);
+ checkRemove("", ["a", "b"], "");
+ checkRemove("a a", [], "a");
+
+ checkRemove("null", null, "");
+ checkRemove("undefined", undefined, "");
+
+ // toggle() method
+
+ function checkToggle(before, argument, expectedRes, after, expectedException) {
+ checkModification(e, "toggle", argument, expectedRes, before, after,
+ expectedException, desc);
+ }
+
+ checkToggle(null, "", null, null, "SyntaxError");
+ checkToggle(null, "aa ", null, null, "InvalidCharacterError");
+
+ checkToggle(null, "a", true, "a");
+ checkToggle("", "a", true, "a");
+ checkToggle(" ", "a", true, "a");
+ checkToggle(" \f", "a", true, "a");
+ checkToggle("a", "b", true, "a b");
+ checkToggle("a", "A", true, "a A");
+ checkToggle("a b c", "d", true, "a b c d");
+ checkToggle(" a a b", "d", true, "a b d");
+
+ checkToggle("a", "a", false, "");
+ checkToggle(" a a a ", "a", false, "");
+ checkToggle(" A A A ", "a", true, "A a");
+ checkToggle(" a b c ", "b", false, "a c");
+ checkToggle(" a b c b b", "b", false, "a c");
+ checkToggle(" a b c ", "c", false, "a b");
+ checkToggle(" a b c ", "a", false, "b c");
+ checkToggle(" a a b", "b", false, "a");
+ checkToggle("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "a", false, "b");
+ checkToggle("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "c", true, "a b c");
+
+ checkToggle("null", null, false, "");
+ checkToggle("", null, true, "null");
+ checkToggle("undefined", undefined, false, "");
+ checkToggle("", undefined, true, "undefined");
+
+
+ // tests for the force argument handling
+ // XXX Remove these if https://github.com/whatwg/dom/issues/443 is fixed
+
+ function checkForceToggle(before, argument, force, expectedRes, after, expectedException) {
+ checkModification(e, "toggle", [argument, force], expectedRes, before,
+ after, expectedException, desc);
+ }
+
+ checkForceToggle("", "a", true, true, "a");
+ checkForceToggle("a", "a", true, true, "a");
+ checkForceToggle("a", "b", true, true, "a b");
+ checkForceToggle("a b", "b", true, true, "a b");
+ checkForceToggle("", "a", false, false, "");
+ checkForceToggle("a", "a", false, false, "");
+ checkForceToggle("a", "b", false, false, "a");
+ checkForceToggle("a b", "b", false, false, "a");
+
+
+ // replace() method
+ function checkReplace(before, token, newToken, expectedRes, after, expectedException) {
+ checkModification(e, "replace", [token, newToken], expectedRes, before,
+ after, expectedException, desc);
+ }
+
+ checkReplace(null, "", "a", null, null, "SyntaxError");
+ checkReplace(null, "", " ", null, null, "SyntaxError");
+ checkReplace(null, " ", "a", null, null, "InvalidCharacterError");
+ checkReplace(null, "\ta", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "a\t", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "\na", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "a\n", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "\fa", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "a\f", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "\ra", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "a\r", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, " a", "b", null, null, "InvalidCharacterError");
+ checkReplace(null, "a ", "b", null, null, "InvalidCharacterError");
+
+ checkReplace(null, "a", "", null, null, "SyntaxError");
+ checkReplace(null, " ", "", null, null, "SyntaxError");
+ checkReplace(null, "a", " ", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "\ta", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "a\t", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "\na", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "a\n", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "\fa", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "a\f", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "\ra", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "a\r", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", " a", null, null, "InvalidCharacterError");
+ checkReplace(null, "b", "a ", null, null, "InvalidCharacterError");
+
+ checkReplace("a", "a", "a", true, "a");
+ checkReplace("a", "a", "b", true, "b");
+ checkReplace("a", "A", "b", false, "a");
+ checkReplace("a b", "b", "A", true, "a A");
+ checkReplace("a b", "c", "a", false, "a b");
+ checkReplace("a b c", "d", "e", false, "a b c");
+ // https://github.com/whatwg/dom/issues/443
+ checkReplace("a a a b", "a", "a", true, "a b");
+ checkReplace("a a a b", "c", "d", false, "a a a b");
+ checkReplace(null, "a", "b", false, null);
+ checkReplace("", "a", "b", false, "");
+ checkReplace(" ", "a", "b", false, " ");
+ checkReplace(" a \f", "a", "b", true, "b");
+ checkReplace("a b c", "b", "d", true, "a d c");
+ checkReplace("a b c", "c", "a", true, "a b");
+ checkReplace("c b a", "c", "a", true, "a b");
+ checkReplace("a b a", "a", "c", true, "c b");
+ checkReplace("a b a", "b", "c", true, "a c");
+ checkReplace(" a a b", "a", "c", true, "c b");
+ checkReplace(" a a b", "b", "c", true, "a c");
+ checkReplace("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "a", "c", true, "c b");
+ checkReplace("\t\n\f\r a\t\n\f\r b\t\n\f\r ", "b", "c", true, "a c");
+
+ checkReplace("a null", null, "b", true, "a b");
+ checkReplace("a b", "a", null, true, "null b");
+ checkReplace("a undefined", undefined, "b", true, "a b");
+ checkReplace("a b", "a", undefined, true, "undefined b");
+}
+
+var content = document.getElementById("content");
+
+var htmlNode = document.createElement("div");
+content.appendChild(htmlNode);
+testClassList(htmlNode, " (HTML node)");
+
+var xhtmlNode = document.createElementNS(XHTML_NS, "div");
+content.appendChild(xhtmlNode);
+testClassList(xhtmlNode, " (XHTML node)");
+
+var mathMLNode = document.createElementNS(MATHML_NS, "math");
+content.appendChild(mathMLNode);
+testClassList(mathMLNode, " (MathML node)");
+
+var xmlNode = document.createElementNS(null, "foo");
+content.appendChild(xmlNode);
+testClassList(xmlNode, " (XML node with null namespace)");
+
+var fooNode = document.createElementNS("http://example.org/foo", "foo");
+content.appendChild(fooNode);
+testClassList(fooNode, " (foo node)");
+</script>
diff --git a/testing/web-platform/mozilla/tests/dom/delayed_window_print.html b/testing/web-platform/mozilla/tests/dom/delayed_window_print.html
new file mode 100644
index 0000000000..0bb9977184
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/delayed_window_print.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test for delaying window.print() before load</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<body>
+<script>
+let t = async_test("Delayed print before load");
+let beforePrintCalled = false;
+window.addEventListener("beforeprint", t.step_func(function() {
+ assert_false(beforePrintCalled, "Should only call beforeprint once");
+ beforePrintCalled = true;
+ assert_true(
+ !!document.getElementById("before-load"),
+ "Should show contents that get added before load"
+ );
+ assert_true(
+ !!document.getElementById("during-load"),
+ "Should show contents that get added during load"
+ );
+ setTimeout(function() { t.done(); }, 0);
+}));
+
+t.step(function() {
+ window.print();
+
+ let div = document.createElement("div");
+ div.id = "before-load";
+ document.body.appendChild(div);
+});
+
+window.addEventListener("load", t.step_func(function() {
+ window.print();
+
+ let div = document.createElement("div");
+ div.id = "during-load";
+ document.body.appendChild(div);
+}));
+</script>
diff --git a/testing/web-platform/mozilla/tests/dom/dispatch_select_event.html b/testing/web-platform/mozilla/tests/dom/dispatch_select_event.html
new file mode 100644
index 0000000000..1fb70aa5b1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/dispatch_select_event.html
@@ -0,0 +1,35 @@
+<!-- See also Bug 1679427.
+Ensure `select` event is only fired once when tab-ing to an `<input>` element.
+-->
+<!doctype html>
+<html>
+<head>
+ <script src=/resources/testharness.js></script>
+ <script src=/resources/testharnessreport.js></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+</head>
+<body>
+ <button>Press this button and Press Tab</button><input value="abc">
+ <script>
+ promise_test(async t => {
+ await new Promise(resolve => { window.onload = resolve; });
+ const button = document.querySelector("button");
+ const input = document.querySelector("input");
+
+ let countSelectEvent = 0;
+ input.addEventListener("select", event => {
+ countSelectEvent++;
+ });
+
+ button.focus();
+ const tabKey = "\uE004";
+ await test_driver.send_keys(button, tabKey);
+ await new Promise(resolve => requestAnimationFrame(
+ () => requestAnimationFrame(resolve)
+ ));
+ assert_equals(countSelectEvent, 1, "Select event was fired more than once!");
+ }, "Select event should only be fired once.");
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/dom/focus-invalid-uri-link.html b/testing/web-platform/mozilla/tests/dom/focus-invalid-uri-link.html
new file mode 100644
index 0000000000..5de81c866f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/focus-invalid-uri-link.html
@@ -0,0 +1,63 @@
+<!doctype html>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src=/resources/testdriver.js></script>
+<script src=/resources/testdriver-actions.js></script>
+<script src=/resources/testdriver-vendor.js></script>
+<script>
+function abs(uri) {
+ return new URL(uri, window.location.href).href;
+}
+const CHILD_DOC = `
+<!doctype html>
+<script src="${abs("/resources/testdriver.js")}"></` + `script>
+<script src="${abs("/resources/testdriver-actions.js")}"></` + `script>
+<script src="${abs("/resources/testdriver-vendor.js")}"></` + `script>
+<script>
+ test_driver.set_test_context(opener);
+</` + `script>
+
+<a href>To link or not to link</a>
+
+<script>
+onload = async function() {
+ let link = document.querySelector("a");
+ link.focus();
+ let focused = document.activeElement == link;
+ let clicked = new Promise(resolve => {
+ link.addEventListener("click", resolve, { once: true });
+ });
+ const enterKey = '\\uE007';
+ await test_driver.send_keys(link, enterKey);
+ await clicked;
+ test_driver.message_test({ testResult: true, focused, clicked: true });
+};
+</` + `script>
+`
+
+promise_test(async function(t) {
+ await new Promise(resolve => {
+ window.onload = resolve;
+ })
+
+ let messagePromise = new Promise(resolve => {
+ addEventListener("message", function(msg) {
+ if (msg.data.testResult) {
+ resolve(msg);
+ }
+ });
+ });
+
+ let win = window.open("data:text/html," + escape(CHILD_DOC));
+
+ assert_true(true, "Window opened");
+ let message = await messagePromise;
+ assert_true(true, "message: " + JSON.stringify(message));
+
+ let { focused, clicked } = message.data;
+ assert_true(focused, "Link should be focusable");
+ assert_true(clicked, "Link should be keyboard activatable");
+
+ win.close();
+}, "Link to invalid URI should be focusable and keyboard activatable");
+</script>
diff --git a/testing/web-platform/mozilla/tests/dom/fs/fs-writable_unlocked_on_tab_close.https.window.js b/testing/web-platform/mozilla/tests/dom/fs/fs-writable_unlocked_on_tab_close.https.window.js
new file mode 100644
index 0000000000..6e8192aaef
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/fs/fs-writable_unlocked_on_tab_close.https.window.js
@@ -0,0 +1,70 @@
+// META: title=Origin private file system used from multiple tabs
+// META: script=support/testHelpers.js
+
+promise_test(async t => {
+ const bc = new BroadcastChannel("Coordinate writables");
+
+ function firstReady(win) {
+ return new Promise(resolve => {
+ // Blur triggers after the unload event and after window.closed is set
+ win.onblur = () => {
+ // Closing the low-level file handle may get stuck, but the unlocking
+ // request can only be sent to the parent after the handle is closed.
+ // There is no guarantee when or if the closing will be complete.
+ //
+ // Therefore, the content process shutdown does not wait for the
+ // completion but sets window.closed and calls the unload listeners
+ // while actually still holding onto some resources.
+ //
+ // Since in this test we mainly want to ensure that a file
+ // does not remain locked indefinitely, we wait for a reasonable amount
+ // of time before creating a new writable, corresponding roughly to
+ // a 500ms closing delay.
+ const timeoutMs = 400;
+ setTimeout(() => {
+ resolve(win);
+ }, timeoutMs);
+ };
+ });
+ }
+
+ const firstTabName = "support/fs-open_writable_then_close_tab.sub.html";
+ const firstTab = await firstReady(window.open(firstTabName));
+ assert_true(firstTab.closed, "Is the first tab already closed?");
+
+ function secondReady(win) {
+ return new Promise(resolve => {
+ bc.onmessage = e => {
+ if (e.data === "Second window ready!") {
+ resolve(win);
+ }
+ };
+ });
+ }
+
+ const secondTabName = "support/fs-open_writable_after_trigger.sub.html";
+ const secondTab = await secondReady(window.open(secondTabName));
+
+ let isDone = false;
+ let childStatus = "Success";
+
+ const secondSucceeded = new Promise(resolve => {
+ bc.onmessage = e => {
+ isDone = true;
+ if (e.data !== "Success") {
+ childStatus = e.data;
+ }
+
+ resolve();
+ };
+ });
+
+ bc.postMessage("Create writable in the second window");
+
+ await secondSucceeded;
+ assert_true(isDone, "Did the second tab respond?");
+
+ await fetch_tests_from_window(secondTab);
+
+ assert_equals(childStatus, "Success");
+}, `writable available for other tabs after one tab is closed`);
diff --git a/testing/web-platform/mozilla/tests/dom/fs/support/fs-open_writable_after_trigger.sub.html b/testing/web-platform/mozilla/tests/dom/fs/support/fs-open_writable_after_trigger.sub.html
new file mode 100644
index 0000000000..b64d97083f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/fs/support/fs-open_writable_after_trigger.sub.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<title>Child context test(s)</title>
+<head>
+ <script src="/resources/testharness.js"></script>
+ <script src="testHelpers.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script>
+ const channel = new BroadcastChannel("Coordinate writables");
+
+ let triggered = false;
+
+ channel.onmessage = e => {
+ if ("Create writable in the second window" === e.data) {
+ triggered = true;
+ }
+ };
+
+ channel.postMessage("Second window ready!");
+
+ promise_test(async t => {
+ try {
+ const maxWaitMs = 2000;
+ await waitUntil(() => { return triggered; }, maxWaitMs);
+ assert_true(triggered, "Did we receive a trigger?");
+
+ const dir = await navigator.storage.getDirectory();
+ const opts = { create: true };
+ const file = await dir.getFileHandle('funky-file-handle', opts);
+ let writable = await file.createWritable({});
+ t.add_cleanup(async () => { await writable.close(); });
+ assert_true(!!writable, "Did we receive a writable?");
+
+ channel.postMessage("Success");
+ } catch(err) {
+ channel.postMessage(err.message);
+
+ throw err;
+ }
+ });
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/dom/fs/support/fs-open_writable_then_close_tab.sub.html b/testing/web-platform/mozilla/tests/dom/fs/support/fs-open_writable_then_close_tab.sub.html
new file mode 100644
index 0000000000..098fe83b1f
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/fs/support/fs-open_writable_then_close_tab.sub.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<title>Child context test(s)</title>
+<head>
+ <script src="/resources/testharness.js"></script>
+</head>
+<body>
+ <div id="log"></div>
+ <script>
+ window.addEventListener('load', async () => {
+ const dir = await navigator.storage.getDirectory();
+ const opts = { create: true };
+ const file = await dir.getFileHandle('funky-file-handle', opts);
+ const writable = await file.createWritable({});
+
+ window.close();
+ });
+ </script>
+</body>
+</html>
diff --git a/testing/web-platform/mozilla/tests/dom/fs/support/testHelpers.js b/testing/web-platform/mozilla/tests/dom/fs/support/testHelpers.js
new file mode 100644
index 0000000000..5cf47435c1
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/fs/support/testHelpers.js
@@ -0,0 +1,15 @@
+async function waitUntil(isWaitDone, untilMs, stepMs = 25) {
+ const startMs = Date.now();
+
+ return new Promise((resolve, reject) => {
+ const areWeDoneYet = setInterval(async function() {
+ if (await isWaitDone()) {
+ clearInterval(areWeDoneYet);
+ resolve();
+ } else if (Date.now() > startMs + untilMs) {
+ clearInterval(areWeDoneYet);
+ reject(new Error("Timed out after " + untilMs + "ms"));
+ }
+ }, stepMs);
+ });
+}
diff --git a/testing/web-platform/mozilla/tests/dom/range-in-two-selections.html b/testing/web-platform/mozilla/tests/dom/range-in-two-selections.html
new file mode 100644
index 0000000000..a37464d55a
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/range-in-two-selections.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+</head>
+
+<body>
+<span>One two</span>
+<script>
+promise_test(async function (t) {
+ await new Promise(resolve => {
+ window.onload = resolve;
+ })
+ const range = document.createRange();
+ range.setStart(document.body, 0);
+ range.setEnd(document.body, 1);
+ const highlight = new Highlight(range);
+ CSS.highlights.set("foo", highlight);
+ document.getSelection().addRange(range);
+
+ const highlightRange = highlight.entries().next().value[0];
+ const selectionRange = document.getSelection().getRangeAt(0);
+ assert_equals(
+ highlightRange,
+ selectionRange,
+ "The same range must be present in the highlight and the Selection."
+ );
+}, "Range is shared between a custom highlight and the document's Selection.");
+</script>
+</body>
+
+</html>
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/resources/test.html b/testing/web-platform/mozilla/tests/dom/throttling/resources/test.html
new file mode 100644
index 0000000000..7eb9dd1e40
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/resources/test.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<meta charset=utf-8>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="throttling.js"></script>
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/resources/throttling.js b/testing/web-platform/mozilla/tests/dom/throttling/resources/throttling.js
new file mode 100644
index 0000000000..280b0adc0d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/resources/throttling.js
@@ -0,0 +1,136 @@
+function waitForLoad() {
+ return new Promise(resolve => addEventListener('load', resolve))
+ .then(() => delay(10));
+}
+
+function delay(timeout) {
+ return new Promise(resolve => step_timeout(() => resolve(), 10));
+}
+
+function busy(work) {
+ return delay(10).then(() => new Promise(resolve => {
+ step_timeout(() => {
+ let end = performance.now() + work;
+ while (performance.now() < end) {
+
+ }
+
+ resolve();
+ }, 1);
+ }));
+}
+
+function getThrottlingRate(delay) {
+ return new Promise(resolve => {
+ let start = performance.now();
+ setTimeout(() => {
+ let rate = Math.floor((performance.now() - start) / delay);
+ resolve(rate);
+ }, delay);
+ });
+}
+
+function addElement(t, element, src) {
+ return new Promise((resolve, reject) => {
+ let e = document.createElement(element);
+ e.addEventListener('load', () => resolve(e));
+ if (src) {
+ e.src = src;
+ }
+ document.body.appendChild(e);
+ t.add_cleanup(() => e.remove());
+ });
+}
+
+function inFrame(t) {
+ return addElement(t, "iframe", "resources/test.html")
+ .then(frame => delay(10).then(() => Promise.resolve(frame.contentWindow)));
+}
+
+function addWebSocket(t, url) {
+ return new Promise((resolve, reject) => {
+ let socket = new WebSocket(url);
+ socket.onopen = () => {
+ t.add_cleanup(() => socket.close());
+ resolve();
+ };
+ socket.onerror = reject;
+ });
+}
+
+function addRTCPeerConnection(t) {
+ return new Promise((resolve, reject) => {
+ let connection = new RTCPeerConnection();
+ t.add_cleanup(() => {
+ connection.close()
+ });
+
+ resolve();
+ });
+}
+
+function addIndexedDB(t) {
+ return new Promise((resolve, reject) => {
+ let iDBState = {
+ running: false,
+ db: null
+ };
+
+ let req = indexedDB.open("testDB", 1);
+
+ req.onupgradeneeded = e => {
+ let db = e.target.result;
+ let store = db.createObjectStore("testOS", {keyPath: "id"});
+ let index = store.createIndex("index", ["col"]);
+ };
+
+ req.onsuccess = e => {
+ let db = iDBState.db = e.target.result;
+ let store = db.transaction("testOS", "readwrite").objectStore("testOS");
+ let ctr = 0;
+
+ iDBState.running = true;
+
+ function putLoop() {
+ if (!iDBState.running) {
+ return;
+ }
+
+ let req = store.put({id: ctr++, col: "foo"});
+ req.onsuccess = putLoop;
+
+ if (!iDBState.request) {
+ iDBState.request = req;
+ }
+ }
+
+ putLoop();
+ resolve();
+ };
+
+ t.add_cleanup(() => {
+ iDBState.running = false;
+ iDBState.db && iDBState.db.close();
+ iDBState.db = null;
+ });
+ });
+}
+
+function addWebAudio(t) {
+ return new Promise(resolve => {
+ let context = new (window.AudioContext || window.webkitAudioContext)();
+ context.onstatechange = () => (context.state === "running") && resolve();
+
+ let gain = context.createGain();
+ gain.gain.value = 0.1;
+ gain.connect(context.destination);
+
+ let webaudionode = context.createOscillator();
+ webaudionode.type = 'square';
+ webaudionode.frequency.value = 440; // value in hertz
+ webaudionode.connect(gain);
+ webaudionode.start();
+
+ t.add_cleanup(() => webaudionode.stop());
+ });
+}
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/resources/ws.sub.js b/testing/web-platform/mozilla/tests/dom/throttling/resources/ws.sub.js
new file mode 100644
index 0000000000..a1ac273a54
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/resources/ws.sub.js
@@ -0,0 +1,3 @@
+var __SERVER__NAME = "{{host}}";
+var __PORT = "{{ports[ws][0]}}";
+var __PATH = "echo";
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-1.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-1.window.js
new file mode 100644
index 0000000000..86cefc8a81
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-1.window.js
@@ -0,0 +1,10 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => busy(100)
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_greater_than(rate, 10, "Timeout wasn't throttled");
+ }), "Throttle when all budget has been used.");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-2.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-2.window.js
new file mode 100644
index 0000000000..3ccb35dc08
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-2.window.js
@@ -0,0 +1,11 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => inFrame(t)
+ .then(win => win.busy(100)
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_greater_than(rate, 10, "Timeout wasn't throttled");
+ }), "Throttle iframe when all budget has been used");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-3.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-3.window.js
new file mode 100644
index 0000000000..d1c38bcc12
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-3.window.js
@@ -0,0 +1,11 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => inFrame(t)
+ .then(win => busy(100)
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when all budget in parent has been used");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-4.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-4.window.js
new file mode 100644
index 0000000000..b072b51809
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-4.window.js
@@ -0,0 +1,11 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => inFrame(t)
+ .then(win => win.busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle parent when all budget in iframe has been used");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-indexeddb.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-indexeddb.window.js
new file mode 100644
index 0000000000..73c734a584
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-indexeddb.window.js
@@ -0,0 +1,35 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => addIndexedDB(t)
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open IndexedDB transactions.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addIndexedDB(t))
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open IndexedDB transactions in iframe.");
+
+promise_test(t => inFrame(t)
+ .then(win => addIndexedDB(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open IndexedDB transactions in parent.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addIndexedDB(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open IndexedDB transactions in iframe.");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-webaudio.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-webaudio.window.js
new file mode 100644
index 0000000000..5cd7193788
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-webaudio.window.js
@@ -0,0 +1,35 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => addWebAudio(t)
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there is active WebAudio.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addWebAudio(t))
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there is active WebAudio in iframe.");
+
+promise_test(t => inFrame(t)
+ .then(win => addWebAudio(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there is active WebAudio in parent.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addWebAudio(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there is active WebAudio in iframe.");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-webrtc.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-webrtc.window.js
new file mode 100644
index 0000000000..2842f77e44
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-webrtc.window.js
@@ -0,0 +1,35 @@
+// META: script=resources/throttling.js
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => addRTCPeerConnection(t)
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open RTCPeerConnections.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addRTCPeerConnection(t))
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open RTCPeerConnections in iframe.");
+
+promise_test(t => inFrame(t)
+ .then(win => addRTCPeerConnection(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open RTCPeerConnections in parent.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addRTCPeerConnection(t)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open RTCPeerConnections in iframe.");
diff --git a/testing/web-platform/mozilla/tests/dom/throttling/throttling-ws.window.js b/testing/web-platform/mozilla/tests/dom/throttling/throttling-ws.window.js
new file mode 100644
index 0000000000..185654e04d
--- /dev/null
+++ b/testing/web-platform/mozilla/tests/dom/throttling/throttling-ws.window.js
@@ -0,0 +1,37 @@
+// META: script=resources/ws.sub.js
+// META: script=resources/throttling.js
+let server = "ws://" + __SERVER__NAME + ":" + __PORT + "/" + __PATH;
+
+setup(() => waitForLoad()
+ .then(() => "setup done"));
+
+promise_test(t => addWebSocket(t, server)
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open WebSockets.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addWebSocket(t, server))
+ .then(() => busy(100))
+ .then(() => getThrottlingRate(100))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle when there are open WebSockets in iframe.");
+
+promise_test(t => inFrame(t)
+ .then(win => addWebSocket(t, server)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open WebSockets in parent.");
+
+promise_test(t => inFrame(t)
+ .then(win => win.addWebSocket(t, server)
+ .then(() => win.busy(100))
+ .then(() => win.getThrottlingRate(100)))
+ .then(rate => {
+ assert_less_than(rate, 10, "Timeout was throttled");
+ }), "Don't throttle iframe when there are open WebSockets in iframe.");