diff options
Diffstat (limited to 'testing/web-platform/tests/html/browsers/the-window-object')
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> |