summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/browsers/the-window-object
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/browsers/the-window-object')
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/BarProp.window.js59
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/Document-defaultView.html38
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/Window-document.html25
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-01.html47
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-02.html62
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-03.html30
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/iterator.html11
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test1.html12
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test2.html6
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test3.html8
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/window_length.html51
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/close-method.window.js39
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/closed-attribute.window.js69
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/defaultstatus.html17
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/document-attribute.window.js15
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/focus.window.js15
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1-1.html20
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1-2.html2
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1.html10
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_2-1.html22
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_2.html10
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-1.html21
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-2.html4
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-3.html4
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3.html9
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-1.html21
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-2.html4
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-3.html4
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4.html9
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-1.html27
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-2.html2
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-manual.html10
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-1.html19
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-2.html1
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-3.html1
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-manual.html10
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/historical.window.js4
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/length-attribute.window.js24
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/name-attribute.window.js18
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/cross-global-npo.html38
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/cross-global-support.html4
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/named-objects.html76
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/navigated-named-objects.window.js67
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/prototype.html94
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/test.html7
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/window-named-properties.html83
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/window-null-names.html20
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/navigate-to-about-blank-while-initial-load-pending.html26
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/noopener-noreferrer-BarProp.window.js23
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/noopener-noreferrer-sizing.window.js17
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/callback.js1
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/close_beforeunload-1.html7
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/close_beforeunload.html16
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/close_script_defer-1.html1
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/close_script_defer.html18
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/close_unload-1.html7
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/close_unload.html16
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/creating_browsing_context_test_01.html39
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/no_window_open_when_term_nesting_level_nonzero.window.js113
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001-1.html2
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001-2.html16
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001.html3
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002-1.html8
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002-2.html16
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002.html3
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-is-popup-condition.html149
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-innerwidth-innerheight.html75
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-screenx-screeny.html67
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-top-left.html68
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-width-height.html75
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-height.html91
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-innerheight.html76
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-innerwidth.html75
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-left.html76
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-screenx.html75
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-screeny.html76
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-top.html73
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-width.html91
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-innerheight-innerwidth.html55
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-noopener.html11
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-noreferrer.html11
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-screenx-screeny.html55
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-top-left.html69
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-width-height.html71
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/close-self.html3
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/is-popup-barprop.html15
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/message-opener.html52
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/tokenization-noopener-noreferrer.js152
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/proxy-getOwnPropertyDescriptor.html126
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/security-window/window-security.https.html200
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/self-et-al.window.js43
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/support/BarProp-target.html17
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/support/closed.html12
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/support/noopener-target.html15
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/support/noreferrer-target.html13
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/support/same-origin-iframe.html8
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/support/sizing-target.html17
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/support/window-open-popup-target.html24
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/support/windowFeature-values-target.html24
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-aliases.html28
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-indexed-access-vs-named-access.html58
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-delete-no-cache.html31
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-strict.html75
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties.html71
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-open-defaults.window.js12
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-open-invalid-url.html10
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-open-noopener.html137
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-open-noreferrer.html20
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-open-popup-behavior.html51
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-open-windowfeatures-values.html72
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-opener-unconfigurable.window.js17
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-properties.https.html358
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-prototype-chain.html32
-rw-r--r--testing/web-platform/tests/html/browsers/the-window-object/window-reuse-in-nested-browsing-contexts.tentative.html158
114 files changed, 4671 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/BarProp.window.js b/testing/web-platform/tests/html/browsers/the-window-object/BarProp.window.js
new file mode 100644
index 0000000000..27a357cab5
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/BarProp.window.js
@@ -0,0 +1,59 @@
+function assert_barProps(barPropObjects, visible) {
+ let lastBarProp = undefined;
+ for (const currentBarProp of barPropObjects) {
+ assert_not_equals(currentBarProp, lastBarProp, "BarBrop objects of different properties are identical");
+ assert_equals(currentBarProp.visible, visible, "a BarProp's visible is wrong");
+ lastBarProp = currentBarProp;
+ }
+}
+
+function assert_identical_barProps(barProps, w, oldBarPropObjects, visible) {
+ barProps.map(val => w[val]).map((val, index) => {
+ assert_equals(val, oldBarPropObjects[index], "BarProp identity not preserved");
+ });
+ assert_barProps(oldBarPropObjects, visible);
+}
+
+async_test(t => {
+ const frame = document.body.appendChild(document.createElement("iframe")),
+ frameW = frame.contentWindow,
+ barProps = ["locationbar", "menubar", "personalbar", "scrollbars", "statusbar", "toolbar"],
+ barPropObjects = barProps.map(val => frameW[val]);
+
+ assert_barProps(barPropObjects, true);
+ frame.remove();
+ assert_identical_barProps(barProps, frameW, barPropObjects, false);
+ t.step_timeout(() => {
+ assert_identical_barProps(barProps, frameW, barPropObjects, false);
+ t.done();
+ }, 0);
+}, "BarBrop objects of a nested Window");
+
+async_test(t => {
+ const openee = window.open("/common/blank.html"),
+ barProps = ["locationbar", "menubar", "personalbar", "scrollbars", "statusbar", "toolbar"],
+ barPropObjects = barProps.map(val => openee[val]);
+
+ // This is used to demonstrate that the Document is replaced while the global object (not the
+ // global this object) stays the same
+ openee.tiedToGlobalObject = openee.document;
+
+ assert_barProps(barPropObjects, true);
+ openee.onload = t.step_func(() => {
+ assert_own_property(openee, "tiedToGlobalObject");
+ assert_not_equals(openee.tiedToGlobalObject, openee.document);
+
+ assert_identical_barProps(barProps, openee, barPropObjects, true);
+
+ openee.onunload = t.step_func(() => {
+ assert_identical_barProps(barProps, openee, barPropObjects, true);
+ t.step_timeout(() => {
+ assert_identical_barProps(barProps, openee, barPropObjects, false);
+ t.done();
+ }, 0);
+ });
+
+ openee.close();
+ assert_identical_barProps(barProps, openee, barPropObjects, true);
+ });
+}, "BarProp objects of an auxiliary Window");
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/Document-defaultView.html b/testing/web-platform/tests/html/browsers/the-window-object/Document-defaultView.html
new file mode 100644
index 0000000000..dbc75d30b2
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/Document-defaultView.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Document#defaultView</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_equals(document.defaultView, window);
+}, "Document in a browsing context");
+
+test(function() {
+ var d = new Document();
+ assert_equals(d.defaultView, null);
+}, "Document created with the Document constructor");
+
+test(function() {
+ var d = document.implementation.createDocument(null, null);
+ assert_equals(d.defaultView, null);
+}, "Document created with createDocument");
+
+test(function() {
+ var d = document.implementation.createHTMLDocument();
+ assert_equals(d.defaultView, null);
+}, "Document created with createHTMLDocument");
+
+test(function() {
+ var parser = new DOMParser();
+ var d = parser.parseFromString("<foo\/\>", "application/xml");
+ assert_equals(d.defaultView, null);
+}, "Document created with XML DOMParser");
+
+test(function() {
+ var parser = new DOMParser();
+ var d = parser.parseFromString("bar", "text/html");
+ assert_equals(d.defaultView, null);
+}, "Document created with HTML DOMParser");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/Window-document.html b/testing/web-platform/tests/html/browsers/the-window-object/Window-document.html
new file mode 100644
index 0000000000..9b27f5f7c7
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/Window-document.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Window#document</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var URL = "/common/blank.html";
+
+ var iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ var initialWindow = iframe.contentWindow;
+ var initialDocument = initialWindow.document;
+ assert_equals(initialDocument.URL, "about:blank");
+ iframe.src = URL;
+ iframe.onload = this.step_func_done(function() {
+ assert_equals(iframe.contentWindow, initialWindow);
+ assert_equals(initialDocument.URL, "about:blank");
+ var loadedDocument = initialWindow.document;
+ assert_equals(loadedDocument.URL, location.href.replace(location.pathname, URL));
+ assert_not_equals(initialDocument, loadedDocument);
+ });
+}, "Document in a browsing context");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-01.html b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-01.html
new file mode 100644
index 0000000000..9710d15fb2
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-01.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: the browsing contexts must be sorted in the order that their containers were inserted into the Document</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/browsers.html#accessing-other-browsing-contexts" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+
+var t1 = async_test("The window's length must return the number of child browsing contexts(in iframe)");
+function on_load1(fr) {
+ t1.step(function () {
+ var doc = fr.contentDocument;
+ var fr3 = doc.createElement("iframe");
+ fr3.setAttribute("id", "fr3");
+ doc.body.insertBefore(fr3, doc.getElementById("tbl"));
+
+ assert_equals(fr.contentWindow.length, 3, "The window.length should be 3.");
+ assert_array_equals([fr.contentWindow[0].frameElement, fr.contentWindow[1].frameElement, fr.contentWindow[2].frameElement],
+ [fr.contentDocument.getElementById("fr4"), fr.contentDocument.getElementById("fr5"), fr.contentDocument.getElementById("fr3")],
+ "The child browsing contexts must be sorted in the order that their containers were inserted into the Document.");
+ });
+ t1.done();
+}
+
+var t2 = async_test("The window's length must return zero if it has no child browsing context");
+function on_load2(fr) {
+ t2.step(function () {
+ assert_equals(fr.contentWindow.length, 0, "The window.length should be 0.");
+ });
+ t2.done();
+}
+
+</script>
+<iframe id="fr1" src="test1.html" style="display:none" onload="on_load1(this)"></iframe>
+<iframe id="fr2" src="test2.html" style="display:none" onload="on_load2(this)"></iframe>
+<script>
+
+test(function () {
+ assert_equals(window.length, 2, "The window.length should be 2.");
+ assert_array_equals([window[0].frameElement, window[1].frameElement],
+ [document.getElementById("fr1"), document.getElementById("fr2")],
+ "The child browsing contexts must be sorted in the tree order.");
+}, "The window's length must return the number of child browsing contexts");
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-02.html b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-02.html
new file mode 100644
index 0000000000..d09c944fd8
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-02.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<head>
+ <meta charset="utf-8">
+ <title>HTML Test: the browsing contexts created by various container elements</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+
+ var t1 = async_test("Accessing child browsing contexts 1");
+ var t2 = async_test("Accessing child browsing contexts 2");
+ var t3 = async_test("Accessing child browsing contexts 3");
+ function on_load() {
+ //Child browsing contexts created by iframe, object and embed elements.
+ t1.step(function () {
+ assert_equals(window.length, 3, "The top browsing context should have 3 child browsing contexts.");
+ });
+ t1.step(function () {
+ assert_equals(window[0].name, "win1", "The browsing context name should be 'win1'.");
+ assert_equals(window[1].name, "win2", "The browsing context name should be 'win2'.");
+ assert_equals(window[2].name, "win3", "The browsing context name should be 'win3'.");
+ });
+ t1.done();
+
+ //Child browsing contexts created by frame elements.
+ t2.step(function () {
+ assert_equals(document.getElementById("fr").contentWindow.length, 2,
+ "The child browsing context created by the iframe element should have 2 child browsing contexts.");
+ });
+ t2.step(function () {
+ assert_equals(document.getElementById("fr").contentWindow[0].name, "win4",
+ "The browsing context name should be 'win4'.");
+ assert_equals(document.getElementById("fr").contentWindow[1].name, "win5",
+ "The browsing context name should be 'win5'.");
+ });
+ t2.done();
+
+ //The child browsing context will be removed if the data attribute of the associated object element is removed.
+ t3.step(function () {
+ document.getElementById("obj").removeAttribute("type");
+ assert_equals(window.length, 3, "The top browsing context should have 3 child browsing contexts.");
+ document.getElementById("obj").removeAttribute("data");
+ assert_equals(window.length, 3, "The top browsing context should have 3 child browsing contexts.");
+
+ setTimeout(function () {
+ assert_equals(window.length, 2, "The top browsing context should have 2 child browsing contexts.");
+ }, 1);
+ });
+ t3.done();
+ }
+
+ </script>
+</head>
+<body onload="on_load()">
+ <div id="log"></div>
+ <div style="display:none">
+ <iframe id="fr" name="win1" src="test3.html"></iframe>
+ <object id="obj" name="win2" type="text/html" data="about:blank"></object>
+ <object type="image/png" src="/images/green.png"></object>
+ <embed id="emb" name="win3" type="image/svg+xml" src="/images/green.svg"></embed>
+ </div>
+</body>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-03.html b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-03.html
new file mode 100644
index 0000000000..1548891175
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/indexed-browsing-contexts-03.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<head>
+ <meta charset="utf-8">
+ <title>HTML Test: indexed property of a Window object</title>
+ <link rel="author" title="Intel" href="http://www.intel.com/" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+
+ var t1 = async_test("Indexed child browsing contexts");
+ function on_load() {
+ t1.step(function () {
+ assert_equals(window[0], document.getElementsByTagName("object")[0].contentWindow,
+ "The first child browsing context's container should be the object element.");
+ assert_equals(window[1], document.getElementsByTagName("iframe")[0].contentWindow,
+ "The second child browsing context's container should be the iframe element.");
+ });
+ t1.done();
+ }
+
+ </script>
+</head>
+<body onload="on_load()">
+ <div id="log"></div>
+ <div style="display:none">
+ <div id="0"></div>
+ <object name="0" type="text/html" data="test2.html"></object>
+ <iframe name="0" src="about:blank"></iframe>
+ </div>
+</body>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/iterator.html b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/iterator.html
new file mode 100644
index 0000000000..76dc7dbae6
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/iterator.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>window[@@iterator]</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ assert_false(Symbol.iterator in window);
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test1.html b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test1.html
new file mode 100644
index 0000000000..f85f90f7c6
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test1.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: child browsing contexts created by iframe elements</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<table id="tbl">
+ <tr>
+ <td>
+ <iframe id="fr4" src=""></iframe>
+ </td>
+ </tr>
+ <iframe id="fr5" src="about:blank"></iframe>
+</table>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test2.html b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test2.html
new file mode 100644
index 0000000000..d6a16647fe
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test2.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: child browsing contexts created by object and embed elements</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<object type="image/png" src="/images/green.png"></object>
+<embed type="image/png" src="/images/green.png"></embed>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test3.html b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test3.html
new file mode 100644
index 0000000000..a62fdbaae7
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/test3.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: child browsing contexts created by frame elements</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<frameset>
+ <frame name="win4"></frame>
+ <frame name="win5"></frame>
+</frameset>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/window_length.html b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/window_length.html
new file mode 100644
index 0000000000..c9559b531a
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/accessing-other-browsing-contexts/window_length.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<title>window.length</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var iframe;
+var subframe;
+var other_window;
+test(function() {assert_equals(window.length, 0)}, "No child browsing contexts");
+test(function() {
+ iframe = document.createElement("iframe");
+ assert_equals(window.length, 0)
+}, "iframe not inserted into the document");
+
+test(function() {
+ document.body.appendChild(iframe);
+ assert_equals(window.length, 1)
+}, "One iframe inserted into the document");
+
+test(function() {
+ subframe = document.createElement("iframe");
+ iframe.contentDocument.body.appendChild(subframe);
+ assert_equals(window.length, 1);
+}, "Child browsing context has a child browsing context");
+
+test(function() {
+ try {
+ assert_equals(iframe.contentWindow.length, 1);
+ } finally {
+ subframe.parentNode.removeChild(subframe);
+ }
+}, "window.length in child frame");
+
+test(function() {
+ iframe.parentNode.removeChild(iframe);
+ other_window = window.open();
+ assert_equals(window.length, 0);
+ assert_equals(other_window.length, 0);
+}, "Opened window")
+
+test(function() {
+ other_window.document.body.appendChild(iframe);
+ try {
+ assert_equals(other_window.length, 1);
+ } finally {
+ other_window.close();
+ }
+}, "Iframe in opened window")
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/close-method.window.js b/testing/web-platform/tests/html/browsers/the-window-object/close-method.window.js
new file mode 100644
index 0000000000..0288f9cab8
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/close-method.window.js
@@ -0,0 +1,39 @@
+function assert_closed_opener(w, closed, opener) {
+ assert_equals(w.closed, closed);
+ assert_equals(w.opener, opener);
+}
+
+async_test(t => {
+ const openee = window.open();
+ assert_closed_opener(openee, false, self);
+ openee.onunload = t.step_func(() => {
+ assert_closed_opener(openee, true, self);
+ t.step_timeout(() => {
+ assert_closed_opener(openee, true, null);
+ t.done();
+ }, 0);
+ });
+ openee.close();
+ assert_closed_opener(openee, true, self);
+}, "window.close() queues a task to discard, but window.closed knows immediately");
+
+async_test(t => {
+ const openee = window.open("", "greatname");
+ assert_closed_opener(openee, false, self);
+ openee.close();
+ assert_closed_opener(openee, true, self);
+ const openee2 = window.open("", "greatname");
+ assert_not_equals(openee, openee2);
+ assert_closed_opener(openee, true, self); // Ensure second window.open() call was synchronous
+ openee2.onunload = t.step_func(() => {
+ assert_closed_opener(openee2, true, self);
+ t.step_timeout(() => {
+ assert_closed_opener(openee, true, null);
+ assert_closed_opener(openee2, true, null);
+ t.done();
+ }, 0);
+ });
+ openee2.close();
+ assert_closed_opener(openee, true, self); // Ensure second close() call was synchronous
+ assert_closed_opener(openee2, true, self);
+}, "window.close() affects name targeting immediately");
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/closed-attribute.window.js b/testing/web-platform/tests/html/browsers/the-window-object/closed-attribute.window.js
new file mode 100644
index 0000000000..88a3beba6f
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/closed-attribute.window.js
@@ -0,0 +1,69 @@
+// META: script=/common/get-host-info.sub.js
+
+function closedTest(newWindow, closeNewWindowsBrowsingContext) {
+ assert_equals(newWindow.closed, false);
+ closeNewWindowsBrowsingContext();
+ assert_equals(newWindow.closed, true);
+}
+
+test(() => {
+ const frame = document.body.appendChild(document.createElement("iframe"));
+ closedTest(frame.contentWindow, () => frame.remove());
+}, "closed and same-origin nested browsing context");
+
+test(() => {
+ const openee = window.open();
+ closedTest(openee, () => openee.close());
+
+ // close() is a no-op once "is closing" is set
+ openee.close();
+ assert_equals(openee.closed, true);
+}, "closed/close() and same-origin auxiliary browsing context");
+
+const support = new URL("support/closed.html", location.href).pathname;
+[
+ {
+ type: "cross-origin",
+ url: `${get_host_info().HTTP_REMOTE_ORIGIN}${support}`
+ },
+ {
+ type: "cross-site",
+ url: `${get_host_info().HTTP_NOTSAMESITE_ORIGIN}${support}`
+ }
+].forEach(val => {
+ async_test(t => {
+ const frame = document.createElement("iframe"),
+ ident = `${val.type}-nested-bc`;
+ frame.src = `${val.url}?window=parent&ident=${ident}`;
+ const listener = t.step_func(e => {
+ if (e.data === ident) {
+ closedTest(frame.contentWindow, () => frame.remove());
+ self.removeEventListener("message", listener);
+ t.done();
+ }
+ });
+ // Use a message event rather than onload for consistency with auxiliary browsing contexts.
+ self.addEventListener("message", listener);
+ document.body.append(frame);
+ }, `closed and ${val.type} nested browsing context`);
+
+ async_test(t => {
+ const ident = `${val.type}-auxiliary-bc`,
+ support = new URL("support/closed.html", location.href).pathname,
+ openee = window.open(`${val.url}?window=opener&ident=${ident}`),
+ listener = t.step_func(e => {
+ if (e.data === ident) {
+ closedTest(openee, () => openee.close());
+
+ // close() is a no-op once "is closing" is set
+ openee.close();
+ assert_equals(openee.closed, true);
+
+ self.removeEventListener("message", listener);
+ t.done();
+ }
+ });
+ // As there's no cross-origin onload, use a message event.
+ self.addEventListener("message", listener);
+ }, `closed/close() and ${val.type} auxiliary browsing context`);
+});
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/defaultstatus.html b/testing/web-platform/tests/html/browsers/the-window-object/defaultstatus.html
new file mode 100644
index 0000000000..f683f130cd
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/defaultstatus.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>window.defaultStatus and window.defaultstatus are not supported</title>
+<link rel="author" href="mailto:masonf@chromium.org">
+<link rel="help" href="https://developer.mozilla.org/en-US/docs/Web/API/Window/defaultStatus">
+<link rel="help" href="https://crbug.com/692835">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+test(() => {
+ assert_false(window.hasOwnProperty('defaultStatus'));
+ assert_false(window.hasOwnProperty('defaultstatus'));
+ assert_equals(window.defaultStatus,undefined);
+ assert_equals(window.defaultstatus,undefined);
+}, "The window.defaultStatus and window.defaultstatus attributes are not supported");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/document-attribute.window.js b/testing/web-platform/tests/html/browsers/the-window-object/document-attribute.window.js
new file mode 100644
index 0000000000..f13acdb8a3
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/document-attribute.window.js
@@ -0,0 +1,15 @@
+async_test(t => {
+ const frame = document.createElement("iframe");
+ frame.onload = t.step_func(() => {
+ const frameW = frame.contentWindow,
+ frameD = frame.contentDocument;
+ assert_equals(frameW.document, frameD);
+ frame.remove();
+ assert_equals(frameW.document, frameD);
+ t.step_timeout(() => {
+ assert_equals(frameW.document, frameD);
+ t.done();
+ }, 100);
+ });
+ document.body.append(frame);
+}, "Window object's document IDL attribute and discarding the browsing context");
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/focus.window.js b/testing/web-platform/tests/html/browsers/the-window-object/focus.window.js
new file mode 100644
index 0000000000..6ec7feee28
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/focus.window.js
@@ -0,0 +1,15 @@
+async_test(t => {
+ const input = document.body.appendChild(document.createElement("input"));
+ input.onfocus = t.step_func(() => {
+ const frame = document.body.appendChild(document.createElement("iframe")),
+ frameW = frame.contentWindow;
+ frameW.onfocus = t.unreached_func();
+ frame.remove();
+ frameW.focus();
+ t.step_timeout(() => {
+ assert_equals(document.activeElement, input);
+ t.done();
+ }, 100);
+ });
+ input.focus();
+});
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1-1.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1-1.html
new file mode 100644
index 0000000000..217608e46e
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1-1.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<iframe></iframe>
+<script>
+var t = opener.t;
+
+onload = t.step_func(function() {
+ setTimeout(t.step_func(function() {
+ var history_length = history.length;
+ var iframe = document.getElementsByTagName("iframe")[0];
+ iframe.onload = t.step_func(function() {
+ opener.assert_equals(history.length, history_length + 1);
+ iframe.parentNode.removeChild(iframe);
+ opener.assert_equals(history.length, history_length);
+ t.done();
+ window.close();
+ });
+ iframe.src = "discard_iframe_history_1-2.html;";
+ }), 100);
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1-2.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1-2.html
new file mode 100644
index 0000000000..b43598f2cd
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1-2.html
@@ -0,0 +1,2 @@
+<!doctype html>
+Filler text
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1.html
new file mode 100644
index 0000000000..4d1e473fc0
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_1.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>Removing iframe from document removes it from history</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+var w = window.open("discard_iframe_history_1-1.html");
+</script>
+
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_2-1.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_2-1.html
new file mode 100644
index 0000000000..61e5891ebd
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_2-1.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<iframe></iframe>
+<script>
+var t = opener.t;
+
+onload = t.step_func(function() {
+ setTimeout(t.step_func(function() {
+ var history_length = history.length;
+ var iframe = document.getElementsByTagName("iframe")[0];
+ iframe.onload = t.step_func(function() {
+ setTimeout(t.step_func(function() {
+ opener.assert_equals(history.length, history_length + 1, "History length before iframe removal");
+ document.body.innerHTML = "";
+ opener.assert_equals(history.length, history_length, "History length after iframe removal");
+ t.done();
+ window.close();
+ }), 100);
+ });
+ iframe.src = "discard_iframe_history_1-2.html";
+ }), 100);
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_2.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_2.html
new file mode 100644
index 0000000000..89d0fb4c64
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_2.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>Removing iframe from document via innerHTML removes it from history</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+var w = window.open("discard_iframe_history_2-1.html");
+</script>
+
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-1.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-1.html
new file mode 100644
index 0000000000..de3f075d64
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-1.html
@@ -0,0 +1,21 @@
+<script>
+history_lengths = [];
+
+var t = opener.t;
+
+push_length = t.step_func(function () {
+ history_lengths.push(history.length)
+});
+
+do_test = t.step_func(function () {
+ try {
+ var start_length = history_lengths[0];
+ expected = [start_length, start_length + 1, start_length];
+ opener.assert_array_equals(history_lengths, expected);
+ t.done();
+ } finally {
+ window.close();
+ }
+});
+</script>
+<iframe src="discard_iframe_history_3-2.html"></iframe>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-2.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-2.html
new file mode 100644
index 0000000000..95f9fce5d8
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-2.html
@@ -0,0 +1,4 @@
+<a href="discard_iframe_history_3-3.html" onclick="parent.push_length()">Click me</a>
+<script>
+onload = function() {setTimeout(parent.t.step_func(function() {document.links[0].click()}), 100)}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-3.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-3.html
new file mode 100644
index 0000000000..4672b0ec30
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3-3.html
@@ -0,0 +1,4 @@
+<button onclick="var p = parent; p.push_length(); frameElement.parentNode.removeChild(frameElement); p.push_length(); p.do_test();">Click me</button>
+<script>
+onload = function() {setTimeout(parent.t.step_func(function() {document.getElementsByTagName("button")[0].click()}), 100)}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3.html
new file mode 100644
index 0000000000..38dbdbd0fa
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_3.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Removing iframe from document removes it from history</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+var w = window.open("discard_iframe_history_3-1.html");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-1.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-1.html
new file mode 100644
index 0000000000..1b5726cdcd
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-1.html
@@ -0,0 +1,21 @@
+<script>
+history_lengths = [];
+
+var t = opener.t;
+
+push_length = t.step_func(function () {
+ history_lengths.push(history.length)
+});
+
+do_test = t.step_func(function () {
+ try {
+ var start_length = history_lengths[0];
+ expected = [start_length, start_length + 1, start_length];
+ opener.assert_array_equals(history_lengths, expected);
+ t.done();
+ } finally {
+ window.close();
+ }
+});
+</script>
+<iframe src="discard_iframe_history_4-2.html"></iframe>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-2.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-2.html
new file mode 100644
index 0000000000..979b2b28e4
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-2.html
@@ -0,0 +1,4 @@
+<a href="discard_iframe_history_4-3.html" onclick="parent.push_length()">Click me</a>
+<script>
+onload = function() {setTimeout(parent.t.step_func(function() {document.links[0].click()}), 100)}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-3.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-3.html
new file mode 100644
index 0000000000..b4308f439a
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4-3.html
@@ -0,0 +1,4 @@
+<button onclick="var p = parent; p.push_length(); frameElement.parentNode.innerHTML = ''; p.push_length(); p.do_test();">Click me</button>
+<script>
+onload = function() {setTimeout(parent.t.step_func(function() {document.getElementsByTagName("button")[0].click()}), 100)}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4.html
new file mode 100644
index 0000000000..ffd444e3bf
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/discard_iframe_history_4.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Removing iframe from document removes it from history</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+var w = window.open("discard_iframe_history_4-1.html");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-1.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-1.html
new file mode 100644
index 0000000000..9969427989
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-1.html
@@ -0,0 +1,27 @@
+<!doctype html>
+<iframe></iframe>
+<script>
+var t = opener.t;
+var iframe = document.getElementsByTagName("iframe")[0];
+var history_length;
+
+function load_frame(src) {
+ history_length = history.length;
+ iframe.src = src;
+ var button = document.getElementsByTagName("button")[0];
+ button.parentNode.removeChild(button);
+}
+
+remove_frame = t.step_func(function() {
+ try {
+ opener.assert_equals(history.length, history_length + 1, "History length after loading page in iframe");
+ iframe.parentNode.removeChild(iframe);
+ opener.assert_equals(history.length, history_length, "History length after removing iframe");
+ t.done();
+ } finally {
+ window.close();
+ }
+});
+
+</script>
+<button onclick="load_frame('discard_iframe_history_1-2.html')">Click here</button>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-2.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-2.html
new file mode 100644
index 0000000000..8c3d1a9dad
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-2.html
@@ -0,0 +1,2 @@
+<!doctype html>
+<button onclick="parent.remove_frame()">Click here</button>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-manual.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-manual.html
new file mode 100644
index 0000000000..ca9dd91f2e
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_1-manual.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>Removing iframe from document removes it from history</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+setup({timeout:3600000})
+var t = async_test();
+var w = window.open("discard_iframe_history_1-1.html");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-1.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-1.html
new file mode 100644
index 0000000000..bc01cae88c
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-1.html
@@ -0,0 +1,19 @@
+<script>
+history_lengths = [];
+
+function push_length() {
+ history_lengths.push(history.length)
+}
+
+do_test = opener.t.step_func(function () {
+ try {
+ var start_length = history_lengths[0];
+ expected = [start_length, start_length + 1, start_length];
+ opener.assert_array_equals(history_lengths, expected);
+ opener.t.done();
+ } finally {
+ window.close();
+ }
+});
+</script>
+<iframe src="discard_iframe_history_2-2.html"></iframe>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-2.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-2.html
new file mode 100644
index 0000000000..b25bf5f001
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-2.html
@@ -0,0 +1 @@
+<a href="discard_iframe_history_2-3.html" onclick="parent.push_length()">Click me</a>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-3.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-3.html
new file mode 100644
index 0000000000..68847e9a7c
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-3.html
@@ -0,0 +1 @@
+<button onclick="var p = parent; p.push_length(); frameElement.parentNode.removeChild(frameElement); p.push_length(); p.do_test();">Click me</button>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-manual.html b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-manual.html
new file mode 100644
index 0000000000..57eaabcd0c
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/garbage-collection-and-browsing-contexts/non-automated/discard_iframe_history_2-manual.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<title>Removing iframe from document removes it from history</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+setup({timeout:3600000})
+var t = async_test();
+var w = window.open("discard_iframe_history_2-1.html");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/historical.window.js b/testing/web-platform/tests/html/browsers/the-window-object/historical.window.js
new file mode 100644
index 0000000000..653f12b464
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/historical.window.js
@@ -0,0 +1,4 @@
+test(() => {
+ assert_false("showModalDialog" in window)
+ assert_false("showModalDialog" in Window.prototype)
+}, "showModalDialog() has been removed from the platform")
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/length-attribute.window.js b/testing/web-platform/tests/html/browsers/the-window-object/length-attribute.window.js
new file mode 100644
index 0000000000..d56e1e4692
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/length-attribute.window.js
@@ -0,0 +1,24 @@
+async_test(t => {
+ const frame = document.createElement("iframe");
+ frame.srcdoc = "<iframe name=x srcdoc='<iframe name=z></iframe>'></iframe><iframe name=y></iframe>";
+ frame.onload = t.step_func_done(() => {
+ const frameW = frame.contentWindow;
+ assert_equals(frameW.length, 2);
+ assert_not_equals(frameW.x, undefined);
+ assert_not_equals(frameW.y, undefined);
+ assert_equals(frameW.z, undefined);
+ assert_equals(frameW.x, frameW[0]);
+ assert_equals(frameW.y, frameW[1]);
+ const xFrameW = frameW.x;
+ assert_equals(xFrameW.length, 1);
+ assert_not_equals(xFrameW.z, undefined);
+ assert_equals(xFrameW.z, xFrameW[0]);
+ frame.remove();
+ assert_equals(frameW.length, 0);
+ assert_equals(frameW.x, undefined);
+ assert_equals(frameW[0], undefined);
+ assert_equals(xFrameW.length, 0);
+ assert_equals(xFrameW.z, undefined);
+ });
+ document.body.append(frame);
+}, "Window object's length IDL attribute (and named access)");
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/name-attribute.window.js b/testing/web-platform/tests/html/browsers/the-window-object/name-attribute.window.js
new file mode 100644
index 0000000000..f266dd7acb
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/name-attribute.window.js
@@ -0,0 +1,18 @@
+test(() => {
+ const frame = document.createElement("iframe"),
+ name = "A",
+ name2 = "B";
+ frame.setAttribute("name", name);
+ document.body.append(frame);
+ const frameW = frame.contentWindow;
+ assert_equals(frameW.name, name);
+ frameW.name = name2;
+ assert_equals(frame.getAttribute("name"), name);
+ assert_equals(frameW.name, name2);
+ frame.remove();
+ assert_equals(frame.getAttribute("name"), name);
+ assert_equals(frameW.name, "");
+ frameW.name = name2;
+ assert_equals(frame.getAttribute("name"), name);
+ assert_equals(frameW.name, "");
+}, "Window object's name IDL attribute");
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/cross-global-npo.html b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/cross-global-npo.html
new file mode 100644
index 0000000000..2acad0734c
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/cross-global-npo.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Named access across globals</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+async_test(function() {
+ var iframe = document.createElement("iframe");
+ iframe.src = "cross-global-support.html";
+ document.body.appendChild(iframe);
+ iframe.onload = this.step_func_done(function() {
+ var name = "named";
+ var win = iframe.contentWindow;
+ var element = win.document.getElementById(name);
+
+ var expectedValues = [
+ // [value, is own property]
+ [element, false, "window"],
+ [element, false, "Window.prototype"],
+ [element, true, "named prototype object"],
+ [undefined, false, "EventTarget.prototype"],
+ [undefined, false, "Object.prototype"],
+ ];
+ for (var object = win; object; object = Object.getPrototypeOf(object)) {
+ var expected = expectedValues.shift();
+ assert_equals(object[name], expected[0], "[[Get]] on " + expected[2]);
+ var desc = Object.getOwnPropertyDescriptor(object, name);
+ if (expected[1]) {
+ assert_not_equals(desc, undefined, "[[GetOwnProperty]] on " + expected[2] + " should return something");
+ assert_equals(desc.value, element, "[[GetOwnProperty]] on " + expected[2]);
+ } else {
+ assert_equals(desc, undefined, "[[GetOwnProperty]] on " + expected[2]);
+ }
+ }
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/cross-global-support.html b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/cross-global-support.html
new file mode 100644
index 0000000000..9d7b9f8a25
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/cross-global-support.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Named access across globals: support file</title>
+<span id="named"></span>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/named-objects.html b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/named-objects.html
new file mode 100644
index 0000000000..d5b1789d59
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/named-objects.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Named access on the Window object</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/browsers.html#named-access-on-the-window-object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<div style="display:none">
+ <p name="a" id="p1"></p>
+ <a name="a" id="a1" href="#"></a>
+ <area name="a" id="area1"></area>
+ <embed name="a" id="embed1"></embed>
+ <form name="a" id="form1"></form>
+ <img name="a" id="img1">
+ <object name="a" id="obj1"></object>
+ <span name="a" id="span1"></span>
+
+ <b id="b" name="c"></b>
+ <a name="c"></a>
+ <iframe name="c" id="fm1"></iframe>
+ <iframe name="c" id="fm2" src="test.html" onload="on_load()"></iframe>
+ <input id="b"></input>
+ <span id="d"></span>
+ <a name=""></a>
+ <b id=""></b>
+</div>
+<script>
+
+test(function() {
+ assert_equals(window['c'], document.getElementById("fm1").contentWindow, "The first iframe's window should be returned.");
+}, "Check if the first nested browsing context is returned by window['c']");
+
+test(function() {
+ assert_true(window['a'] instanceof HTMLCollection);
+ assert_array_equals(window['a'],
+ [ document.getElementById('embed1'),
+ document.getElementById('form1'), document.getElementById('img1'),
+ document.getElementById('obj1') ],
+ "The elements are not in tree order.");
+
+ document.getElementById('form1').setAttribute("name", "");
+ document.getElementById('embed1').setAttribute("name", "");
+ assert_array_equals(window['a'],
+ [ document.getElementById('img1'),
+ document.getElementById('obj1') ],
+ "Window['a'] should not contain the elements with empty name attribute.");
+}, "Check if window['a'] contains all embed, form, img, and object elements, and their order");
+
+var t = async_test("Check that window['fs'] does not return the frameset element with name='fs' (historical)");
+function on_load () {
+ t.step(function () {
+ assert_equals(document.getElementById('fm2').contentWindow['fs'],
+ undefined,
+ "The frameset element should not be returned.");
+ });
+ t.done();
+}
+
+test(function() {
+ assert_true(window['b'] instanceof HTMLCollection);
+ assert_array_equals(window['b'], [document.getElementsByTagName('b')[0], document.getElementsByTagName('input')[0]]);
+
+ document.getElementsByTagName('b')[0].setAttribute("id", "");
+ assert_equals(window['b'], document.getElementsByTagName('input')[0],
+ "The window['b'] should not contain the elements with empty id attribute.");
+}, "Check if window['b'] returns the elements with the id='b'");
+
+test(function() {
+ assert_equals(window['d'], document.getElementById('d'));
+}, "Check if window['d'] returns the element with id='d'");
+
+test(function() {
+ assert_equals(window[''], undefined, "The window[''] should be undefined");
+}, "Check widow[''] when there are some elements with empty id or name attribute");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/navigated-named-objects.window.js b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/navigated-named-objects.window.js
new file mode 100644
index 0000000000..59d94efc99
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/navigated-named-objects.window.js
@@ -0,0 +1,67 @@
+// META: script=/common/get-host-info.sub.js
+
+function echoURL(content) {
+ return `/common/echo.py?content=${encodeURIComponent(content)}`;
+}
+
+function setSrc(frame, type, content) {
+ if (type === "same-origin") {
+ frame.src = echoURL(content);
+ } else if (type === "cross-site") {
+ frame.src = `${get_host_info().HTTP_NOTSAMESITE_ORIGIN}${echoURL(content)}`;
+ } else {
+ frame.srcdoc = content;
+ }
+}
+
+["srcdoc", "same-origin", "cross-site"].forEach(type => {
+ const initialType = type === "srcdoc" ? type : "same-origin";
+
+ [
+ {
+ "namedObject": "<div id=abc></div>",
+ "namedObjectLocalName": "div"
+ },
+ {
+ "namedObject": "<object name=abc></object>",
+ "namedObjectLocalName": "object"
+ },
+ {
+ "namedObject": "<iframe id=abc></iframe>",
+ "namedObjectLocalName": "iframe"
+ }
+ ].forEach(testData => {
+ async_test(t => {
+ const frame = document.createElement("iframe");
+ t.add_cleanup(() => frame.remove());
+ setSrc(frame, initialType, `<script>function f() { return abc }</script>${testData.namedObject}`);
+ frame.onload = t.step_func(() => {
+ const f = frame.contentWindow.f,
+ associatedAbc = f();
+ frame.onload = t.step_func_done(() => {
+ assert_equals(f(), associatedAbc);
+ assert_equals(associatedAbc.localName, testData.namedObjectLocalName);
+ });
+ setSrc(frame, type, "<span id=abc></span>");
+ });
+ document.body.append(frame);
+ }, `Window's associated Document object is used for finding named objects (<${testData.namedObjectLocalName}> via ${type} <iframe>)`);
+ });
+
+ async_test(t => {
+ const frame = document.createElement("iframe");
+ t.add_cleanup(() => frame.remove());
+ setSrc(frame, initialType, "<script>function f() { return abc }</script><object name=abc data='about:blank'></object>");
+ frame.onload = t.step_func(() => {
+ const f = frame.contentWindow.f,
+ associatedAbc = f(),
+ associatedAbcContainer = associatedAbc.frameElement;
+ frame.onload = t.step_func_done(() => {
+ assert_equals(f(), associatedAbcContainer);
+ assert_equals(associatedAbcContainer.contentWindow, null);
+ });
+ setSrc(frame, type, "<span id=abc></span>");
+ });
+ document.body.append(frame);
+ }, `Window's associated Document object is used for finding named objects (<object> with browsing ccontext via ${type} <iframe)>`);
+});
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/prototype.html b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/prototype.html
new file mode 100644
index 0000000000..910374381b
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/prototype.html
@@ -0,0 +1,94 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Named access with shadowing properties</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var name = "named1";
+ window[name] = "shadowing";
+ var element = document.createElement("span");
+ element.id = name;
+ document.body.appendChild(element);
+
+ assert_equals(window[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(window, name).value, "shadowing");
+
+ assert_equals(Window.prototype[name], element);
+ assert_equals(Object.getOwnPropertyDescriptor(Window.prototype, name), undefined);
+
+ var npo = Object.getPrototypeOf(Window.prototype);
+ assert_equals(npo[name], element);
+ assert_equals(Object.getOwnPropertyDescriptor(npo, name).value, element);
+
+ assert_equals(EventTarget.prototype[name], undefined);
+ assert_equals(Object.getOwnPropertyDescriptor(EventTarget.prototype, name), undefined);
+}, "Property on window.");
+
+test(function() {
+ var name = "named2";
+ Window.prototype[name] = "shadowing";
+ var element = document.createElement("span");
+ element.id = name;
+ document.body.appendChild(element);
+
+ assert_equals(window[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(window, name), undefined);
+
+ assert_equals(Window.prototype[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(Window.prototype, name).value, "shadowing");
+
+ var npo = Object.getPrototypeOf(Window.prototype);
+ assert_equals(npo[name], element);
+ assert_equals(Object.getOwnPropertyDescriptor(npo, name).value, element);
+
+ assert_equals(EventTarget.prototype[name], undefined);
+ assert_equals(Object.getOwnPropertyDescriptor(EventTarget.prototype, name), undefined);
+}, "Property on Window.prototype.");
+
+test(function() {
+ var name = "named3";
+ EventTarget.prototype[name] = "shadowing";
+ var element = document.createElement("span");
+ element.id = name;
+ document.body.appendChild(element);
+
+ assert_equals(window[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(window, name), undefined);
+
+ assert_equals(Window.prototype[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(Window.prototype, name), undefined);
+
+ var npo = Object.getPrototypeOf(Window.prototype);
+ assert_equals(npo[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(npo, name), undefined);
+
+ assert_equals(EventTarget.prototype[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(EventTarget.prototype, name).value, "shadowing");
+}, "Property on EventTarget.prototype.");
+
+test(function() {
+ var name = "named4";
+ Object.prototype[name] = "shadowing";
+ var element = document.createElement("span");
+ element.id = name;
+ document.body.appendChild(element);
+
+ assert_equals(window[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(window, name), undefined);
+
+ assert_equals(Window.prototype[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(Window.prototype, name), undefined);
+
+ var npo = Object.getPrototypeOf(Window.prototype);
+ assert_equals(npo[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(npo, name), undefined);
+
+ assert_equals(EventTarget.prototype[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(EventTarget.prototype, name), undefined);
+
+ assert_equals(Object.prototype[name], "shadowing");
+ assert_equals(Object.getOwnPropertyDescriptor(Object.prototype, name).value, "shadowing");
+}, "Property on Object.prototype.");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/test.html b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/test.html
new file mode 100644
index 0000000000..c3b3cc1852
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/test.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Named Object</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<frameset name="fs" id="fs1">
+ <frame></frame>
+</frameset>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/window-named-properties.html b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/window-named-properties.html
new file mode 100644
index 0000000000..bd3929dd89
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/window-named-properties.html
@@ -0,0 +1,83 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Changes to named properties of the window object</title>
+<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
+<link rel="author" title="Boris Zbarsky" href="bzbarsky@mit.edu">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-window-nameditem">
+<link rel="help" href="https://webidl.spec.whatwg.org/#named-properties-object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe name="bar"></iframe>
+<iframe name="baz"></iframe>
+<iframe name="baz"></iframe>
+<iframe name="constructor"></iframe>
+<iframe id="quux"></iframe>
+<script>
+function assert_data_propdesc(pd, Writable, Enumerable, Configurable) {
+ assert_equals(typeof pd, "object");
+ assert_equals(pd.writable, Writable);
+ assert_equals(pd.enumerable, Enumerable);
+ assert_equals(pd.configurable, Configurable);
+}
+test(function() {
+ assert_true("bar" in window, "bar not in window");
+ assert_equals(window["bar"],
+ document.getElementsByTagName("iframe")[0].contentWindow);
+}, "Static name");
+
+test(function() {
+ assert_true("quux" in window, "quux not in window");
+ assert_equals(window["quux"],
+ document.getElementsByTagName("iframe")[4]);
+}, "Static id");
+
+test(function() {
+ assert_true("bar" in Window.prototype, "bar in Window.prototype");
+ assert_false(Window.prototype.hasOwnProperty("bar"), "Window.prototype.hasOwnProperty(\"bar\")");
+
+ var gsp = Object.getPrototypeOf(Object.getPrototypeOf(window));
+ assert_true("bar" in gsp, "bar in gsp");
+ assert_true(gsp.hasOwnProperty("bar"), "gsp.hasOwnProperty(\"bar\")");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(gsp, "bar"),
+ true, false, true);
+}, "Static name on the prototype");
+test(function() {
+ assert_equals(window.constructor, Window);
+ assert_false(window.hasOwnProperty("constructor"), "window.constructor should not be an own property.");
+
+ var proto = Object.getPrototypeOf(window);
+ assert_equals(proto.constructor, Window);
+ assert_true("constructor" in proto, "constructor in proto");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(proto, "constructor"),
+ true, false, true);
+
+ var gsp = Object.getPrototypeOf(proto);
+ assert_true("constructor" in gsp, "constructor in gsp");
+ assert_false(gsp.hasOwnProperty("constructor"), "gsp.hasOwnProperty(\"constructor\")");
+ assert_equals(Object.getOwnPropertyDescriptor(gsp, "constructor"), undefined);
+}, "constructor");
+test(function() {
+ var gsp = Object.getPrototypeOf(Object.getPrototypeOf(window));
+ assert_equals(gsp.baz, document.getElementsByTagName("iframe")[1].contentWindow);
+}, "duplicate property names")
+var t = async_test("Dynamic name")
+var t2 = async_test("Ghost name")
+t.step(function() {
+ var iframe = document.getElementsByTagName("iframe")[0];
+ iframe.setAttribute("srcdoc", "<script>window.name='foo'<\/script>");
+ iframe.onload = function() {
+ t.step(function() {
+ assert_true("foo" in window, "foo not in window");
+ assert_equals(window["foo"], iframe.contentWindow);
+ });
+ t.done();
+ t2.step(function() {
+ assert_false("bar" in window, "bar still in window");
+ assert_equals(window["bar"], undefined);
+ });
+ t2.done();
+ };
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/window-null-names.html b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/window-null-names.html
new file mode 100644
index 0000000000..6801ef9d8a
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/named-access-on-the-window-object/window-null-names.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Named access with null characters</title>
+<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-window-nameditem">
+<link rel="help" href="https://webidl.spec.whatwg.org/#named-properties-object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var iframe = document.createElement("iframe")
+ iframe.name = "a\0b"
+ document.body.appendChild(iframe)
+ assert_equals(window["a\0b"], iframe.contentWindow)
+ assert_equals(window["ab"], undefined)
+ assert_equals(window["a"], undefined)
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/navigate-to-about-blank-while-initial-load-pending.html b/testing/web-platform/tests/html/browsers/the-window-object/navigate-to-about-blank-while-initial-load-pending.html
new file mode 100644
index 0000000000..3a0def8ae6
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/navigate-to-about-blank-while-initial-load-pending.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test navigating to about:blank while window.open initial load pending.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test(t => {
+ // Open a new window and initiate a navigation. The test does not actually
+ // expect this navigation to complete so it does not matter what URL is
+ // used other than it must not be about:blank. The intent is to start a
+ // navigation to some URL and then assign about:blank to the location
+ // attribute. This assignment should stop the inital navigation and start a
+ // new navigation to about:blank. When the about:blank page finishes loading
+ // the load event is expected to fire and the document URL should to be set to
+ // about:blank.
+ var window1 = window.open('resources/post-to-opener.html', '_blank');
+ t.add_cleanup(() => {
+ window1.close();
+ });
+ window1.location = 'about:blank';
+ window1.onload = t.step_func_done(e => {
+ assert_equals(window1.document.URL, "about:blank");
+ });
+}, 'Navigating to about:blank while window.open initial load pending.');
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/noopener-noreferrer-BarProp.window.js b/testing/web-platform/tests/html/browsers/the-window-object/noopener-noreferrer-BarProp.window.js
new file mode 100644
index 0000000000..a75a034650
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/noopener-noreferrer-BarProp.window.js
@@ -0,0 +1,23 @@
+const barProps = ["locationbar", "menubar", "personalbar", "scrollbars", "statusbar", "toolbar"];
+
+test(() => {
+ for(const prop of barProps) {
+ assert_true(window[prop].visible);
+ }
+}, "All bars visible");
+
+["noopener", "noreferrer"].forEach(openerStyle => {
+ async_test(t => {
+ const channelName = "5454" + openerStyle + "34324";
+ const channel = new BroadcastChannel(channelName);
+ window.open("support/BarProp-target.html?" + channelName, "", openerStyle);
+ channel.onmessage = t.step_func_done(e => {
+ // Send message first so if asserts throw the popup is still closed
+ channel.postMessage(null);
+
+ for(const prop of barProps) {
+ assert_true(e.data[prop]);
+ }
+ });
+ }, `window.open() with ${openerStyle} should have all bars visible`);
+});
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/noopener-noreferrer-sizing.window.js b/testing/web-platform/tests/html/browsers/the-window-object/noopener-noreferrer-sizing.window.js
new file mode 100644
index 0000000000..cc53ba5f2f
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/noopener-noreferrer-sizing.window.js
@@ -0,0 +1,17 @@
+const windowProps = ["innerWidth", "innerHeight"];
+
+["noopener", "noreferrer"].forEach(openerStyle => {
+ async_test(t => {
+ const channelName = "34342" + openerStyle + "8907";
+ const channel = new BroadcastChannel(channelName);
+ window.open("support/sizing-target.html?" + channelName, "", openerStyle);
+ channel.onmessage = t.step_func_done(e => {
+ // Send message first so if asserts throw the popup is still closed
+ channel.postMessage(null);
+
+ for(const prop of windowProps) {
+ assert_equals(window[prop], e.data[prop]);
+ }
+ });
+ }, `window.open() with ${openerStyle} should have equal viewport width and height`);
+});
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/callback.js b/testing/web-platform/tests/html/browsers/the-window-object/open-close/callback.js
new file mode 100644
index 0000000000..ae51265a21
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/callback.js
@@ -0,0 +1 @@
+opener.callback() \ No newline at end of file
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_beforeunload-1.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_beforeunload-1.html
new file mode 100644
index 0000000000..6f44d8a83e
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_beforeunload-1.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<script>
+onload = function() {opener.postMessage("loaded", "*")};
+onbeforeunload = function() {
+ opener.callback();
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_beforeunload.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_beforeunload.html
new file mode 100644
index 0000000000..dcb8830ab6
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_beforeunload.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>Running beforeunload handler in window.close()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+var w = window.open("close_beforeunload-1.html");
+onmessage = t.step_func(function(event) {
+ if (event.data != "loaded") {
+ return;
+ }
+ w.close();
+});
+callback = function() {t.done()}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_script_defer-1.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_script_defer-1.html
new file mode 100644
index 0000000000..c50eddd41f
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_script_defer-1.html
@@ -0,0 +1 @@
+<!doctype html>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_script_defer.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_script_defer.html
new file mode 100644
index 0000000000..1217882b16
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_script_defer.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Running defer script in window.close()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+t.step(function() {
+ var w = window.open("close_script_defer-1.html");
+ w.document.open()
+ w.document.write("<script defer src='callback.js'><\/script>")
+ setTimeout(function() {
+ w.close();
+ }, 1000);
+})
+setTimeout(function() {t.done();}, 1000)
+callback = t.step(function() {assert_unreached()})
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_unload-1.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_unload-1.html
new file mode 100644
index 0000000000..9a9e304e84
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_unload-1.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<script>
+onload = function() {opener.postMessage("loaded", "*")};
+onunload = function() {
+ opener.callback();
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_unload.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_unload.html
new file mode 100644
index 0000000000..e4d231b285
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/close_unload.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<title>Running unload handler in window.close()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test();
+var w = window.open("close_unload-1.html");
+onmessage = t.step_func(function(event) {
+ if (event.data != "loaded") {
+ return;
+ }
+ w.close();
+});
+callback = function() {t.done()}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/creating_browsing_context_test_01.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/creating_browsing_context_test_01.html
new file mode 100644
index 0000000000..062f61949d
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/creating_browsing_context_test_01.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>[Browsing Context] : [APIs for creating browsing_contexts by name]</title>
+<link rel="author" title="Duhyeong Kim" href="mailto:dduskim@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+<meta name=timeout content=long>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function() {
+ var currentUrl = 'http://' + window.location.host + '/common/blank.html';
+ var win = window.open(currentUrl, '', 'height=1,width=1');
+ this.add_cleanup(function() { win.close(); });
+ win.onload = this.step_func_done(function () {
+ assert_equals(win.location.href, currentUrl, 'should be equal to result url');
+ });
+}, 'first argument: absolute url');
+
+test(function() {
+ var win = window.open('', '', 'height=1,width=1');
+ this.add_cleanup(function() { win.close(); });
+ assert_equals(win.location.href, 'about:blank', 'win.location.href');
+ assert_equals(win.document.charset, 'UTF-8', 'win.document.charset');
+}, 'first argument: empty url');
+
+test(function () {
+ var win = window.open('', 'testWindow', 'height=1,width=1');
+ win.close();
+ assert_equals(win.name, 'testWindow', 'should have a browsing context name');
+}, 'second argument: passing a non-empty name');
+
+test(function () {
+ var win = window.open('', '', 'height=1,width=1');
+ this.add_cleanup(function() { win.close(); });
+ assert_equals(win.name, '', 'window should not have a name');
+ win.name = 'testWindow';
+ assert_equals(win.name, 'testWindow', 'window should have a name');
+}, 'second argument: setting name after opening');
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/no_window_open_when_term_nesting_level_nonzero.window.js b/testing/web-platform/tests/html/browsers/the-window-object/open-close/no_window_open_when_term_nesting_level_nonzero.window.js
new file mode 100644
index 0000000000..3dff403b9c
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/no_window_open_when_term_nesting_level_nonzero.window.js
@@ -0,0 +1,113 @@
+test(function() {
+ var test_window = window.open('', '', 'height=1,width=1');
+ var test_document = test_window.document;
+
+ var frame = test_document.createElement('iframe');
+ test_document.body.appendChild(frame);
+
+ frame.contentWindow.onpagehide = function(evt) {
+ assert_equals(frame.contentWindow.open('', '', 'height=1,width=1'), null,
+ "expected no popup during pagehide");
+ };
+ frame.contentDocument.onvisibilitychange = function(evt) {
+ assert_equals(frame.contentWindow.open('', '', 'height=1,width=1'), null,
+ "expected no popup during visibilitychange");
+ };
+ frame.contentWindow.onbeforeunload = function(evt) {
+ assert_equals(frame.contentWindow.open('', '', 'height=1,width=1'), null,
+ "expected no popup during beforeunload");
+ };
+ frame.contentWindow.onunload = function(evt) {
+ assert_equals(frame.contentWindow.open('', '', 'height=1,width=1'), null,
+ "expected no popup during unload");
+ };
+
+ frame.remove();
+}, 'no popups with frame removal');
+
+async_test(function(t) {
+ var test_window = window.open('', '', 'height=1,width=1');
+ var test_document = test_window.document;
+
+ var frame = test_document.createElement('iframe');
+ test_document.body.appendChild(frame);
+
+ frame.contentWindow.onpagehide = t.step_func(function(evt) {
+ assert_equals(frame.contentWindow.open('', '', 'height=1,width=1'), null,
+ "expected no popup during pagehide");
+ });
+ frame.contentDocument.onvisibilitychange = t.step_func(function(evt) {
+ assert_equals(frame.contentWindow.open('', '', 'height=1,width=1'), null,
+ "expected no popup during visibilitychange");
+ });
+ frame.contentWindow.onbeforeunload = t.step_func(function(evt) {
+ assert_equals(frame.contentWindow.open('', '', 'height=1,width=1'), null,
+ "expected no popup during beforeunload");
+ });
+ frame.contentWindow.onunload = t.step_func(function(evt) {
+ assert_equals(frame.contentWindow.open('', '', 'height=1,width=1'), null,
+ "expected no popup during unload");
+ });
+
+ frame.onload = t.step_func_done();
+
+ frame.contentWindow.location.href = "about:blank";
+}, 'no popups with frame navigation');
+
+async_test(function(t) {
+ var test_window = window.open('', '', 'height=1,width=1');
+ var test_document = test_window.document;
+
+ var frame = test_document.createElement('iframe');
+ test_document.body.appendChild(frame);
+
+ frame.contentWindow.onpagehide = t.step_func(function(evt) {
+ assert_equals(test_window.open('', '', 'height=1,width=1'), null,
+ "expected no popup during pagehide");
+ });
+ frame.contentDocument.onvisibilitychange = t.step_func(function(evt) {
+ assert_equals(test_window.open('', '', 'height=1,width=1'), null,
+ "expected no popup during visibilitychange");
+ });
+ frame.contentWindow.onbeforeunload = t.step_func(function(evt) {
+ assert_equals(test_window.open('', '', 'height=1,width=1'), null,
+ "expected no popup during beforeunload");
+ });
+ frame.contentWindow.onunload = t.step_func(function(evt) {
+ assert_equals(test_window.open('', '', 'height=1,width=1'), null,
+ "expected no popup during unload");
+ });
+
+ frame.onload = t.step_func_done();
+
+ frame.contentWindow.location.href = "about:blank";
+}, 'no popups from synchronously reachable window');
+
+async_test(function(t) {
+ var test_window = window.open('', '', 'height=1,width=1');
+ var test_document = test_window.document;
+
+ var frame = test_document.createElement('iframe');
+ test_document.body.appendChild(frame);
+
+ frame.contentWindow.onpagehide = t.step_func(function(evt) {
+ assert_equals(window.open('', '', 'height=1,width=1'), null,
+ "expected no popup during pagehide");
+ });
+ frame.contentDocument.onvisibilitychange = t.step_func(function(evt) {
+ assert_equals(window.open('', '', 'height=1,width=1'), null,
+ "expected no popup during visibilitychange");
+ });
+ frame.contentWindow.onbeforeunload = t.step_func(function(evt) {
+ assert_equals(window.open('', '', 'height=1,width=1'), null,
+ "expected no popup during beforeunload");
+ });
+ frame.contentWindow.onunload = t.step_func(function(evt) {
+ assert_equals(window.open('', '', 'height=1,width=1'), null,
+ "expected no popup during unload");
+ });
+
+ frame.onload = t.step_func_done();
+
+ frame.contentWindow.location.href = "about:blank";
+}, 'no popups from another synchronously reachable window');
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001-1.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001-1.html
new file mode 100644
index 0000000000..7dd48b41c2
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001-1.html
@@ -0,0 +1,2 @@
+<!doctype html>
+<p>Now open a new tab and navigate to <a href="001-2.html">001-2</a></p>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001-2.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001-2.html
new file mode 100644
index 0000000000..b1413861a3
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001-2.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<script>
+var result = "FAIL";
+if (opener != null) {
+ result = "FAIL (did you open this page in a new tab?)";
+} else {
+ var w = window.open("", "test_name");
+ if (w.location.href !== "about:blank") {
+ result = "FAIL (didn't open an about:blank browsing context)";
+ } else {
+ w.close();
+ result = "PASS";
+ }
+ document.write(result);
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001.html
new file mode 100644
index 0000000000..7b0f21ec04
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/001.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<title>Accessing named windows from outside the unit of related browsing contexts</title>
+<a href="001-1.html" target="test_name">Click here</a>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002-1.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002-1.html
new file mode 100644
index 0000000000..0e210f351b
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002-1.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<p>Now open a new tab and navigate to <a></a></p>
+<script>
+href = window.location.href.replace("http://", "http://www.").replace("002-1.html", "002-2.html");
+var a = document.getElementsByTagName("a")[0];
+a.href = href;
+a.textContent = href;
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002-2.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002-2.html
new file mode 100644
index 0000000000..b1413861a3
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002-2.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<script>
+var result = "FAIL";
+if (opener != null) {
+ result = "FAIL (did you open this page in a new tab?)";
+} else {
+ var w = window.open("", "test_name");
+ if (w.location.href !== "about:blank") {
+ result = "FAIL (didn't open an about:blank browsing context)";
+ } else {
+ w.close();
+ result = "PASS";
+ }
+ document.write(result);
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002.html
new file mode 100644
index 0000000000..b568ae8d48
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/non_automated/002.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<title>Accessing different-origin named windows from outside the unit of related browsing contexts</title>
+<a href="002-1.html" target="test_name">Click here</a>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-is-popup-condition.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-is-popup-condition.html
new file mode 100644
index 0000000000..4f52e2e8de
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-is-popup-condition.html
@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: condition for is popup</title>
+<meta name="variant" content="?single-1">
+<meta name="variant" content="?single-2">
+<meta name="variant" content="?position">
+<meta name="variant" content="?combination">
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/window-object.html#window-open-steps">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var windowURL = 'resources/is-popup-barprop.html';
+
+var target = document.location.search.substring(1);
+
+// features, visible
+// NOTE: visible == !isPopup
+var tests = {
+ "single-1": [
+ // Empty feature results in non-popup.
+ [undefined, true],
+
+ // The explicit popup feature.
+ ["popup", false],
+ ["popup=1", false],
+ ["popup=true", false],
+ ["popup=0", true],
+
+ // Other feature alone results in popup.
+ ["location", false],
+ ["location=yes", false],
+ ["location=true", false],
+ ["location=no", false],
+
+ ["toolbar", false],
+ ["toolbar=yes", false],
+ ["toolbar=true", false],
+ ["toolbar=no", false],
+
+ ["menubar", false],
+ ["menubar=yes", false],
+ ["menubar=true", false],
+ ["menubar=no", false],
+
+ ["resizable", false],
+ ["resizable=yes", false],
+ ["resizable=true", false],
+ ["resizable=no", false],
+ ],
+ "single-2": [
+ ["scrollbars", false],
+ ["scrollbars=yes", false],
+ ["scrollbars=true", false],
+ ["scrollbars=no", false],
+
+ ["status", false],
+ ["status=yes", false],
+ ["status=true", false],
+ ["status=no", false],
+
+ ["titlebar", false],
+ ["titlebar=yes", false],
+ ["titlebar=true", false],
+ ["titlebar=no", false],
+
+ ["close", false],
+ ["close=yes", false],
+ ["close=true", false],
+ ["close=no", false],
+
+ ["minimizable", false],
+ ["minimizable=yes", false],
+ ["minimizable=true", false],
+ ["minimizable=no", false],
+
+ ["personalbar", false],
+ ["personalbar=yes", false],
+ ["personalbar=true", false],
+ ["personalbar=no", false],
+ ],
+ "position": [
+ ["left=500", false],
+ ["screenX=500", false],
+
+ ["top=500", false],
+ ["screenY=500", false],
+
+ ["width=500", false],
+ ["innerWidth=500", false],
+
+ ["outerWidth=500", false],
+
+ ["height=500", false],
+ ["innerHeight=500", false],
+
+ ["outerHeight=500", false],
+ ],
+ "combination": [
+ // The following combination results in non-popup.
+ ["location,toolbar,menubar,resizable,scrollbars,status", true],
+
+ // Either location or toolbar is required for non-popup.
+ ["location,menubar,resizable,scrollbars,status", true],
+ ["toolbar,menubar,resizable,scrollbars,status", true],
+
+ ["resizable,scrollbars,status", false],
+ ["location=no,menubar=no,resizable,scrollbars,status", false],
+
+ // menubar is required for non-popup.
+ ["location,toolbar,resizable,scrollbars,status", false],
+
+ // resizable is required for non-popup, but defaults to true
+ ["location,toolbar,menubar,scrollbars,status", true],
+ ["location,toolbar,menubar,resizable=no,scrollbars,status", false],
+
+ // scrollbars is required for non-popup.
+ ["location,toolbar,menubar,resizable,status", false],
+
+ // status is required for non-popup.
+ ["location,toolbar,menubar,resizable,scrollbars", false],
+
+ // The explicit popup feature has priority than others.
+ ["popup=1,location,toolbar,menubar,resizable,scrollbars,status", false],
+ ["popup=yes,location,toolbar,menubar,resizable,scrollbars,status", false],
+ ["popup=true,location,toolbar,menubar,resizable,scrollbars,status", false],
+ ["popup=0,location,toolbar,menubar,resizable,scrollbars", true],
+ ],
+};
+
+tests[target].forEach(([features, visible]) => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.locationbar, visible, `window.locationbar.visible`);
+ assert_equals(data.menubar, visible, `window.menubar.visible`);
+ assert_equals(data.personalbar, visible, `window.personalbar.visible`);
+ assert_equals(data.scrollbars, visible, `window.scrollbars.visible`);
+ assert_equals(data.statusbar, visible, `window.statusbar.visible`);
+ assert_equals(data.toolbar, visible, `window.toolbar.visible`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL), '', features);
+ }, `${format_value(features)} should set BarProp visibility to ${visible}`);
+});
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-innerwidth-innerheight.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-innerwidth-innerheight.html
new file mode 100644
index 0000000000..019ee9d730
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-innerwidth-innerheight.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: negative values for legacy `innerwidth`, `innerheight`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var windowURL = 'resources/message-opener.html';
+var featuresPrefix = `top=0,left=0,`;
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-integers
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the features tested here were set to invalid
+ // values in later tests.
+ // In cases where the value for `innerwidth` or `innerheight` is
+ // is less than the browser's minimum allowed value for that dimension,
+ // but NOT 0, the value affected will become the browser's minimum allowed value.
+
+ // This should result in a minimally-sized window for later comparison
+ var featureString = `${featuresPrefix}innerwidth=1,innerheight=1`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+
+ // Negative values for `innerwidth` should result in a window with minimum
+ // valid allowed width
+ [ 'innerwidth=-404',
+ 'innerwidth=-404.5',
+ 'innerwidth=-404e1'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}height=405,${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.width, baselineDimensions.width, `"${feature} is negative and should result in a minimally-wide window"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + "&expected_innerWidth=" + baselineDimensions.width, '', featureString);
+ }, `features "${feature}" should NOT set "width=404"`);
+ });
+
+ // Negative values for `innerheight` should result in a window with minimum
+ // valid allowed height
+ [ 'innerheight=-404',
+ 'innerheight=-404.5',
+ 'innerheight=-404e1'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}width=404,${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.height, baselineDimensions.height, `"${feature} is negative and should result in a minimal-height window"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerHeight=' + baselineDimensions.height, '', featureString);
+ }, `features "${feature}" should NOT set "height=404"`);
+ });
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-screenx-screeny.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-screenx-screeny.html
new file mode 100644
index 0000000000..6e316db482
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-screenx-screeny.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: negative values for legacy `screenx`, `screeny`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var featuresPrefix = `width=401,height=404,`;
+var windowURL = 'resources/message-opener.html';
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-integers
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the feature tested here were set to 0
+ // for comparison later.
+ var featureString = `${featuresPrefix}top=0,left=0`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+ // Negative values should be interpreted as 0
+ [ 'screeny=-204',
+ 'screeny=-204.5',
+ 'screeny=-0'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}left=0,${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.top, baselineDimensions.top, `"${feature} is negative and should be set to 0"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenY=' + baselineDimensions.top, '', featureString);
+ }, `features "${feature}" should NOT set "top=204"`);
+ });
+
+ // Negative values should be interpreted as 0
+ [ 'screenx=-204',
+ 'screenx=-204.5',
+ 'screenx=-0'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}top=0,${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.left, baselineDimensions.left, `"${feature} is negative and should be set to 0"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenX=' + baselineDimensions.left, '', featureString);
+ }, `features "${feature}" should NOT set "left=204"`);
+ });
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-top-left.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-top-left.html
new file mode 100644
index 0000000000..316b01a401
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-top-left.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: negative values for `top`, `left`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var featuresPrefix = `width=401,height=404,`;
+var windowURL = 'resources/message-opener.html';
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-integers
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the feature tested here were set to 0
+ // for comparison later.
+ var featureString = `${featuresPrefix}top=0,left=0`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+
+ // Negative values for `top`, `left` should be interpreted as 0
+ [ 'top=-204',
+ 'top=-204.5',
+ 'top=-0'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}left=0,${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.top, baselineDimensions.top, `"${feature} is negative and should be set to 0"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenY=' + baselineDimensions.top, '', featureString);
+ }, `features "${feature}" should NOT set "top=204"`);
+ });
+
+// Negative values for `top`, `left` should be interpreted as 0
+ [ 'left=-204',
+ 'left=-204.5',
+ 'left=-0'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}top=0,${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.left, baselineDimensions.left, `"${feature} is negative and should be set to 0"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenX=' + baselineDimensions.left, '', featureString);
+ }, `features "${feature}" should NOT set "left=204"`);
+ });
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-width-height.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-width-height.html
new file mode 100644
index 0000000000..3cb155620d
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-negative-width-height.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: negative values for `width`, `height`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var featuresPrefix = `top=0,left=0,`;
+var windowURL = 'resources/message-opener.html';
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-integers
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the features tested here were set to invalid
+ // values in later tests.
+ // In cases where the value for `width` or `height` is
+ // is less than the browser's minimum allowed value for that dimension,
+ // but NOT 0, the value affected will become the browser's minimum allowed value.
+
+ // This should result in a minimally-sized window for later comparison
+ var featureString = `${featuresPrefix}width=1,height=1`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+
+ // Negative values for `width` should result in a window with minimum
+ // valid allowed width
+ [ 'width=-404',
+ 'width=-404.5',
+ 'width=-404e1'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}height=405,${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.width, baselineDimensions.width, `"${feature} is negative and should result in a minimally-wide window"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerWidth=' + baselineDimensions.width, '', featureString);
+ }, `features "${feature}" should NOT set "width=404"`);
+ });
+
+ // Negative values for `height` should result in a window with minimum
+ // valid allowed height
+ [ 'height=-404',
+ 'height=-404.5',
+ 'height=-404e1'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}width=404,${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.height, baselineDimensions.height, `"${feature} is negative and should result in a minimal-height window"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerHeight=' + baselineDimensions.height, '', featureString);
+ }, `features "${feature}" should NOT set "height=404"`);
+ });
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-height.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-height.html
new file mode 100644
index 0000000000..d8ee866c50
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-height.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: non-integer values for feature `height`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var featuresPrefix = `top=0,left=0,width=401,`;
+var windowURL = 'resources/message-opener.html';
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-integers
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the feature tested here were set to 0
+ // for comparison later.
+ var featureString = `${featuresPrefix}height=0`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+ // The absence of the sizing feature should have the same behavior
+ // as that feature set to 0
+ [ featuresPrefix,
+ 'top=0,left=0',
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.height, baselineDimensions.height);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerHeight=' + baselineDimensions.height, '', feature);
+ }, `${feature}: absence of feature "height" should be treated same as "height=0"`);
+ });
+
+ // When code point in first position is not an ASCII digit, "+" or "-",
+ // that's an error and the value becomes 0
+ [ 'height=/404',
+ 'height=_404',
+ 'height=L404'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.height, baselineDimensions.height, `"${feature} begins with an invalid character and should be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerHeight=' + baselineDimensions.height, '', featureString);
+ }, `features "${feature}" should NOT set "height=404"`);
+ });
+
+ // Codepoints that are valid ASCII digits should be collected
+ // Non-ASCII digits and subsequent code points are ignored
+ [ 'height=405.5',
+ 'height=405.32',
+ 'height=405LLl',
+ 'height=405^4',
+ 'height=405*3',
+ 'height=405/5',
+ 'height=405 ',
+ 'height=405e1',
+ 'height=405e-1'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.height, 405, `"${featureString} value after first non-digit will be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + "&expected_innerHeight=405", '', featureString);
+ }, `features "${feature}" should set "height=405"`);
+ });
+
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-innerheight.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-innerheight.html
new file mode 100644
index 0000000000..f191d875d8
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-innerheight.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: non-integer values for legacy feature `innerheight`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var featuresPrefix = `top=0,left=0,width=401,`;
+var windowURL = 'resources/message-opener.html';
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-integers
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the feature tested here were set to 0
+ // for comparison later.
+ var featureString = `${featuresPrefix}height=0`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+ // When code point in first position is not an ASCII digit, "+" or "-",
+ // that's an error and the value becomes 0
+ [ 'innerheight=/404',
+ 'innerheight=_404',
+ 'innerheight=L404'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.height, baselineDimensions.height, `"${feature} begins with an invalid character and should be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerHeight=' + baselineDimensions.height, '', featureString);
+ }, `features "${feature}" should NOT set "height=404"`);
+ });
+
+ // Codepoints that are valid ASCII digits should be collected
+ // Non-ASCII digits and subsequent code points are ignored
+ [ 'innerheight=405.5',
+ 'innerheight=405.32',
+ 'innerheight=405LLl',
+ 'innerheight=405^4',
+ 'innerheight=405*3',
+ 'innerheight=405/5',
+ 'innerheight=405 ',
+ 'innerheight=405e1',
+ 'innerheight=405e-1'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.height, 405, `"${featureString} value after first non-digit will be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + "&expected_innerHeight=405", '', featureString);
+ }, `features "${feature}" should set "height=405"`);
+ });
+
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-innerwidth.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-innerwidth.html
new file mode 100644
index 0000000000..d1ddc5e43a
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-innerwidth.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: non-integer values for legacy feature `innerwidth`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var featuresPrefix = `top=0,left=0,height=401,`;
+var windowURL = 'resources/message-opener.html';
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-integers
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the feature tested here were set to 0
+ // for comparison later.
+ var featureString = `${featuresPrefix}width=0`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+ // When code point in first position is not an ASCII digit, "+" or "-",
+ // that's an error and the value becomes 0
+ [ 'innerwidth=/404',
+ 'innerwidth=_404',
+ 'innerwidth=L404'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.width, baselineDimensions.width, `"${feature} begins with an invalid character and should be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerWidth=' + baselineDimensions.width, '', featureString);
+ }, `features "${feature}" should NOT set "width=404"`);
+ });
+
+ // Codepoints that are valid ASCII digits should be collected
+ // Non-ASCII digits and subsequent code points are ignored
+ [ 'innerwidth=405.5',
+ 'innerwidth=405.32',
+ 'innerwidth=405LLl',
+ 'innerwidth=405^4',
+ 'innerwidth=405*3',
+ 'innerwidth=405/5',
+ 'innerwidth=405 ',
+ 'innerwidth=405e1',
+ 'innerwidth=405e-1'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.width, 405, `"${featureString} value after first non-digit will be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerWidth=405', '', featureString);
+ }, `features "${feature}" should set "width=405"`);
+ });
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-left.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-left.html
new file mode 100644
index 0000000000..c771204dc4
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-left.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: non-integer values for feature `left`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+
+var featuresPrefix = `width=401,height=204,top=0,`;
+var windowURL = 'resources/message-opener.html';
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-integers
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the feature tested here were set to 0
+ // for comparison later.
+ var featureString = `${featuresPrefix}left=0`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+ // When code point in first position is not an ASCII digit, "+" or "-",
+ // that's an error and the value becomes 0
+ [ 'left=/104',
+ 'left=_104',
+ 'left=L104'
+ ].forEach(feature => {
+ async_test(t => {
+ var featureString = `${featuresPrefix}${feature}`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.left, baselineDimensions.left, `"${feature} begins with an invalid character and should be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenX=' + baselineDimensions.left, '', featureString);
+ }, `features "${feature}" should NOT set "left=104"`);
+ });
+
+ // Codepoints that are valid ASCII digits should be collected
+ // Non-ASCII digits and subsequent code points are ignored
+ [ 'left=105.5',
+ 'left=105.32',
+ 'left=105LLl',
+ 'left=105^4',
+ 'left=105*3',
+ 'left=105/5',
+ 'left=105 ',
+ 'left=105e1',
+ 'left=105e-1'
+ ].forEach(feature => {
+ async_test(t => {
+ var featureString = `${featuresPrefix}${feature}`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.left, 105, `"${featureString} value after first non-digit will be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenX=105', '', featureString);
+ }, `features "${feature}" should set "left=105"`);
+ });
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-screenx.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-screenx.html
new file mode 100644
index 0000000000..49a3783257
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-screenx.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: non-integer values for legacy feature `screenx`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var featuresPrefix = `width=401,height=204,top=0,`;
+var windowURL = 'resources/message-opener.html';
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-integers
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the feature tested here were set to 0
+ // for comparison later.
+ var featureString = `${featuresPrefix}left=0`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+ // When code point in first position is not an ASCII digit, "+" or "-",
+ // that's an error and the value becomes 0
+ [ 'screenx=/104',
+ 'screenx=_104',
+ 'screenx=L104'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.left, baselineDimensions.left, `"${feature} begins with an invalid character and should be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenX=' + baselineDimensions.left, '', featureString);
+ }, `features "${feature}" should NOT set "screenx=104"`);
+ });
+
+ // Codepoints that are valid ASCII digits should be collected
+ // Non-ASCII digits and subsequent code points are ignored
+ [ 'screenx=105.5',
+ 'screenx=105.32',
+ 'screenx=105LLl',
+ 'screenx=105^4',
+ 'screenx=105*3',
+ 'screenx=105/5',
+ 'screenx=105 ',
+ 'screenx=105e1',
+ 'screenx=105e-1'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.left, 105, `"${featureString} value after first non-digit will be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenX=105', '', featureString);
+ }, `features "${feature}" should set "screenx=105"`);
+ });
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-screeny.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-screeny.html
new file mode 100644
index 0000000000..5183405445
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-screeny.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: non-integer values for legacy feature `screeny`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var featuresPrefix = `height=401,width=402,left=0,`;
+var windowURL = 'resources/message-opener.html';
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-integers
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the feature tested here were set to 0
+ // for comparison later.
+ var featureString = `${featuresPrefix}top=0`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+ // When code point in first position is not an ASCII digit, "+" or "-",
+ // that's an error and the value becomes 0
+ [ 'screeny=/404',
+ 'screeny=_404',
+ 'screeny=L404'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.top, baselineDimensions.top, `"${feature} begins with an invalid character and should be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenY=' + baselineDimensions.top, '', featureString);
+ }, `features "${feature}" should NOT set "screeny=404"`);
+ });
+
+ // Codepoints that are valid ASCII digits should be collected
+ // Non-ASCII digits and subsequent code points are ignored
+ [ 'screeny=405.5',
+ 'screeny=405.32',
+ 'screeny=405LLl',
+ 'screeny=405^4',
+ 'screeny=405*3',
+ 'screeny=405/5',
+ 'screeny=405 ',
+ 'screeny=405e1',
+ 'screeny=405e-1'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.top, 405, `"${featureString} value after first non-digit will be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenY=405', '', featureString);
+ }, `features "${feature}" should set "screeny=405"`);
+ });
+
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-top.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-top.html
new file mode 100644
index 0000000000..a7926e748b
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-top.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: non-integer values for feature `top`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var windowURL = 'resources/message-opener.html';
+var featuresPrefix = `width=401,height=204,left=0,`;
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the feature tested here were set to 0
+ // for comparison later.
+ var featureString = `${featuresPrefix}top=0`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+ // When code point in first position is not an ASCII digit, "+" or "-",
+ // that's an error and the value becomes 0
+ [ 'top=/104',
+ 'top=_104',
+ 'top=L104'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.top, baselineDimensions.top, `"${feature} begins with an invalid character and should be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenY=' + baselineDimensions.top, '', featureString);
+ }, `features "${feature}" should NOT set "top=104"`);
+ });
+
+ // Codepoints that are valid ASCII digits should be collected
+ // Non-ASCII digits and subsequent code points are ignored
+ [ 'top=105.5',
+ 'top=105.32',
+ 'top=105LLl',
+ 'top=105^4',
+ 'top=105*3',
+ 'top=105/5',
+ 'top=105 ',
+ 'top=105e1',
+ 'top=105e-1'
+ ].forEach(feature => {
+ async_test(t => {
+ var featureString = `${featuresPrefix}${feature}`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.top, 105, `"${feature} value after first non-digit will be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenY=105', '', featureString);
+ }, `features "${feature}" should set "top=105"`);
+ });
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-width.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-width.html
new file mode 100644
index 0000000000..6878063ed7
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-non-integer-width.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: non-integer values for feature `width`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var featuresPrefix = `top=0,left=0,height=401,`;
+var windowURL = 'resources/message-opener.html';
+
+// https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-integers
+
+setup (() => {
+ // Before running tests, open a window using features that mimic
+ // what would happen if the feature tested here were set to 0
+ // for comparison later.
+ var featureString = `${featuresPrefix}width=0`;
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage((data, e) => {
+ e.source.close();
+ runWindowTests(data);
+ });
+ var win = window.open(prefixedMessage.url(windowURL), '', featureString);
+});
+
+function runWindowTests (baselineDimensions) {
+
+ // The absence of the sizing feature should have the same behavior
+ // as that feature set to 0
+ [ featuresPrefix,
+ 'top=0,left=0',
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.width, baselineDimensions.width);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerWidth=' + baselineDimensions.width, '', feature);
+ }, `${feature}: absence of feature "width" should be treated same as "width=0"`);
+ });
+
+ // When code point in first position is not an ASCII digit, "+" or "-",
+ // that's an error and the value becomes 0
+ [ 'width=/404',
+ 'width=_404',
+ 'width=L404'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.width, baselineDimensions.width, `"${feature} begins with an invalid character and should be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerWidth=' + baselineDimensions.width, '', featureString);
+ }, `features "${feature}" should NOT set "width=404"`);
+ });
+
+ // Codepoints that are valid ASCII digits should be collected
+ // Non-ASCII digits and subsequent code points are ignored
+ [ 'width=405.5',
+ 'width=405.32',
+ 'width=405LLl',
+ 'width=405^4',
+ 'width=405*3',
+ 'width=405/5',
+ 'width=405 ',
+ 'width=405e1',
+ 'width=405e-1'
+ ].forEach(feature => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ var featureString = `${featuresPrefix}${feature}`;
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.width, 405, `"${featureString} value after first non-digit will be ignored"`);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + "&expected_innerWidth=405", '', featureString);
+ }, `features "${feature}" should set "width=405"`);
+ });
+}
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-innerheight-innerwidth.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-innerheight-innerwidth.html
new file mode 100644
index 0000000000..cf3ad25514
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-innerheight-innerwidth.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: tokenization -- legacy size features `innerheight`, `innerwidth`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var windowURL = 'resources/message-opener.html';
+var width = 'width=401,';
+var height = 'height=402,';
+
+[ 'innerwidth=401',
+ ' innerwidth = 401',
+ 'innerwidth==401',
+ '\ninnerwidth= 401',
+ ',innerwidth=401,,',
+ 'INNERWIDTH=401',
+ 'innerWidth=401'
+].forEach((features, idx, arr) => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.width, 401);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerWidth=401', '', height + features);
+ }, `${format_value(features)} should set width of opened window`);
+});
+
+[ 'innerheight=402',
+ ' innerheight = 402',
+ 'innerheight==402',
+ '\ninnerheight= 402',
+ ',innerheight=402,,',
+ 'INNERHEIGHT=402',
+ 'innerHeight=402'
+].forEach((features, idx, arr) => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.height, 402);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerHeight=402', '', width + features);
+ }, `${format_value(features)} should set height of opened window`);
+});
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-noopener.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-noopener.html
new file mode 100644
index 0000000000..c955e67789
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-noopener.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: tokenization -- `noopener`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/tokenization-noopener-noreferrer.js"></script>
+<script>
+ booleanTests("noopener");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-noreferrer.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-noreferrer.html
new file mode 100644
index 0000000000..4807f634fd
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-noreferrer.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: tokenization -- `noreferrer`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/tokenization-noopener-noreferrer.js"></script>
+<script>
+ booleanTests("noreferrer");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-screenx-screeny.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-screenx-screeny.html
new file mode 100644
index 0000000000..5a53fefc40
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-screenx-screeny.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: tokenization -- legacy position features `screenx`, `screeny`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var windowURL = 'resources/message-opener.html';
+var width = 'width=401,';
+var height = 'height=402,';
+
+[ 'screenx=141',
+ ' screenx = 141',
+ 'screenx==141',
+ '\nscreenx= 141',
+ ',screenx=141,,',
+ 'SCREENX=141',
+ 'screenX=141'
+].forEach((features, idx, arr) => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.left, 141);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenX=141', '', width + height + features);
+ }, `${format_value(features)} should set left position of opened window`);
+});
+
+[ 'screeny=142',
+ ' screeny = 142',
+ 'screeny==142',
+ '\nscreeny= 142',
+ ',screeny=142,,',
+ 'SCREENY=142',
+ 'screenY=142'
+].forEach((features, idx, arr) => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.top, 142);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenY=142', '', width + height + features);
+ }, `${format_value(features)} should set top position of opened window`);
+});
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-top-left.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-top-left.html
new file mode 100644
index 0000000000..842cbcf820
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-top-left.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: tokenization -- position features `top` and `left`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var windowURL = 'resources/message-opener.html';
+var width = 'width=401,';
+var height = 'height=402,';
+
+[ 'left=141',
+ ' left = 141',
+ 'left==141',
+ '\nleft= 141',
+ ',left=141,,',
+ 'LEFT=141'
+].forEach((features, idx, arr) => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.left, 141);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenX=141', '', width + height + features);
+ }, `"${features}" should set left position of opened window`);
+});
+
+[ 'top=142',
+ ' top = 142',
+ 'top==142',
+ '\ttop= 142',
+ ',top=142,,',
+ 'TOP=142'
+].forEach((features, idx, arr) => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.top, 142);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenY=142', '', width + height + features);
+ }, `${format_value(features)} should set top position of opened window`);
+});
+
+[ 'top=152,left=152',
+ 'top=152,,left=152,',
+ 'top=152==left=152',
+ ',,top= 152, left=152'
+].forEach((features, idx, arr) => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.top, 152);
+ assert_equals(data.left, 152);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_screenX=152&expected_screenY=152', '', width + height + features);
+ }, `${format_value(features)} should set top and left position of opened window`);
+});
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-width-height.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-width-height.html
new file mode 100644
index 0000000000..ff61199179
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/open-features-tokenization-width-height.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML: window.open `features`: tokenization -- size features `width` and `height`</title>
+<meta name=timeout content=long>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#apis-for-creating-and-navigating-browsing-contexts-by-name">
+
+<!-- user agents are not required to support open features other than `noopener`
+ and on some platforms position and size features don't make sense -->
+<meta name="flags" content="may" />
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var windowURL = 'resources/message-opener.html';
+var width = 'width=401,';
+var height = 'height=402,';
+
+[ 'width=401',
+ ' width = 401',
+ 'width==401',
+ '\nwidth= 401',
+ ',width=401,,',
+ 'WIDTH=401'
+].forEach((features, idx, arr) => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.width, 401);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerWidth=401', '', height + features);
+ }, `${format_value(features)} should set width of opened window`);
+});
+
+[ 'height=402',
+ ' height = 402',
+ 'height==402',
+ '\nheight= 402',
+ ',height=402,,',
+ 'HEIGHT=402'
+].forEach((features, idx, arr) => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.height, 402);
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerHeight=402', '', width + features);
+ }, `${format_value(features)} should set height of opened window`);
+});
+
+[ 'height=402,width=401',
+ ' height = 402 , width = 401 ,',
+ 'height==402 width = 401',
+ '\nheight= 402,,width=\n401',
+ ',height=402,,width==401',
+ 'HEIGHT=402, WIDTH=401'
+].forEach((features, idx, arr) => {
+ async_test(t => {
+ var prefixedMessage = new PrefixedMessageTest();
+ prefixedMessage.onMessage(t.step_func_done((data, e) => {
+ e.source.close();
+ assert_equals(data.height, 402);
+ assert_equals(data.width, 401)
+ }));
+ var win = window.open(prefixedMessage.url(windowURL) + '&expected_innerHeight=402&expected_innerWidth=401', '', features);
+ }, `${format_value(features)} should set height and width of opened window`);
+});
+
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/close-self.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/close-self.html
new file mode 100644
index 0000000000..0c0cf9fc49
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/close-self.html
@@ -0,0 +1,3 @@
+<script>
+ window.close();
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/is-popup-barprop.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/is-popup-barprop.html
new file mode 100644
index 0000000000..5636e29878
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/is-popup-barprop.html
@@ -0,0 +1,15 @@
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var prefixedMessage = new PrefixedMessageResource();
+function sendBarProps() {
+ prefixedMessage.postToOpener({
+ locationbar: window.locationbar.visible,
+ menubar: window.menubar.visible,
+ personalbar: window.personalbar.visible,
+ scrollbars: window.scrollbars.visible,
+ statusbar: window.statusbar.visible,
+ toolbar: window.toolbar.visible,
+ });
+}
+window.addEventListener('load', sendBarProps);
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/message-opener.html b/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/message-opener.html
new file mode 100644
index 0000000000..39ad139769
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/message-opener.html
@@ -0,0 +1,52 @@
+<script src="/common/PrefixedPostMessage.js"></script>
+<script>
+var prefixedMessage = new PrefixedMessageResource();
+var max = 150, attempts = 0;
+
+const urlParams = new URLSearchParams(location.search);
+const expected_innerWidth = urlParams.get('expected_innerWidth');
+const expected_innerHeight = urlParams.get('expected_innerHeight');
+const expected_screenX = urlParams.get('expected_screenX');
+const expected_screenY = urlParams.get('expected_screenY');
+let should_wait_until_settled = expected_innerWidth === null && expected_innerHeight === null && expected_screenX === null && expected_screenY === null;
+
+function sendCoordinates() {
+ // Certain windowing systems position windows asynchronously.
+ // As a result, the window may not be positioned yet when the
+ // load event fires. To accommodate this, allow waiting up to
+ // 15 seconds for positioning to take place.
+ if ((!window.screenX && expected_screenX) &&
+ (!window.screenY && expected_screenY) && ++attempts < max) {
+ setTimeout(sendCoordinates, 100);
+ return;
+ }
+ if (expected_innerWidth && window.innerWidth != expected_innerWidth && ++attempts < max) {
+ setTimeout(sendCoordinates, 10);
+ return;
+ }
+ if (expected_innerHeight && window.innerHeight != expected_innerHeight && ++attempts < max) {
+ setTimeout(sendCoordinates, 10);
+ return;
+ }
+ if (expected_screenX && window.screenX != expected_screenX && ++attempts < max) {
+ setTimeout(sendCoordinates, 10);
+ return;
+ }
+ if (expected_screenY && window.screenY != expected_screenY && ++attempts < max) {
+ setTimeout(sendCoordinates, 10);
+ return;
+ }
+ if (should_wait_until_settled) {
+ should_wait_until_settled = false;
+ setTimeout(sendCoordinates, 300);
+ return;
+ }
+ prefixedMessage.postToOpener({
+ left: window.screenX,
+ top: window.screenY,
+ width: window.innerWidth,
+ height: window.innerHeight
+ });
+}
+window.addEventListener('load', sendCoordinates);
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/tokenization-noopener-noreferrer.js b/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/tokenization-noopener-noreferrer.js
new file mode 100644
index 0000000000..a9d42e26de
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/open-close/resources/tokenization-noopener-noreferrer.js
@@ -0,0 +1,152 @@
+function booleanTests(feature) {
+ const windowURL = 'resources/close-self.html';
+ // Tests for how windows features are tokenized into 'name', 'value'
+ // window features separators are ASCII whitespace, '=' and ','
+
+ const featureUpper = feature.toUpperCase(),
+ featureSplitBegin = feature.slice(0, 2),
+ featureSplitEnd = feature.slice(2),
+ featureMixedCase = featureSplitBegin.toUpperCase() + featureSplitEnd;
+ featureMixedCase2 = featureSplitBegin + featureSplitEnd.toUpperCase();
+
+ test (t => {
+ // Tokenizing `name`: initial window features separators are ignored
+ // Each of these variants should tokenize to (`${feature}`, '')
+ [
+ ` ${feature}`,
+ `=${feature}`,
+ `,,${feature}`,
+ `,=, ${feature}`,
+ `\n=${feature}=`,
+ `\t${feature}`,
+ `\r,,,=${feature}`,
+ `\u000C${feature}`
+ ].forEach(variant => {
+ const win = window.open(windowURL, "", variant);
+ assert_equals(win, null, `"${variant}" should activate feature "${feature}"`);
+ });
+ }, `Tokenization of "${feature}" should skip window features separators before feature`);
+
+ test (t => {
+ // Tokenizing `name`: lowercase conversion
+ // Each of these variants should tokenize as feature (`${feature}`, '')
+ // except where indicated
+ // Note also that `value` is lowercased during tokenization
+ [
+ `${featureUpper}`,
+ `${featureMixedCase}`,
+ ` ${featureMixedCase2}`,
+ `=${featureUpper}`,
+ `${featureUpper}=1`,
+ `${featureUpper}=1`,
+ `${featureUpper}=yes`,
+ `${feature}=YES`,
+ ].forEach(variant => {
+ const win = window.open(windowURL, '', variant);
+ assert_equals(win, null, `"${variant}" should activate feature "${feature}"`);
+ });
+ }, `Feature "${feature}" should be converted to ASCII lowercase`);
+
+ test (t => {
+ // After `name` has been collected, ignore any window features separators until '='
+ // except ',' OR a non-window-features-separator — break in those cases
+ // i.e. ignore whitespace until '=' unless a ',' is encountered first
+ // Each of these variants should tokenize as feature ('noopener', '')
+ [
+ `${feature}`,
+ ` ${feature}\r`,
+ `${feature}\n =`,
+ `${feature},`,
+ `${feature} =,`,
+ `, ${feature} =`,
+ `${feature},=`,
+ `${feature} foo`,
+ `foo ${feature}=1`,
+ `foo=\u000Cbar\u000C${feature}`
+ ].forEach(variant => {
+ const win = window.open(windowURL, '', variant);
+ assert_equals(win, null, `"${variant}" should activate feature "${feature}"`);
+ });
+ }, `After "${feature}", tokenization should skip window features separators that are not "=" or ","`);
+
+ test (t => {
+ // After initial '=', tokenizing should ignore all separators except ','
+ // before collecting `value`
+ // Each of these variants should tokenize as feature ('noopener', '')
+ // Except where indicated
+ [
+ `${feature}= yes`,
+ `${feature}==,`,
+ `${feature}=\n ,`,
+ `${feature} = \t ,`,
+ `${feature}\n=\r 1,`,
+ `${feature}=,yes`,
+ `${feature}= yes=,`,
+ `${feature} = \u000Cyes`
+ ].forEach(variant => {
+ const win = window.open(windowURL, '', variant);
+ assert_equals(win, null, `"${variant}" should activate feature "${feature}"`);
+ });
+ }, `Tokenizing "${feature}" should ignore window feature separators except "," after initial "=" and before value`);
+
+ test (t => {
+ // Tokenizing `value` should collect any non-separator code points until first separator
+ [
+ `${feature}=1`,
+ `${feature}=yes`,
+ `${feature} = yes ,`,
+ `${feature}=\nyes ,`,
+ `${feature}=yes yes`,
+ `${feature}=yes\ts`,
+ `${feature}==`,
+ `${feature}=1\n,`,
+ `==${feature}===`,
+ `${feature}==\u000C`
+ ].forEach(variant => {
+ const win = window.open(windowURL, '', variant);
+ assert_equals(win, null, `"${variant}" should set "${feature}"`);
+ });
+ }, `Tokenizing "${feature}" should read characters until first window feature separator as \`value\``);
+
+ test (t => {
+ [
+ `${feature}=1`,
+ `${feature}=2`,
+ `${feature}=12345`,
+ `${feature}=1.5`,
+ `${feature}=-1`,
+ ].forEach(variant => {
+ const win = window.open(windowURL, '', variant);
+ assert_equals(win, null, `"${variant}" should activate feature "${feature}"`);
+ });
+ }, 'Integer values other than 0 should activate the feature');
+
+ test (t => {
+ [
+ `${feature}=0`,
+ `${feature}=0.5`,
+ `${feature}=error`,
+ ].forEach(variant => {
+ const win = window.open(windowURL, '', variant);
+ assert_not_equals(win, null, `"${variant}" should NOT activate feature "${feature}"`);
+ });
+ }, `Integer value of 0 should not activate "${feature}"`);
+
+ test (t => {
+ [
+ `-${feature}`,
+ `${featureUpper}RRR`,
+ `${featureMixedCase}R`,
+ `${featureSplitBegin}_${featureSplitEnd}`,
+ ` ${featureSplitBegin} ${featureSplitEnd}`,
+ `${featureSplitBegin}\n${featureSplitEnd}`,
+ `${featureSplitBegin},${featureSplitEnd}`,
+ `\0${feature}`,
+ `${feature}\u0000=yes`,
+ `foo=\u000C${feature}`
+ ].forEach(variant => {
+ const win = window.open(windowURL, '', variant);
+ assert_not_equals(win, null, `"${variant}" should NOT activate feature "${feature}"`);
+ });
+ }, `Invalid feature names should not tokenize as "${feature}"`);
+}
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/proxy-getOwnPropertyDescriptor.html b/testing/web-platform/tests/html/browsers/the-window-object/proxy-getOwnPropertyDescriptor.html
new file mode 100644
index 0000000000..4ea9504870
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/proxy-getOwnPropertyDescriptor.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>getOwnPropertyDescriptor() is correct for Proxy with host object target</title>
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+ <link rel="help" href="https://webidl.spec.whatwg.org/#Unforgeable">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+'use strict';
+
+const assert_accessor_descriptor_equals = (actual, expected) => {
+ assert_equals(actual.get, expected.get, 'get');
+ assert_equals(actual.set, expected.set, 'set');
+ assert_equals(actual.enumerable, expected.enumerable, 'enumerable');
+ assert_equals(actual.configurable, expected.configurable, 'configurable');
+};
+
+const assert_data_descriptor_equals = (actual, expected) => {
+ assert_equals(actual.value, expected.value, 'value');
+ assert_equals(actual.writable, expected.writable, 'writable');
+ assert_equals(actual.enumerable, expected.enumerable, 'enumerable');
+ assert_equals(actual.configurable, expected.configurable, 'configurable');
+};
+
+test(() => {
+ const windowProxy = new Proxy(window, {});
+ name = 'old_name';
+ const descriptor = Object.getOwnPropertyDescriptor(windowProxy, 'name');
+
+ assert_equals(descriptor.get.call(window), 'old_name');
+ descriptor.set.call(window, 'new_name');
+ assert_equals(name, 'new_name');
+ assert_true(descriptor.enumerable);
+ assert_true(descriptor.configurable);
+}, 'Window target, no trap, "name" attribute');
+
+test(() => {
+ let trapCalls = 0;
+ const windowProxy = new Proxy(window, {
+ getOwnPropertyDescriptor(...args) {
+ trapCalls++;
+ return Reflect.getOwnPropertyDescriptor(...args);
+ },
+ });
+
+ assert_accessor_descriptor_equals(
+ Object.getOwnPropertyDescriptor(windowProxy, 'document'),
+ Object.getOwnPropertyDescriptor(window, 'document')
+ );
+ assert_equals(trapCalls, 1);
+}, 'Window target, forwarding trap, [LegacyUnforgeable] "document" attribute');
+
+test(() => {
+ const trapResult = {get() {}, set(_val) {}, enumerable: false, configurable: true};
+ const windowProxy = new Proxy(new Proxy(window, {}), {
+ getOwnPropertyDescriptor: () => trapResult,
+ });
+
+ assert_accessor_descriptor_equals(
+ Object.getOwnPropertyDescriptor(windowProxy, 'onclick'),
+ trapResult
+ );
+}, 'Window proxy target, custom trap, "onclick" event handler attribute');
+
+test(() => {
+ let trapCalls = 0;
+ const documentProxy = new Proxy(document, {
+ getOwnPropertyDescriptor(...args) {
+ trapCalls++;
+ return Reflect.getOwnPropertyDescriptor(...args);
+ },
+ });
+
+ assert_accessor_descriptor_equals(
+ Object.getOwnPropertyDescriptor(documentProxy, 'location'),
+ Object.getOwnPropertyDescriptor(document, 'location')
+ );
+ assert_equals(trapCalls, 1);
+}, 'Document target, forwarding trap, [LegacyUnforgeable] "location" attribute');
+
+test(() => {
+ const trapResult = {value: 4, writable: false, enumerable: true, configurable: true};
+ const documentProxy = new Proxy(new Proxy(document, {}), {
+ getOwnPropertyDescriptor: () => trapResult,
+ });
+
+ assert_data_descriptor_equals(
+ Object.getOwnPropertyDescriptor(documentProxy, 'foo'),
+ trapResult
+ );
+}, 'Document proxy target, custom trap, non-existent value attribute');
+
+test(() => {
+ const locationProxy = new Proxy(location, {});
+ location.hash = '#old';
+ const descriptor = Object.getOwnPropertyDescriptor(locationProxy, 'hash');
+
+ assert_equals(descriptor.get.call(location), '#old');
+ descriptor.set.call(location, '#new');
+ assert_equals(location.hash, '#new');
+ assert_true(descriptor.enumerable);
+ assert_false(descriptor.configurable);
+}, 'Location target, no trap, [LegacyUnforgeable] "hash" attribute');
+
+test(() => {
+ let trapCalls = 0;
+ const locationProxy = new Proxy(new Proxy(location, {}), {
+ getOwnPropertyDescriptor(...args) {
+ trapCalls++;
+ return Reflect.getOwnPropertyDescriptor(...args);
+ },
+ });
+
+ assert_data_descriptor_equals(
+ Object.getOwnPropertyDescriptor(locationProxy, 'reload'),
+ Object.getOwnPropertyDescriptor(location, 'reload')
+ );
+ assert_equals(trapCalls, 1);
+}, 'Location proxy target, forwarding trap, [LegacyUnforgeable] "reload" method');
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/security-window/window-security.https.html b/testing/web-platform/tests/html/browsers/the-window-object/security-window/window-security.https.html
new file mode 100644
index 0000000000..68af5bd90b
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/security-window/window-security.https.html
@@ -0,0 +1,200 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: Window Security</title>
+<link rel="author" title="Intel" href="http://www.intel.com/" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/browsers.html#the-window-object" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/timers.html#timers" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/webappapis.html#atob" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowsessionstorage" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowlocalstorage" />
+<link rel="help" href="https://html.spec.whatwg.org/multipage/multipage/browsers.html#window" />
+<link rel="help" href="http://dev.w3.org/csswg/cssom/#extensions-to-the-window-interface" />
+<link rel="help" href="http://dev.w3.org/csswg/cssom-view/#extensions-to-the-window-interface" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test("Window Security testing");
+
+function fr_load() {
+ fr = document.getElementById("fr");
+
+ t.step(function () {
+ //SecurityError should be thrown
+ [
+ //attributes
+ {name: "devicePixelRatio"},
+ {name: "document"},
+ {name: "external"},
+ {name: "frameElement"},
+ {name: "history"},
+ {name: "innerWidth"},
+ {name: "innerHeight"},
+ {name: "locationbar"},
+ {name: "localStorage"},
+ {name: "menubar"},
+ {name: "name"},
+ {name: "navigator"},
+ {name: "onabort"},
+ {name: "onafterprint"},
+ {name: "onbeforeprint"},
+ {name: "onbeforeunload"},
+ {name: "onblur"},
+ {name: "oncancel"},
+ {name: "oncanplay"},
+ {name: "oncanplaythrough"},
+ {name: "onchange"},
+ {name: "onclick"},
+ {name: "onclose"},
+ {name: "oncontextmenu"},
+ {name: "oncuechange"},
+ {name: "ondblclick"},
+ {name: "ondrag"},
+ {name: "ondragend"},
+ {name: "ondragenter"},
+ {name: "ondragleave"},
+ {name: "ondragover"},
+ {name: "ondragstart"},
+ {name: "ondrop"},
+ {name: "ondurationchange"},
+ {name: "onemptied"},
+ {name: "onended"},
+ {name: "onerror"},
+ {name: "onfocus"},
+ {name: "onhashchange"},
+ {name: "oninput"},
+ {name: "oninvalid"},
+ {name: "onkeydown"},
+ {name: "onkeypress"},
+ {name: "onkeyup"},
+ {name: "onload"},
+ {name: "onloadeddata"},
+ {name: "onloadedmetadata"},
+ {name: "onloadstart"},
+ {name: "onmessage"},
+ {name: "onmousedown"},
+ {name: "onmousemove"},
+ {name: "onmouseout"},
+ {name: "onmouseover"},
+ {name: "onmouseup"},
+ {name: "onmousewheel"},
+ {name: "onoffline"},
+ {name: "ononline"},
+ {name: "onpause"},
+ {name: "onplay"},
+ {name: "onplaying"},
+ {name: "onpagehide"},
+ {name: "onpageshow"},
+ {name: "onpopstate"},
+ {name: "onprogress"},
+ {name: "onratechange"},
+ {name: "onreset"},
+ {name: "onresize"},
+ {name: "onscroll"},
+ {name: "onseeked"},
+ {name: "onseeking"},
+ {name: "onselect"},
+ {name: "onstalled"},
+ {name: "onstorage"},
+ {name: "onsubmit"},
+ {name: "onsuspend"},
+ {name: "ontimeupdate"},
+ {name: "onunload"},
+ {name: "onvolumechange"},
+ {name: "onwaiting"},
+ {name: "pageXOffset"},
+ {name: "pageYOffset"},
+ {name: "personalbar"},
+ {name: "screen"},
+ {name: "scrollbars"},
+ {name: "statusbar"},
+ {name: "status"},
+ {name: "screenX"},
+ {name: "screenY"},
+ {name: "sessionStorage"},
+ {name: "toolbar"},
+ //methods
+ {name: "alert", isMethod: true},
+ {name: "clearInterval", isMethod: true, args:[1]},
+ {name: "clearTimeout", isMethod: true, args:[function () {}, 1]},
+ {name: "confirm", isMethod: true},
+ {name: "getComputedStyle", isMethod: true, args:[document.body, null]},
+ {name: "getSelection", isMethod: true},
+ {name: "matchMedia", isMethod: true, args:["(min-width:50px)"]},
+ {name: "moveBy", isMethod: true, args:[10, 10]},
+ {name: "moveTo", isMethod: true, args:[10, 10]},
+ {name: "open", isMethod: true},
+ {name: "print", isMethod: true},
+ {name: "prompt", isMethod: true},
+ {name: "resizeTo", isMethod: true, args:[10, 10]},
+ {name: "resizeBy", isMethod: true, args:[10, 10]},
+ {name: "scroll", isMethod: true, args:[10, 10]},
+ {name: "scrollTo", isMethod: true, args:[10, 10]},
+ {name: "scrollBy", isMethod: true, args:[10, 10]},
+ {name: "setInterval", isMethod: true, args:[function () {}, 1]},
+ {name: "setTimeout", isMethod: true, args:[function () {}, 1]},
+ {name: "stop", isMethod: true},
+ ].forEach(function (item) {
+ test(function () {
+ assert_true(item.name in window, "window." + item.name + " should exist.");
+ assert_throws_dom("SecurityError", function () {
+ if (item.isMethod)
+ if (item.args)
+ fr.contentWindow[item.name](item.args[0], item.args[1]);
+ else
+ fr.contentWindow[item.name]();
+ else
+ fr.contentWindow[item.name];
+ }, "A SecurityError exception should be thrown.");
+ }, "A SecurityError exception must be thrown when window." + item.name + " is accessed from a different origin.");
+ });
+
+ //SecurityError should not be thrown
+ [
+ //attributes
+ {name: "closed"},
+ {name: "frames"},
+ {name: "length"},
+ {name: "location"},
+ {name: "opener"},
+ {name: "parent"},
+ {name: "self"},
+ {name: "top"},
+ {name: "window"},
+ //methods
+ {name: "blur", isMethod: true},
+ {name: "close", isMethod: true},
+ {name: "focus", isMethod: true},
+ {name: "postMessage", isMethod: true, args: [{msg: 'foo'}, "*"]}
+ ].forEach(function (item) {
+ test(function () {
+ assert_true(item.name in window, "window." + item.name + " should exist.");
+ try {
+ if (item.isMethod)
+ if (item.args)
+ fr.contentWindow[item.name](item.args[0], item.args[1]);
+ else
+ fr.contentWindow[item.name]();
+ else
+ fr.contentWindow[item.name];
+ } catch (e) {
+ assert_unreached("An unexpected exception was thrown.");
+ }
+ }, "A SecurityError exception should not be thrown when window." + item.name + " is accessed from a different origin.");
+ });
+ });
+ t.done();
+}
+
+</script>
+<script>
+onload = function() {
+ var frame = document.createElement('iframe');
+ frame.id = "fr";
+ frame.setAttribute("style", "display:none");
+ frame.setAttribute('src', get_host_info().HTTPS_REMOTE_ORIGIN + "/");
+ frame.setAttribute("onload", "fr_load()");
+ document.body.appendChild(frame);
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/self-et-al.window.js b/testing/web-platform/tests/html/browsers/the-window-object/self-et-al.window.js
new file mode 100644
index 0000000000..1b0fa1211a
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/self-et-al.window.js
@@ -0,0 +1,43 @@
+function delayed_assert_done(t, w, windowProxySelfReference) {
+ // Let's make sure nobody is being sneaky
+ t.step_timeout(() => {
+ t.step_timeout(() => {
+ assert_equals(w[windowProxySelfReference], w, `${windowProxySelfReference} got cleared after some time`);
+ t.done();
+ }, 0);
+ }, 0);
+}
+
+[
+ "frames",
+ "globalThis",
+ "self",
+ "window"
+].forEach(windowProxySelfReference => {
+ async_test(t => {
+ const frame = document.body.appendChild(document.createElement("iframe")),
+ otherW = frame.contentWindow;
+ assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} is broken`);
+ frame.remove();
+ assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} got cleared after browsing context removal`);
+ assert_true(otherW.closed);
+
+ delayed_assert_done(t, otherW, windowProxySelfReference);
+ }, `iframeWindow.${windowProxySelfReference} before and after removal`);
+
+ async_test(t => {
+ const otherW = window.open();
+ assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} is broken`);
+ otherW.onunload = t.step_func(() => {
+ assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} got cleared after browsing context unload`);
+ t.step_timeout(() => {
+ assert_equals(otherW.opener, null); // Ensure browsing context is discarded
+ assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} got cleared after browsing context removal`);
+ delayed_assert_done(t, otherW, windowProxySelfReference);
+ }, 0);
+ });
+ otherW.close();
+ assert_equals(otherW[windowProxySelfReference], otherW, `${windowProxySelfReference} got cleared after browsing context closure`);
+ assert_true(otherW.closed);
+ }, `popupWindow.${windowProxySelfReference} before, after closing, and after discarding`)
+});
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/support/BarProp-target.html b/testing/web-platform/tests/html/browsers/the-window-object/support/BarProp-target.html
new file mode 100644
index 0000000000..9921e7a577
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/support/BarProp-target.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<script>
+ const barProps = ["locationbar", "menubar", "personalbar", "scrollbars", "statusbar", "toolbar"];
+ const barPropsObj = {};
+ const channelName = location.search.substr(1);
+ const channel = new BroadcastChannel(channelName);
+ for (const prop of barProps) {
+ barPropsObj[prop] = window[prop].visible;
+ }
+ channel.postMessage(barPropsObj);
+
+ // Because messages are not delivered synchronously and because closing a
+ // browsing context prompts the eventual clearing of all task sources, this
+ // document should not be closed until the opener document has confirmed
+ // receipt.
+ channel.onmessage = () => { window.close() };
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/support/closed.html b/testing/web-platform/tests/html/browsers/the-window-object/support/closed.html
new file mode 100644
index 0000000000..3b70598e34
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/support/closed.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<!--
+ There's two URL parameters supported here:
+
+ window: The property name of a getter on the global object that returns the relevant WindowProxy
+ object to message.
+ ident: A reasonably unique identifier that will be echoed as the message.
+-->
+<script>
+ const params = new URLSearchParams(location.search);
+ self[params.get("window")].postMessage(params.get("ident"), "*");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/support/noopener-target.html b/testing/web-platform/tests/html/browsers/the-window-object/support/noopener-target.html
new file mode 100644
index 0000000000..41e197a746
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/support/noopener-target.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<script>
+ var channelName = location.search.substr(1);
+ var channel = new BroadcastChannel(channelName);
+ channel.postMessage({ name: window.name,
+ haveOpener: window.opener !== null });
+
+ // Because messages are not delivered synchronously and because closing a
+ // browsing context prompts the eventual clearing of all task sources, this
+ // document should not be closed until the opener document has confirmed
+ // receipt.
+ channel.onmessage = function() {
+ window.close();
+ };
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/support/noreferrer-target.html b/testing/web-platform/tests/html/browsers/the-window-object/support/noreferrer-target.html
new file mode 100644
index 0000000000..c2446c6fe9
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/support/noreferrer-target.html
@@ -0,0 +1,13 @@
+<script>
+ const channelName = location.search.substr(1),
+ channel = new BroadcastChannel(channelName);
+ channel.postMessage({ name: window.name,
+ haveOpener: window.opener !== null,
+ referrer: document.referrer });
+
+ // Because messages are not delivered synchronously and because closing a
+ // browsing context prompts the eventual clearing of all task sources, this
+ // document should not be closed until the opener document has confirmed
+ // receipt.
+ channel.onmessage = () => window.close();
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/support/same-origin-iframe.html b/testing/web-platform/tests/html/browsers/the-window-object/support/same-origin-iframe.html
new file mode 100644
index 0000000000..763d9e466b
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/support/same-origin-iframe.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <script>
+ window.addEventListener('load', () => { window.didLoadFrame = true; });
+ </script>
+ </head>
+</html>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/support/sizing-target.html b/testing/web-platform/tests/html/browsers/the-window-object/support/sizing-target.html
new file mode 100644
index 0000000000..7cd5348a85
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/support/sizing-target.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<script>
+ const windowProps = ["innerWidth", "innerHeight"];
+ const windowPropsObj = {};
+ const channelName = location.search.substr(1);
+ const channel = new BroadcastChannel(channelName);
+ for (const prop of windowProps) {
+ windowPropsObj[prop] = window[prop];
+ }
+ channel.postMessage(windowPropsObj);
+
+ // Because messages are not delivered synchronously and because closing a
+ // browsing context prompts the eventual clearing of all task sources, this
+ // document should not be closed until the opener document has confirmed
+ // receipt.
+ channel.onmessage = () => { window.close() };
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/support/window-open-popup-target.html b/testing/web-platform/tests/html/browsers/the-window-object/support/window-open-popup-target.html
new file mode 100644
index 0000000000..a0588de829
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/support/window-open-popup-target.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<script>
+ var channelName = window.name;
+ var channel = new BroadcastChannel(channelName);
+ const allBarProps = [
+ window.locationbar.visible,
+ window.menubar.visible,
+ window.personalbar.visible,
+ window.scrollbars.visible,
+ window.statusbar.visible,
+ window.toolbar.visible
+ ];
+ const allTrue = allBarProps.every(x=>x);
+ const allFalse = allBarProps.every(x=>!x);
+ channel.postMessage({isPopup: allFalse, mixedState: !allTrue && !allFalse});
+
+ // Because messages are not delivered synchronously and because closing a
+ // browsing context prompts the eventual clearing of all task sources, this
+ // document should not be closed until the opener document has confirmed
+ // receipt.
+ channel.onmessage = function() {
+ window.close();
+ };
+</script> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/support/windowFeature-values-target.html b/testing/web-platform/tests/html/browsers/the-window-object/support/windowFeature-values-target.html
new file mode 100644
index 0000000000..3a78ddf660
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/support/windowFeature-values-target.html
@@ -0,0 +1,24 @@
+<script>
+ const channelName = location.search.substr(1),
+ channel = new BroadcastChannel(channelName);
+
+ const haveOpener = window.opener !== null;
+ const haveReferrer = document.referrer !== null && document.referrer !== "";
+ const allBarProps = [
+ window.locationbar.visible,
+ window.menubar.visible,
+ window.personalbar.visible,
+ window.scrollbars.visible,
+ window.statusbar.visible,
+ window.toolbar.visible
+ ];
+ const isPopup = allBarProps.every(x=>!x);
+
+ channel.postMessage({haveOpener, haveReferrer, isPopup});
+
+ // Because messages are not delivered synchronously and because closing a
+ // browsing context prompts the eventual clearing of all task sources, this
+ // document should not be closed until the opener document has confirmed
+ // receipt.
+ channel.onmessage = () => window.close();
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-aliases.html b/testing/web-platform/tests/html/browsers/the-window-object/window-aliases.html
new file mode 100644
index 0000000000..135be02a30
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-aliases.html
@@ -0,0 +1,28 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Aliases of the window object</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-frames">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-self">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+var global = this;
+
+test(function() {
+ assert_equals(window, global);
+ assert_equals(window.window, global);
+}, "window should be the global object");
+
+test(function() {
+ assert_equals(frames, global);
+ assert_equals(window.frames, global);
+}, "frames should be the global object");
+
+test(function() {
+ assert_equals(self, global);
+ assert_equals(window.self, global);
+}, "self should be the global object");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-access-vs-named-access.html b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-access-vs-named-access.html
new file mode 100644
index 0000000000..23b9124ef7
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-access-vs-named-access.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Interactions between indexed and named access on the Window object</title>
+<link rel="author" title="Delan Azabani" href="dazabani@igalia.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#accessing-other-browsing-contexts">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#named-access-on-the-window-object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=0></div>
+<div id=4></div>
+<iframe name=3></iframe>
+<iframe name=2></iframe>
+<iframe name=1></iframe>
+<script>
+const divs = document.querySelectorAll("div");
+const iframes = document.querySelectorAll("iframe");
+const wp = Object.getPrototypeOf(window);
+test(function() {
+ assert_equals(window[0], iframes[0].contentWindow);
+ assert_equals(window["0"], iframes[0].contentWindow);
+}, "WindowProxy: document-tree child navigable with index 0 (indexed access)");
+test(function() {
+ assert_equals(window[1], iframes[1].contentWindow);
+ assert_equals(window["1"], iframes[1].contentWindow);
+}, "WindowProxy: document-tree child navigable with index 1 (indexed access)");
+test(function() {
+ assert_equals(window[2], iframes[2].contentWindow);
+ assert_equals(window["2"], iframes[2].contentWindow);
+}, "WindowProxy: document-tree child navigable with index 2 (indexed access)");
+test(function() {
+ assert_equals(window[3], iframes[0].contentWindow);
+ assert_equals(window["3"], iframes[0].contentWindow);
+}, "WindowProxy: document-tree child navigable with target name 3 (named access)");
+test(function() {
+ assert_equals(window[4], divs[1]);
+ assert_equals(window["4"], divs[1]);
+}, "WindowProxy: element with id 4 (named access)");
+test(function() {
+ assert_equals(wp[0], divs[0]);
+ assert_equals(wp["0"], divs[0]);
+}, "Window prototype: element with id 0 (named access)");
+test(function() {
+ assert_equals(wp[1], iframes[2].contentWindow);
+ assert_equals(wp["1"], iframes[2].contentWindow);
+}, "Window prototype: document-tree child navigable with target name 1 (named access)");
+test(function() {
+ assert_equals(wp[2], iframes[1].contentWindow);
+ assert_equals(wp["2"], iframes[1].contentWindow);
+}, "Window prototype: document-tree child navigable with target name 2 (named access)");
+test(function() {
+ assert_equals(wp[3], iframes[0].contentWindow);
+ assert_equals(wp["3"], iframes[0].contentWindow);
+}, "Window prototype: document-tree child navigable with target name 3 (named access)");
+test(function() {
+ assert_equals(wp[4], divs[1]);
+ assert_equals(wp["4"], divs[1]);
+}, "Window prototype: element with id 4 (named access)");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-delete-no-cache.html b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-delete-no-cache.html
new file mode 100644
index 0000000000..22262943aa
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-delete-no-cache.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Deletion of WindowProxy's indexed properties is not cached</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/window-object.html#windowproxy-delete">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+const iframe = document.createElement("iframe");
+iframe.srcdoc = "";
+
+test(() => {
+ assert_equals(window.length, 0);
+ for (let i = 0; i < 1e5; i++) {
+ assert_true(delete window[0]);
+ }
+
+ document.body.append(iframe);
+ assert_false(delete window[0]);
+}, "Absence of index '0' is not cached");
+
+test(() => {
+ assert_equals(window.length, 1);
+ for (let i = 0; i < 1e5; i++) {
+ assert_false(delete window[0]);
+ }
+
+ iframe.remove();
+ assert_true(delete window[0]);
+}, "Presence of index '0' is not cached");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-strict.html b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-strict.html
new file mode 100644
index 0000000000..2ee10a7a64
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties-strict.html
@@ -0,0 +1,75 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Indexed properties of the window object (strict mode)</title>
+<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-window-item">
+<link rel="help" href="https://webidl.spec.whatwg.org/#getownproperty">
+<link rel="help" href="https://webidl.spec.whatwg.org/#defineownproperty">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe></iframe>
+<script>
+test(function() {
+ "use strict";
+ assert_false("-1" in window, "-1 not in window");
+ assert_equals(window[-1], undefined);
+ window[-1] = "foo";
+ assert_equals(window[-1], "foo");
+});
+test(function() {
+ "use strict";
+ assert_throws_js(TypeError, function() {
+ window[0] = "foo";
+ });
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 0, { value: "bar" }))
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 0, { get() { return "baz" } }))
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 0, { set(v) { return "qux" } }))
+ assert_equals(window[0],
+ document.getElementsByTagName("iframe")[0].contentWindow);
+ assert_throws_js(TypeError, () => delete window[0]);
+});
+test(function() {
+ "use strict";
+ assert_throws_js(TypeError, function() {
+ window[1] = "foo";
+ });
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 1, { value: "bar" }))
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 1, { get() { return "baz" } }))
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 1, { set(v) { return "qux" } }))
+ assert_equals(window[1], undefined);
+ assert_equals(Object.getOwnPropertyDescriptor(window, 1), undefined);
+ assert_equals(delete window[1], true);
+});
+test(function() {
+ "use strict";
+ assert_throws_js(TypeError, () => { window[4294967294] = 1; });
+ assert_false(Reflect.set(window, 4294967294, 2));
+ assert_false(Reflect.defineProperty(window, 4294967294, { value: 3 }));
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 4294967294, { get: () => 4 }));
+ assert_equals(window[4294967294], undefined);
+ assert_false(4294967294 in window);
+ assert_true(delete window[4294967294]);
+}, "Borderline numeric key: 2 ** 32 - 2 is an index (strict mode)");
+test(function() {
+ "use strict";
+ window[4294967295] = 1;
+ assert_equals(window[4294967295], 1);
+ assert_true(Reflect.set(window, 4294967295, 2));
+ assert_equals(window[4294967295], 2);
+ assert_true(Reflect.defineProperty(window, 4294967295, { value: 3 }));
+ assert_equals(window[4294967295], 3);
+ Object.defineProperty(window, 4294967295, { get: () => 4 });
+ assert_equals(window[4294967295], 4);
+ assert_true(delete window[4294967295]);
+ assert_false(4294967295 in window);
+}, "Borderline numeric key: 2 ** 32 - 1 is not an index (strict mode)");
+test(function() {
+ "use strict";
+ var proto = Window.prototype;
+ [-1, 0, 1].forEach(function(idx) {
+ assert_false(idx in proto, idx + " in proto");
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties.html b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties.html
new file mode 100644
index 0000000000..57f18c5944
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-indexed-properties.html
@@ -0,0 +1,71 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Indexed properties of the window object (non-strict mode)</title>
+<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-window-item">
+<link rel="help" href="https://webidl.spec.whatwg.org/#getownproperty">
+<link rel="help" href="https://webidl.spec.whatwg.org/#defineownproperty">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<iframe></iframe>
+<script>
+test(function() {
+ assert_false("-1" in window, "-1 not in window");
+ assert_equals(window[-1], undefined);
+ window[-1] = "foo";
+ assert_equals(window[-1], "foo");
+});
+test(() => {
+ const desc = Object.getOwnPropertyDescriptor(window, "0");
+ assert_true(desc.configurable);
+ assert_true(desc.enumerable);
+ assert_false(desc.writable);
+}, "Ensure indexed properties have the correct configuration");
+test(function() {
+ window[0] = "foo";
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 0, { value: "bar" }))
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 0, { get() { return "baz" } }))
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 0, { set() { return "quz" } }))
+ assert_equals(window[0],
+ document.getElementsByTagName("iframe")[0].contentWindow);
+ assert_equals(delete window[0], false);
+});
+test(function() {
+ window[1] = "foo";
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 1, { value: "bar" }))
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 1, { get() { return "baz" } }))
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 1, { set(v) { return "quz" } }))
+ assert_equals(window[1], undefined);
+ assert_equals(Object.getOwnPropertyDescriptor(window, 1), undefined);
+ assert_equals(delete window[1], true);
+});
+test(function() {
+ window[4294967294] = 1;
+ assert_false(Reflect.set(window, 4294967294, 2));
+ assert_false(Reflect.defineProperty(window, 4294967294, { value: 3 }));
+ assert_throws_js(TypeError, () => Object.defineProperty(window, 4294967294, { get: () => 4 }));
+ assert_equals(window[4294967294], undefined);
+ assert_false(4294967294 in window);
+ assert_true(delete window[4294967294]);
+}, "Borderline numeric key: 2 ** 32 - 2 is an index");
+test(function() {
+ window[4294967295] = 1;
+ assert_equals(window[4294967295], 1);
+ assert_true(Reflect.set(window, 4294967295, 2));
+ assert_equals(window[4294967295], 2);
+ assert_true(Reflect.defineProperty(window, 4294967295, { value: 3 }));
+ assert_equals(window[4294967295], 3);
+ Object.defineProperty(window, 4294967295, { get: () => 4 });
+ assert_equals(window[4294967295], 4);
+ assert_true(delete window[4294967295]);
+ assert_false(4294967295 in window);
+}, "Borderline numeric key: 2 ** 32 - 1 is not an index");
+test(function() {
+ var proto = Window.prototype;
+ [-1, 0, 1].forEach(function(idx) {
+ assert_false(idx in proto, idx + " in proto");
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-open-defaults.window.js b/testing/web-platform/tests/html/browsers/the-window-object/window-open-defaults.window.js
new file mode 100644
index 0000000000..1b2d68a462
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-open-defaults.window.js
@@ -0,0 +1,12 @@
+async_test(t => {
+ const frame = document.createElement("iframe");
+ t.add_cleanup(() => frame.remove());
+ frame.name = "foo";
+ frame.src = "/common/blank.html";
+ frame.onload = t.step_func(() => {
+ frame.onload = t.unreached_func();
+ t.step_timeout(() => t.done(), 500);
+ assert_equals(window[0], window.open(undefined, "foo"));
+ });
+ document.body.append(frame);
+}, "window.open()'s url parameter default");
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-open-invalid-url.html b/testing/web-platform/tests/html/browsers/the-window-object/window-open-invalid-url.html
new file mode 100644
index 0000000000..cabc143b9d
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-open-invalid-url.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>window.open() with an invalid URL</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+test(() => {
+ assert_throws_dom("SyntaxError", () => window.open("https://example.com\u0000mozilla.org"));
+}, "Window.open should throw SyntaxError when an invalid url is passed as the first parameter");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-open-noopener.html b/testing/web-platform/tests/html/browsers/the-window-object/window-open-noopener.html
new file mode 100644
index 0000000000..8d3a95df63
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-open-noopener.html
@@ -0,0 +1,137 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>window.open() with "noopener" tests</title>
+
+<meta name="variant" content="?indexed">
+<meta name="variant" content="?_self">
+<meta name="variant" content="?_parent">
+<meta name="variant" content="?_top">
+<meta name=timeout content=long>
+
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+var testData = [
+ { testDescription: "window.open() with 'noopener' should reuse existing target",
+ secondWindowFeatureString: "noopener",
+ shouldReturnWindow: false },
+ { testDescription: "noopener=1 means the same as noopener",
+ secondWindowFeatureString: "noopener=1",
+ shouldReturnWindow: false },
+ { testDescription: "noopener=true means the same as noopener",
+ secondWindowFeatureString: "noopener=true",
+ shouldReturnWindow: false },
+ { testDescription: "noopener=0 means lack of noopener",
+ secondWindowFeatureString: "noopener=0",
+ shouldReturnWindow: true },
+ { testDescription: "noopener separated only by spaces should work",
+ secondWindowFeatureString: "make me noopener",
+ shouldReturnWindow: false },
+ { testDescription: "Trailing noopener should work",
+ secondWindowFeatureString: "abc def, \n\r noopener",
+ shouldReturnWindow: false },
+ { testDescription: "Leading noopener should work",
+ secondWindowFeatureString: "noopener \f\t , hey, there",
+ shouldReturnWindow: false },
+ { testDescription: "Interior noopener should work",
+ secondWindowFeatureString: "and now, noopener , hey, there",
+ shouldReturnWindow: false },
+ { testDescription: "noreferrer should also suppress opener when reusing existing target",
+ secondWindowFeatureString: "noreferrer",
+ shouldReturnWindow: false },
+];
+
+/**
+ * Loop over our testData array and kick off an async test for each entry. Each
+ * async test opens a window using window.open() with some per-test unique name,
+ * then tries to do a second window.open() call with the same name and the
+ * test-specific feature string. It then checks whether that second
+ * window.open() call reuses the existing window, whether the return value of
+ * the second window.open() call is correct (it should be null in the noopener
+ * cases and non-null in the cases when the existing window gets reused) and so
+ * forth.
+ */
+function indexedTests() {
+ var tests = [];
+ for(var i = 0; i < testData.length; ++i) {
+ var test = testData[i];
+ var t = async_test(test.testDescription);
+ tests.push(t);
+ t.secondWindowFeatureString = test.secondWindowFeatureString;
+ t.windowName = "someuniquename" + i;
+
+ if (test.shouldReturnWindow) {
+ t.step(function() {
+ var windowName = this.windowName;
+
+ var w1 = window.open("", windowName);
+ this.add_cleanup(function() { w1.close(); });
+
+ assert_equals(w1.opener, window);
+
+ var w2 = window.open("", windowName, this.secondWindowFeatureString);
+ assert_equals(w2, w1);
+ assert_equals(w2.opener, w1.opener);
+ assert_equals(w2.opener, window);
+ this.done();
+ });
+ } else {
+ t.step(function() {
+ var w1;
+ this.add_cleanup(function() {
+ w1.close();
+ channel.postMessage(null);
+ });
+
+ var windowName = this.windowName;
+ var channel = new BroadcastChannel(windowName);
+
+ channel.onmessage = this.step_func_done(function(e) {
+ var data = e.data;
+ assert_equals(data.name, windowName, "Should have the right name");
+ assert_equals(data.haveOpener, true, "Should still have opener");
+ assert_equals(w1.opener, window);
+ assert_not_equals(w1.location.href, "about:blank", "Should have navigated");
+ });
+
+ w1 = window.open("", windowName);
+ assert_equals(w1.opener, window);
+
+ var w2 = window.open("support/noopener-target.html?" + windowName,
+ windowName, this.secondWindowFeatureString);
+ assert_equals(w2, null);
+
+ assert_equals(w1.opener, window);
+ });
+ }
+ }
+}
+
+/**
+ * Loop over the special targets that ignore noopener and check that doing a
+ * window.open() with those targets correctly reuses the existing window.
+ */
+function specialTargetTest(target) {
+ if (["_self", "_parent", "_top"].includes(target)) {
+ var t = async_test("noopener window.open targeting " + target);
+ t.openedWindow = window.open(`javascript:var w2 = window.open("", "${target}", "noopener"); this.checkValues(w2); this.close(); void(0);`);
+ assert_equals(t.openedWindow.opener, window);
+ t.openedWindow.checkValues = t.step_func_done(function(win) {
+ assert_equals(win, this.openedWindow);
+ });
+ } else {
+ throw 'testError: special target must be one of: _self, _parent, _top'
+ }
+}
+
+/**
+ * Parse the Query string, check if it matches keyword 'indexed' to run the indexed tests,
+ * otherwise test it as a special target
+ */
+var variant = window.location.href.split("?")[1]
+if(variant == "indexed") {
+ indexedTests();
+} else {
+ specialTargetTest(variant);
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-open-noreferrer.html b/testing/web-platform/tests/html/browsers/the-window-object/window-open-noreferrer.html
new file mode 100644
index 0000000000..92b72cdb5f
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-open-noreferrer.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>window.open() with "noreferrer" tests</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+async_test(t => {
+ const channelName = "343243423432",
+ channel = new BroadcastChannel(channelName);
+ window.open("support/noreferrer-target.html?" + channelName, "", "noreferrer");
+ channel.onmessage = t.step_func_done(e => {
+ // Send message first so if asserts throw the popup is still closed
+ channel.postMessage(null);
+
+ assert_equals(e.data.name, "");
+ assert_equals(e.data.referrer, "");
+ assert_equals(e.data.haveOpener, false);
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-open-popup-behavior.html b/testing/web-platform/tests/html/browsers/the-window-object/window-open-popup-behavior.html
new file mode 100644
index 0000000000..258698d94d
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-open-popup-behavior.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<meta name="timeout" content="long">
+<title>Window.open popup behavior</title>
+<link rel="author" href="masonf@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/window-object.html#window-open-steps">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<script>
+function testOne(windowFeatures, expectPopup) {
+ const windowName = Math.round(Math.random()*1e12);
+ const channel = new BroadcastChannel(windowName);
+ var w;
+ promise_test(() => {
+ return new Promise(resolve => {
+ w = window.open("support/window-open-popup-target.html", windowName, windowFeatures);
+ channel.addEventListener('message', resolve);
+ }).then(e => {
+ // Send message first so if asserts throw the popup is still closed
+ channel.postMessage(null);
+ assert_false(e.data.mixedState, "No mixed state");
+ assert_equals(e.data.isPopup, expectPopup, "Popup state");
+ });
+ },`${windowFeatures} (expect ${expectPopup ? "popup" : "tab"})`);
+}
+
+// No windowpreferences at all - tab.
+testOne(undefined, /*expectPopup=*/false);
+
+// Test all permutations of these properties:
+const features = ["location","toolbar","menubar","resizable","scrollbars","status"];
+const nProps = features.length;
+const skip = 7; // To speed up the test, don't test all values. Skip 7 to pseudo-randomize.
+for(let i=0;i<2**nProps;i+=skip) {
+ const enableVec = Number(i).toString(2).padStart(nProps,'0').split('').map(s => (s==="1"));
+ let windowFeatures = [];
+ for(let i=0;i<nProps;++i) {
+ if (enableVec[i])
+ windowFeatures.push(features[i] + "=yes");
+ }
+ windowFeatures = windowFeatures.join(',');
+ // We get a popup we got windowFeatures, and any of them are false:
+ const expectPopup = !!windowFeatures.length && (!(enableVec[0] || enableVec[1]) || !enableVec[2] || !enableVec[3] || !enableVec[4] || !enableVec[5]);
+ testOne(windowFeatures, expectPopup);
+ testOne(windowFeatures + ",noopener", /*expectPopup=*/false);
+ testOne(windowFeatures + ",noreferrer", /*expectPopup=*/false);
+ testOne(windowFeatures + ",popup", /*expectPopup=*/true); // "popup" feature = popup
+ testOne(windowFeatures + ",noopener,noreferrer,popup", /*expectPopup=*/false);
+}
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-open-windowfeatures-values.html b/testing/web-platform/tests/html/browsers/the-window-object/window-open-windowfeatures-values.html
new file mode 100644
index 0000000000..32551dd8d7
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-open-windowfeatures-values.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<meta charset=utf-8>
+<meta name="timeout" content="long">
+<title>window.open() windowFeature value parsing</title>
+<link rel="author" href="mailto:masonf@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/window-object.html#concept-window-open-features-parse-boolean">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+function testValueGeneric(val, expectTrue, property, testFn) {
+ const windowFeatureStr = val === "" ? property : `${property}=${val}`;
+ async_test(t => {
+ const windowName = '' + Math.round(Math.random()*1e12);
+ const channel = new BroadcastChannel(windowName);
+ channel.onmessage = t.step_func_done(e => {
+ // Send message first so if asserts throw the popup is still closed
+ channel.postMessage(null);
+ testFn(e.data);
+ });
+ window.open("support/windowFeature-values-target.html?" + windowName, windowName, windowFeatureStr);
+ },`Test ${windowFeatureStr}, expected interpretation is ${expectTrue ? 'true' : 'false'}`);
+}
+
+function testValueForNoReferrer(val, expectTrue) {
+ testValueGeneric(val, expectTrue, "noreferrer", (data) => {
+ if (expectTrue) {
+ assert_false(data.haveReferrer);
+ assert_false(data.haveOpener);
+ } else {
+ assert_true(data.haveReferrer);
+ assert_true(data.haveOpener);
+ }
+ });
+}
+
+function testValueForNoOpener(val, expectTrue) {
+ testValueGeneric(val, expectTrue, "noopener", (data) => {
+ assert_equals(data.haveOpener, !expectTrue);
+ });
+}
+
+function testValueForPopup(val, expectTrue) {
+ testValueGeneric(val, expectTrue, "popup", (data) => {
+ assert_equals(data.isPopup, expectTrue);
+ });
+}
+
+function testValue(val, expectTrue) {
+ const quotes = val === "" ? [''] : ['','"',"'"];
+ let noQuotes = true;
+ for (const quote of quotes) {
+ const thisExpectTrue = expectTrue && noQuotes;
+ const thisVal = quote + val + quote;
+ testValueForNoReferrer(thisVal, thisExpectTrue);
+ testValueForNoOpener(thisVal, thisExpectTrue);
+ testValueForPopup(thisVal, thisExpectTrue);
+ noQuotes = false;
+ }
+}
+
+testValue('',true); // Just the parameter means true
+testValue('yes',true); // Yes means true
+testValue('true',true); // True means true
+testValue('foo',false); // If parsing as an integer is an error, false
+testValue('0',false); // 0 is false
+testValue('00',false); // 0 is false
+testValue('1',true); // Non-zero is true
+testValue('99999',true); // Non-zero is true
+testValue('-1',true); // Non-zero is true
+testValue('1foo',true); // This parses to 1
+testValue('0foo',false); // This parses to 0
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-opener-unconfigurable.window.js b/testing/web-platform/tests/html/browsers/the-window-object/window-opener-unconfigurable.window.js
new file mode 100644
index 0000000000..2b9bda6792
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-opener-unconfigurable.window.js
@@ -0,0 +1,17 @@
+test(t => {
+ let desc = Object.getOwnPropertyDescriptor(self, "opener");
+ assert_true(!!desc.get, "Initially {get: function}");
+ assert_true(!!desc.set, "Initially {set: function}");
+ assert_true(desc.configurable, "Initially {configurable: true}");
+ assert_true(desc.enumerable, "Initially {enumerable: true}");
+
+ Object.defineProperty(self, "opener", {configurable: false});
+
+ desc = Object.getOwnPropertyDescriptor(self, "opener");
+ assert_true(!!desc.get, "Still has {get: function}");
+ assert_true(!!desc.set, "Still has {set: function}");
+ assert_false(desc.configurable, "Changed to {configurable: false}");
+ assert_true(desc.enumerable, "Still has {enumerable: true}");
+
+ assert_throws_js(TypeError, () => self.opener = "something", "Throws a TypeError due to {configurable: false}");
+}, "Corner case: self.opener is set while it's not configurable");
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-properties.https.html b/testing/web-platform/tests/html/browsers/the-window-object/window-properties.https.html
new file mode 100644
index 0000000000..c61fb04ae2
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-properties.https.html
@@ -0,0 +1,358 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Properties of the window object</title>
+<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com">
+<link rel="help" href="http://ecma-international.org/ecma-262/5.1/#sec-15.1">
+<link rel="help" href="https://webidl.spec.whatwg.org/#interface-prototype-object">
+<link rel="help" href="https://webidl.spec.whatwg.org/#es-attributes">
+<link rel="help" href="https://webidl.spec.whatwg.org/#es-operations">
+<link rel="help" href="https://dom.spec.whatwg.org/#eventtarget">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowtimers">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowbase64">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowsessionstorage">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#windowlocalstorage">
+<link rel="help" href="https://dvcs.w3.org/hg/editing/raw-file/tip/editing.html#dom-window-getselection">
+<link rel="help" href="http://dev.w3.org/csswg/cssom/#widl-def-Window">
+<link rel="help" href="http://dev.w3.org/csswg/cssom-view/#widl-def-Window">
+<iframe id="iframe" style="visibility: hidden" src="/resources/blank.html"></iframe>
+<iframe id="detachedIframe" style="visibility: hidden" src="/resources/blank.html"></iframe>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+function assert_data_propdesc(pd, Writable, Enumerable, Configurable) {
+ assert_equals(typeof pd, "object");
+ assert_equals(pd.writable, Writable);
+ assert_equals(pd.enumerable, Enumerable);
+ assert_equals(pd.configurable, Configurable);
+}
+function assert_accessor_propdesc(pd, hasSetter, Enumerable, Configurable) {
+ assert_equals(typeof pd, "object");
+ assert_equals(typeof pd.get, "function");
+ assert_true("set" in pd,
+ "Should always have a setter property on the property descriptor");
+ assert_equals(typeof pd.set, hasSetter ? "function" : "undefined");
+ assert_equals(pd.enumerable, Enumerable);
+ assert_equals(pd.configurable, Configurable);
+}
+
+var unforgeableAttributes = [
+ "window",
+ "document",
+ "location",
+ "top"
+];
+
+var replaceableAttributes = [
+ "self",
+ "locationbar",
+ "menubar",
+ "personalbar",
+ "scrollbars",
+ "statusbar",
+ "toolbar",
+ "frames",
+ "parent",
+ "external",
+ "length",
+ "origin",
+
+ // CSSOM-View
+ "screen",
+ "scrollX",
+ "scrollY",
+ "pageXOffset",
+ "pageYOffset",
+ "innerWidth",
+ "innerHeight",
+ "screenLeft",
+ "screenTop",
+ "screenX",
+ "screenY",
+ "outerWidth",
+ "outerHeight",
+ "devicePixelRatio",
+];
+
+var methods = [
+ "close",
+ "stop",
+ "focus",
+ "blur",
+ "open",
+ "alert",
+ "confirm",
+ "prompt",
+ "print",
+ "postMessage",
+
+ // WindowBase64
+ "btoa",
+ "atob",
+
+ // WindowTimers
+ "setTimeout",
+ "clearTimeout",
+ "setInterval",
+ "clearInterval",
+
+ // Microtask queuing
+ "queueMicrotask",
+
+ // ImageBitmap
+ "createImageBitmap",
+
+ // HTML Editing APIs
+ "getSelection",
+
+ // CSSOM
+ "getComputedStyle",
+
+ // CSSOM-View
+ "matchMedia",
+ "moveBy",
+ "moveTo",
+ "resizeBy",
+ "resizeTo",
+ "scroll",
+ "scrollTo",
+ "scrollBy"
+];
+
+var readonlyAttributes = [
+ "history",
+ "frameElement",
+ "navigator",
+
+ // WindowSessionStorage
+ "sessionStorage",
+
+ // WindowLocalStorage
+ "localStorage",
+];
+
+var writableAttributes = [
+ "name",
+ "status",
+ "opener",
+ "onabort",
+ "onafterprint",
+ "onbeforeprint",
+ "onbeforeunload",
+ "onblur",
+ "oncancel",
+ "oncanplay",
+ "oncanplaythrough",
+ "onchange",
+ "onclick",
+ "onclose",
+ "oncontextmenu",
+ "oncuechange",
+ "ondblclick",
+ "ondrag",
+ "ondragend",
+ "ondragenter",
+ "ondragleave",
+ "ondragover",
+ "ondragstart",
+ "ondrop",
+ "ondurationchange",
+ "onemptied",
+ "onended",
+ "onerror",
+ "onfocus",
+ "onhashchange",
+ "oninput",
+ "oninvalid",
+ "onkeydown",
+ "onkeypress",
+ "onkeyup",
+ "onload",
+ "onloadeddata",
+ "onloadedmetadata",
+ "onloadstart",
+ "onmessage",
+ "onmousedown",
+ "onmousemove",
+ "onmouseout",
+ "onmouseover",
+ "onmouseup",
+ "onmousewheel",
+ "onoffline",
+ "ononline",
+ "onpause",
+ "onplay",
+ "onplaying",
+ "onpagehide",
+ "onpageshow",
+ "onpopstate",
+ "onprogress",
+ "onratechange",
+ "onreset",
+ "onresize",
+ "onscroll",
+ "onseeked",
+ "onseeking",
+ "onselect",
+ "onstalled",
+ "onstorage",
+ "onsubmit",
+ "onsuspend",
+ "ontimeupdate",
+ "onunload",
+ "onvolumechange",
+ "onwaiting"
+];
+
+test(function() {
+ // 15.1.1 Value Properties of the Global Object
+ ["NaN", "Infinity", "undefined"].forEach(function(id) {
+ test(function() {
+ assert_true(id in window, id + " in window");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ false, false, false);
+ }, "Value Property: " + id);
+ });
+}, "Value Properties of the Global Object");
+test(function() {
+ // 15.1.2 Function Properties of the Global Object
+ ["eval", "parseInt", "parseFloat", "isNaN", "isFinite"].forEach(function(id) {
+ test(function() {
+ assert_true(id in window, id + " in window");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, false, true);
+ }, "Function Property: " + id);
+ });
+}, "Function Properties of the Global Object");
+test(function() {
+ // 15.1.3 URI Handling Function Properties
+ ["decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent"].forEach(function(id) {
+ test(function() {
+ assert_true(id in window, id + " in window");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, false, true);
+ }, "URI Handling Function Property: " + id);
+ });
+}, "URI Handling Function Properties");
+test(function() {
+ // 15.1.4 Constructor Properties of the Global Object
+ ["Object", "Function", "Array", "String", "Boolean", "Number", "Date",
+ "RegExp", "Error", "EvalError", "RangeError", "ReferenceError",
+ "SyntaxError", "TypeError", "URIError"].forEach(function(id) {
+ test(function() {
+ assert_true(id in window, id + " in window");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, false, true);
+ }, "Constructor Property: " + id);
+ });
+}, "Constructor Properties of the Global Object");
+test(function() {
+ // 15.1.5 Other Properties of the Global Object
+ ["Math", "JSON"].forEach(function(id) {
+ test(function() {
+ assert_true(id in window, id + " in window");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, false, true);
+ }, "Other Property: " + id);
+ });
+}, "Other Properties of the Global Object");
+test(function() {
+ // EventTarget interface
+ ["addEventListener", "removeEventListener", "dispatchEvent"].forEach(function(id) {
+ test(function() {
+ var EventTargetProto = EventTarget.prototype;
+ assert_true(id in window, id + " in window");
+ assert_equals(window[id], EventTargetProto[id]);
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(EventTargetProto, id),
+ true, true, true);
+ assert_equals(Object.getOwnPropertyDescriptor(window, id), undefined);
+ }, "EventTarget method: " + id);
+ });
+}, "EventTarget interface");
+test(function() {
+ // Window interface
+ methods.forEach(function(id) {
+ test(function() {
+ var WindowProto = Window.prototype;
+ assert_true(id in window, id + " in window");
+ assert_false(id in WindowProto, id + " in Window.prototype");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, true, true);
+ }, "Window method: " + id);
+ });
+ readonlyAttributes.forEach(function(id) {
+ test(function() {
+ var WindowProto = Window.prototype;
+ assert_true(id in window, id + " in window");
+ assert_false(id in WindowProto, id + " in Window.prototype");
+ assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ false, true, true);
+ }, "Window readonly attribute: " + id);
+ });
+ writableAttributes.forEach(function(id) {
+ test(function() {
+ var WindowProto = Window.prototype;
+ assert_true(id in window, id + " in window");
+ assert_false(id in WindowProto, id + " in Window.prototype");
+ assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, true, true);
+ }, "Window attribute: " + id);
+ });
+ unforgeableAttributes.forEach(function(id) {
+ test(function() {
+ var WindowProto = Window.prototype;
+ assert_true(id in window, id + " in window");
+ assert_false(id in WindowProto, id + " in Window.prototype");
+ // location has a [PutForwards] extended attribute.
+ assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ id === "location", true, false);
+ }, "Window unforgeable attribute: " + id);
+ });
+ replaceableAttributes.forEach(function(id) {
+ test(function() {
+ var WindowProto = Window.prototype;
+ assert_true(id in window, id + " in window");
+ assert_false(id in WindowProto, id + " in Window.prototype");
+ assert_accessor_propdesc(Object.getOwnPropertyDescriptor(window, id),
+ true, true, true);
+ }, "Window replaceable attribute: " + id);
+ });
+}, "Window interface");
+test(function() {
+ assert_equals(window.constructor, Window);
+ assert_false(window.hasOwnProperty("constructor"), "window.constructor should not be an own property.");
+ assert_data_propdesc(Object.getOwnPropertyDescriptor(Window.prototype, "constructor"),
+ true, false, true);
+}, "constructor");
+var selfReferentialAccessors = ['window', 'self', 'frames'];
+// Test a variety of access methods
+var detached = window.detachedIframe;
+var detachedWindow = detached.contentWindow;
+detachedIframe.remove();
+selfReferentialAccessors.forEach(function(id) {
+ test(function() {
+ assert_equals(eval(`window.${id}`), window);
+ assert_equals(window[id], window);
+ assert_equals(Object.getOwnPropertyDescriptor(window, id).get.call(window), window);
+ assert_equals(Reflect.get(window, id), window);
+ }, "Window readonly getter: " + id);
+
+ test(function() {
+ var globalObject = iframe.contentWindow;
+ var _eval = globalObject.eval;
+ assert_equals(globalObject.eval(`window.${id}`), globalObject);
+ assert_equals(globalObject[id], globalObject);
+ assert_equals(_eval(`Object.getOwnPropertyDescriptor(window, "${id}").get.call(window)`), globalObject);
+ assert_equals(_eval(`Reflect.get(window, "${id}")`), globalObject);
+ }, "Window readonly getter in iframe: " + id);
+ test(function() {
+ var globalObject = detachedWindow;
+ var _eval = globalObject.eval;
+ assert_equals(_eval(`window.${id}`), globalObject);
+ assert_equals(globalObject[id], globalObject);
+ assert_equals(_eval(`Object.getOwnPropertyDescriptor(window, "${id}").get.call(window)`), globalObject);
+ assert_equals(_eval(`Reflect.get(window, "${id}")`), globalObject);
+ }, "Window readonly getter in detached iframe: " + id);
+});
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-prototype-chain.html b/testing/web-platform/tests/html/browsers/the-window-object/window-prototype-chain.html
new file mode 100644
index 0000000000..14dbca35e8
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-prototype-chain.html
@@ -0,0 +1,32 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Prototype chain of the window object</title>
+<link rel="author" title="Ms2ger" href="ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#window">
+<link rel="help" href="https://dom.spec.whatwg.org/#eventtarget">
+<link rel="help" href="https://webidl.spec.whatwg.org/#interface-prototype-object">
+<link rel="help" href="https://webidl.spec.whatwg.org/#named-properties-object">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ assert_class_string(window, "Window");
+}, "window object");
+test(function() {
+ var proto = Object.getPrototypeOf(window);
+ assert_equals(proto, Window.prototype);
+}, "Window.prototype");
+test(function() {
+ var gsp = Object.getPrototypeOf(Object.getPrototypeOf(window));
+ assert_class_string(gsp, "WindowProperties");
+}, "Global scope polluter");
+test(function() {
+ var protoproto = Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(window)));
+ assert_equals(protoproto, EventTarget.prototype);
+}, "EventTarget.prototype");
+test(function() {
+ var protoprotoproto = Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(window))));
+ assert_equals(protoprotoproto, Object.prototype);
+}, "Object.prototype");
+</script>
diff --git a/testing/web-platform/tests/html/browsers/the-window-object/window-reuse-in-nested-browsing-contexts.tentative.html b/testing/web-platform/tests/html/browsers/the-window-object/window-reuse-in-nested-browsing-contexts.tentative.html
new file mode 100644
index 0000000000..03c7a68dfd
--- /dev/null
+++ b/testing/web-platform/tests/html/browsers/the-window-object/window-reuse-in-nested-browsing-contexts.tentative.html
@@ -0,0 +1,158 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+const setupIframe = (t, attrs) => {
+ const iframe = document.createElement('iframe');
+ for (const [key, value] of Object.entries(attrs))
+ iframe[key] = value;
+ const watcher = new EventWatcher(t, iframe, ['load']);
+ document.body.appendChild(iframe);
+ return {iframe, watcher};
+};
+
+promise_test(async t => {
+ const {iframe, watcher} = setupIframe(t, {});
+
+ // Per https://whatwg.org/c/iframe-embed-object.html#process-the-iframe-attributes,
+ // the task to perform the "iframe load event steps" should still be queued.
+ // If a browser already fired a load event, the test will fail here since
+ // EventWatcher will have received an unexpected load event.
+
+ iframe.contentWindow.persistedString = 'Hello world!';
+ iframe.src = 'support/same-origin-iframe.html';
+ await watcher.wait_for(['load']);
+
+ assert_true(iframe.contentWindow.didLoadFrame);
+ // The <iframe>'s session history has only one Document, and that Document is
+ // the initial about:blank Document. The Window object should be reused per
+ // https://whatwg.org/c/iframe-embed-object.html#process-the-iframe-attributes.
+ assert_equals(iframe.contentWindow.persistedString, 'Hello world!');
+}, 'synchronously navigate iframe with no initial src.');
+
+promise_test(async t => {
+ const {iframe, watcher} = setupIframe(t, {});
+
+ // Per https://whatwg.org/c/iframe-embed-object.html#process-the-iframe-attributes,
+ // the task to perform the "iframe load event steps" should still be queued.
+ await watcher.wait_for(['load']);
+
+ iframe.contentWindow.persistedString = 'Hello world!';
+ iframe.src = 'support/same-origin-iframe.html';
+ await watcher.wait_for(['load']);
+
+ assert_true(iframe.contentWindow.didLoadFrame);
+ // The <iframe>'s session history has only one Document, and that Document is
+ // the initial about:blank Document. The Window object should be reused per
+ // https://whatwg.org/c/iframe-embed-object.html#process-the-iframe-attributes.
+ assert_equals(iframe.contentWindow.persistedString, 'Hello world!');
+}, 'after the first iframe load event, navigate iframe with no initial src.');
+
+// Per https://whatwg.org/c/iframe-embed-object.html#otherwise-steps-for-iframe-or-frame-elements,
+// setting the <iframe> src to an empty string before inserting the <iframe>
+// into the document should begin an attempt to navigate to a resource with
+// url == "about:blank".
+promise_test(async t => {
+ const {iframe, watcher} = setupIframe(t, {src: ''});
+
+ // Per https://whatwg.org/c/browsing-the-web.html#navigate, the "about:blank"
+ // resource should be obtained "in parallel". If a browser performs this step
+ // synchronously, the test will fail here since EventWatcher will have
+ // received an unexpected load event.
+
+ iframe.contentWindow.persistedString = 'Hello world!';
+ // An attempt to navigate to "about:blank" already exists but should not have
+ // matured yet since the resource should be obtained "in parallel". The new
+ // navigation attempt will cancel the preexisting attempt.
+ iframe.src = 'support/same-origin-iframe.html';
+ await watcher.wait_for(['load']);
+
+ assert_true(iframe.contentWindow.didLoadFrame);
+ // The navigation attempt to "about:blank" was cancelled, so the <iframe>'s
+ // session history has only one Document, and that Document is the
+ // initial about:blank Document. The Window object should be reused per
+ // https://whatwg.org/c/iframe-embed-object.html#process-the-iframe-attributes.
+ assert_equals(iframe.contentWindow.persistedString, 'Hello world!');
+}, 'synchronously navigate iframe with initial src == "".');
+
+promise_test(async t => {
+ const {iframe, watcher} = setupIframe(t, {src: ''});
+
+ // Per https://whatwg.org/c/browsing-the-web.html#navigate, the "about:blank"
+ // resource should be obtained "in parallel".
+ await watcher.wait_for(['load']);
+
+ iframe.contentWindow.persistedString = 'Hello world!';
+ iframe.src = 'support/same-origin-iframe.html';
+ await watcher.wait_for(['load']);
+
+ assert_true(iframe.contentWindow.didLoadFrame);
+ // A non-initial navigation to about:blank was committed, so the <iframe>
+ // element is no longer displaying the initial about:blank Document. Per
+ // https://whatwg.org/c/browsing-the-web.html#initialise-the-document-object,
+ // the Window object must not be reused.
+ assert_equals(iframe.contentWindow.persistedString, undefined);
+}, 'after the first iframe load event, navigate iframe with initial src == "".');
+
+promise_test(async t => {
+ const {iframe, watcher} = setupIframe(t, {src: 'about:blank'});
+
+ // Per https://whatwg.org/c/browsing-the-web.html#navigate, the "about:blank"
+ // resource should be obtained "in parallel". If a browser performs this step
+ // synchronously, the test will fail here since EventWatcher will have
+ // received an unexpected load event.
+
+ iframe.contentWindow.persistedString = 'Hello world!';
+ // An attempt to navigate to "about:blank" already exists but should not have
+ // matured yet since the resource should be obtained "in parallel". The new
+ // navigation attempt will cancel the preexisting attempt.
+ iframe.src = 'support/same-origin-iframe.html';
+ await watcher.wait_for(['load']);
+
+ assert_true(iframe.contentWindow.didLoadFrame);
+ // The navigation attempt to "about:blank" was cancelled, so the <iframe>'s
+ // session history has only one Document, and that Document is the
+ // initial about:blank Document. The Window object should be reused per
+ // https://whatwg.org/c/iframe-embed-object.html#process-the-iframe-attributes.
+ assert_equals(iframe.contentWindow.persistedString, 'Hello world!');
+}, 'synchronously navigate iframe with initial src == "about:blank".');
+
+promise_test(async t => {
+ const {iframe, watcher} = setupIframe(t, {src: 'about:blank'});
+
+ // Per https://whatwg.org/c/browsing-the-web.html#navigate, the "about:blank"
+ // resource should be obtained "in parallel".
+ await watcher.wait_for(['load']);
+
+ iframe.contentWindow.persistedString = 'Hello world!';
+ iframe.src = 'support/same-origin-iframe.html';
+ await watcher.wait_for(['load']);
+
+ assert_true(iframe.contentWindow.didLoadFrame);
+ // A non-initial navigation to about:blank was committed, so the <iframe>
+ // element is no longer displaying the initial about:blank Document. Per
+ // https://whatwg.org/c/browsing-the-web.html#initialise-the-document-object,
+ // the Window object must not be reused.
+ assert_equals(iframe.contentWindow.persistedString, undefined);
+}, 'after the first iframe load event, navigate iframe with initial src == "about:blank".');
+
+// Per https://whatwg.org/c/iframe-embed-object.html#otherwise-steps-for-iframe-or-frame-elements,
+// setting <iframe> src before inserting the <iframe> into the document should
+// begin an attempt to navigate to the value of the src attribute.
+promise_test(async t => {
+ const {iframe, watcher} = setupIframe(t, {src: 'support/same-origin-iframe.html'});
+
+ iframe.contentWindow.persistedString = 'Hello world!';
+ // Completion of the attempt to navigate happens "in parallel".
+ await watcher.wait_for(['load']);
+
+ assert_true(iframe.contentWindow.didLoadFrame);
+ // The <iframe>'s session history has only one Document, and that Document is
+ // the initial about:blank Document. The Window object should be reused per
+ // https://whatwg.org/c/iframe-embed-object.html#process-the-iframe-attributes.
+ assert_equals(iframe.contentWindow.persistedString, 'Hello world!');
+}, 'iframe with initial src == same-origin resource.');
+</script>