From daa866629ed805cbc491d99bc0d41d45375c7bd9 Mon Sep 17 00:00:00 2001 From: Anne van Kesteren Date: Mon, 10 Sep 2018 18:10:48 +0000 Subject: [PATCH] Bug 1458619 [wpt PR 10789] - HTML: document.open() and aborting documents, a=testonly Automatic update from web-platform-testsHTML: document.open() and aborting documents (#10789) For https://github.com/whatwg/html/pull/3999. Co-authored-by: Anne van Kesteren -- wpt-commits: 2c6612a9b0f67c95fc8cc772cfecc2c1d435d75d wpt-pr: 10789 --HG-- rename : testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/slow.py => testing/web-platform/tests/common/slow.py --- testing/web-platform/meta/MANIFEST.json | 101 ++++++++-- .../resources => common}/slow.py | 0 .../load-error-events-2.html | 2 +- .../load-error-events-3.html | 2 +- .../script-text-modifications.html | 2 +- .../abort-refresh-immediate.window.js | 119 ++++++++++++ ...abort-refresh-multisecond-header.window.js | 69 +++++++ .../abort-refresh-multisecond-meta.window.js | 69 +++++++ .../abort-while-navigating.window.js | 179 ++++++++++++++++++ .../abort.sub.window.js | 104 ++++++++++ .../resources/http-refresh.py | 3 + .../resources/meta-refresh.py | 5 + .../resources/slow-png.py | 8 + 13 files changed, 648 insertions(+), 15 deletions(-) rename testing/web-platform/tests/{html/semantics/scripting-1/the-script-element/resources => common}/slow.py (100%) create mode 100644 testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-immediate.window.js create mode 100644 testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-header.window.js create mode 100644 testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-meta.window.js create mode 100644 testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-while-navigating.window.js create mode 100644 testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort.sub.window.js create mode 100644 testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/http-refresh.py create mode 100644 testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/meta-refresh.py create mode 100644 testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/slow-png.py diff --git a/testing/web-platform/meta/MANIFEST.json b/testing/web-platform/meta/MANIFEST.json index ad17d431b1a4a..f5f9403ec246c 100644 --- a/testing/web-platform/meta/MANIFEST.json +++ b/testing/web-platform/meta/MANIFEST.json @@ -198148,6 +198148,11 @@ {} ] ], + "common/slow.py": [ + [ + {} + ] + ], "common/stringifiers.js": [ [ {} @@ -290673,11 +290678,6 @@ {} ] ], - "html/semantics/scripting-1/the-script-element/resources/slow.py": [ - [ - {} - ] - ], "html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown-child.html": [ [ {} @@ -291413,6 +291413,16 @@ {} ] ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/http-refresh.py": [ + [ + {} + ] + ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/meta-refresh.py": [ + [ + {} + ] + ], "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/page-with-frame.html": [ [ {} @@ -291423,6 +291433,11 @@ {} ] ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/slow-png.py": [ + [ + {} + ] + ], "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/url-frame.html": [ [ {} @@ -368743,6 +368758,36 @@ {} ] ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-immediate.window.js": [ + [ + "/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-immediate.window.html", + {} + ] + ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-header.window.js": [ + [ + "/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-header.window.html", + {} + ] + ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-meta.window.js": [ + [ + "/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-meta.window.html", + {} + ] + ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-while-navigating.window.js": [ + [ + "/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-while-navigating.window.html", + {} + ] + ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort.sub.window.js": [ + [ + "/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort.sub.window.html", + {} + ] + ], "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/aborted-parser.window.js": [ [ "/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/aborted-parser.window.html", @@ -440158,6 +440203,10 @@ "6805c323df5a975231648b830e33ce183c3cbbd3", "support" ], + "common/slow.py": [ + "f3b1c7e2ea61b571bd56cc1c70c5f89bb8e7e4dc", + "support" + ], "common/stringifiers.js": [ "b59ca9c246f75a72d532d58ef628824f8905ff7a", "support" @@ -610715,11 +610764,11 @@ "testharness" ], "html/semantics/scripting-1/the-script-element/load-error-events-2.html": [ - "cefa053e754335e4a84424422a8bfaa9bc72ba75", + "0748b459092089e12743df4ccb458c6edf770515", "testharness" ], "html/semantics/scripting-1/the-script-element/load-error-events-3.html": [ - "c2cf0dbdd988507047184bff3489caeb167f6c88", + "83a752ce2cd860ffb4354a540e5b553d720eb4e9", "testharness" ], "html/semantics/scripting-1/the-script-element/log.py": [ @@ -611586,10 +611635,6 @@ "a6095097dd7e17b1e5370b739b31d361f8fdaf7b", "support" ], - "html/semantics/scripting-1/the-script-element/resources/slow.py": [ - "f3b1c7e2ea61b571bd56cc1c70c5f89bb8e7e4dc", - "support" - ], "html/semantics/scripting-1/the-script-element/script-charset-01.html": [ "c5ac0d0a62a048a55d091935cb6ea733e52a5b82", "testharness" @@ -611667,7 +611712,7 @@ "testharness" ], "html/semantics/scripting-1/the-script-element/script-text-modifications.html": [ - "7278182e171947bbb546e655de84815ff6cacd83", + "0066d3f4260d92b0f541624062269d13fdbd763d", "testharness" ], "html/semantics/scripting-1/the-script-element/script-text-xhtml.xhtml": [ @@ -613518,6 +613563,26 @@ "1c70fce591a38dd7917e1fffbd1d9ebab46e8b7f", "testharness" ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-immediate.window.js": [ + "8d045b9e0ab56874c5eb32367ed56274e0e94a22", + "testharness" + ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-header.window.js": [ + "8c6c1267c4e899a78bd3ad0e67fd8491fd139606", + "testharness" + ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-meta.window.js": [ + "2895f959e55dc3cf2fdfc933c751699b09438b50", + "testharness" + ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-while-navigating.window.js": [ + "e3efeffb8b3af56d365336dba357e0d76f7295aa", + "testharness" + ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort.sub.window.js": [ + "b2f05cf056d54a0602a55a8dda7c67cb94883055", + "testharness" + ], "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/aborted-parser.window.js": [ "1d94de8a7c9f28dfab32111deb664d9921437e46", "testharness" @@ -613670,6 +613735,14 @@ "2404105b09a7724cf8cc5e2cf6d7bf7a8fb6f39b", "support" ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/http-refresh.py": [ + "d2acd4361f92fe286ab13688a9174ce7c5465755", + "support" + ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/meta-refresh.py": [ + "dd3cef44b44252beb3c7729271c51490a475a660", + "support" + ], "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/page-with-frame.html": [ "a1ab01e072b038cd0ec46a8497650845aca83062", "support" @@ -613678,6 +613751,10 @@ "a92a7ae39f8351f97cd865dca5ebe8d4260aa229", "support" ], + "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/slow-png.py": [ + "5fa2fd9a9d850a8a0708985034b89aecf4a51654", + "support" + ], "html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/url-frame.html": [ "be483ff0aea456c3bc7f2e62d863e7f981453203", "support" diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/slow.py b/testing/web-platform/tests/common/slow.py similarity index 100% rename from testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/slow.py rename to testing/web-platform/tests/common/slow.py diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-2.html index cefa053e75433..0748b45909208 100644 --- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-2.html +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-2.html @@ -11,7 +11,7 @@ var test5_load = event_test('no src, parser-inserted, has style sheets blocking scripts, script nesting level == 1', false, false); - + diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-3.html index c2cf0dbdd9885..83a752ce2cd86 100644 --- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-3.html +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-3.html @@ -13,7 +13,7 @@ false, false); document.write( - ` + ` - + diff --git a/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-immediate.window.js b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-immediate.window.js new file mode 100644 index 0000000000000..8d045b9e0ab56 --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-immediate.window.js @@ -0,0 +1,119 @@ +// The following tests deal with the pragma and the +// `Refresh` header. The spec is still hazy on the precise behavior in those +// cases but we use https://github.com/whatwg/html/issues/4003 as a guideline. + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + + const client = new frame.contentWindow.XMLHttpRequest(); + client.open("GET", "/common/blank.html"); + client.onabort = t.step_func_done(); + client.send(); + + frame.contentDocument.open(); + }); + frame.src = "resources/meta-refresh.py?0"; +}, "document.open() aborts documents that are queued for navigation through refresh with timeout 0 (XMLHttpRequest)"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + + frame.contentWindow.fetch("/common/blank.html").then( + t.unreached_func("Fetch should have been aborted"), + t.step_func_done()); + + frame.contentDocument.open(); + }); + frame.src = "resources/meta-refresh.py?0"; +}, "document.open() aborts documents that are queued for navigation through refresh with timeout 0 (fetch())"); + +// We cannot test for img element's error event for this test, as Firefox does +// not fire the event if the fetch is aborted while Chrome does. +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + + let happened = false; + const img = frame.contentDocument.createElement("img"); + img.src = new URL("resources/slow-png.py", document.URL); + img.onload = t.unreached_func("Image loading should not have succeeded"); + // The image fetch starts in a microtask, so let's be sure to test after + // the fetch has started. + t.step_timeout(() => { + frame.contentDocument.open(); + happened = true; + }); + // If 3 seconds have passed and the image has still not loaded, we consider + // it aborted. slow-png.py only sleeps for 2 wallclock seconds. + t.step_timeout(t.step_func_done(() => { + assert_true(happened); + }), 3000); + }); + frame.src = "resources/meta-refresh.py?0"; +}, "document.open() aborts documents that are queued for navigation through refresh with timeout 0 (image loading)"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + + const client = new frame.contentWindow.XMLHttpRequest(); + client.open("GET", "/common/blank.html"); + client.onabort = t.step_func_done(); + client.send(); + + frame.contentDocument.open(); + }); + frame.src = "resources/http-refresh.py?0"; +}, "document.open() aborts documents that are queued for navigation through Refresh header with timeout 0 (XMLHttpRequest)"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + + frame.contentWindow.fetch("/common/blank.html").then( + t.unreached_func("Fetch should have been aborted"), + t.step_func_done()); + + frame.contentDocument.open(); + }); + frame.src = "resources/http-refresh.py?0"; +}, "document.open() aborts documents that are queued for navigation through Refresh header with timeout 0 (fetch())"); + +// We cannot test for img element's error event for this test, as Firefox does +// not fire the event if the fetch is aborted while Chrome does. +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + + let happened = false; + const img = frame.contentDocument.createElement("img"); + img.src = new URL("resources/slow-png.py", document.URL); + img.onload = t.unreached_func("Image loading should not have succeeded"); + // The image fetch starts in a microtask, so let's be sure to test after + // the fetch has started. + t.step_timeout(() => { + frame.contentDocument.open(); + happened = true; + }); + // If 3 seconds have passed and the image has still not loaded, we consider + // it aborted. slow-png.py only sleeps for 2 wallclock seconds. + t.step_timeout(t.step_func_done(() => { + assert_true(happened); + }), 3000); + }); + frame.src = "resources/http-refresh.py?0"; +}, "document.open() aborts documents that are queued for navigation through Refresh header with timeout 0 (image loading)"); diff --git a/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-header.window.js b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-header.window.js new file mode 100644 index 0000000000000..8c6c1267c4e89 --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-header.window.js @@ -0,0 +1,69 @@ +// The following tests deal with the pragma and the +// `Refresh` header. The spec is still hazy on the precise behavior in those +// cases but we use https://github.com/whatwg/html/issues/4003 as a guideline. +// +// This is separate from abort-refresh-multisecond-meta.window.js to avoid +// browser interventions that limit the number of connections in a tab. + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + + const client = new frame.contentWindow.XMLHttpRequest(); + client.open("GET", "/common/blank.html"); + client.onload = t.step_func_done(() => { + assert_true(happened); + }); + client.onerror = t.unreached_func("XMLHttpRequest should have succeeded"); + client.onabort = t.unreached_func("XMLHttpRequest should have succeeded"); + client.ontimeout = t.unreached_func("XMLHttpRequest should have succeeded"); + client.send(); + + frame.contentDocument.open(); + happened = true; + }); + frame.src = "resources/http-refresh.py?1"; +}, "document.open() does NOT abort documents that are queued for navigation through Refresh header with 1-sec timeout (XMLHttpRequest)"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + frame.contentWindow.fetch("/common/blank.html").then( + t.step_func_done(() => { + assert_true(happened); + }), + t.unreached_func("Fetch should have succeeded") + ); + frame.contentDocument.open(); + happened = true; + }); + frame.src = "resources/http-refresh.py?1"; +}, "document.open() does NOT abort documents that are queued for navigation through Refresh header with 1-sec timeout (fetch())"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + const img = frame.contentDocument.createElement("img"); + img.src = new URL("resources/slow-png.py", document.URL); + img.onload = t.step_func_done(() => { + assert_true(happened); + }); + img.onerror = t.unreached_func("Image loading should not have errored"); + // The image fetch starts in a microtask, so let's be sure to test after + // the fetch has started. + t.step_timeout(() => { + frame.contentDocument.open(); + happened = true; + }); + }); + frame.src = "resources/http-refresh.py?4"; +}, "document.open() does NOT abort documents that are queued for navigation through Refresh header with 4-sec timeout (image loading)"); diff --git a/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-meta.window.js b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-meta.window.js new file mode 100644 index 0000000000000..2895f959e55dc --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-refresh-multisecond-meta.window.js @@ -0,0 +1,69 @@ +// The following tests deal with the pragma and the +// `Refresh` header. The spec is still hazy on the precise behavior in those +// cases but we use https://github.com/whatwg/html/issues/4003 as a guideline. +// +// This is separate from abort-refresh-multisecond-header.window.js to avoid +// browser interventions that limit the number of connections in a tab. + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + + const client = new frame.contentWindow.XMLHttpRequest(); + client.open("GET", "/common/blank.html"); + client.onload = t.step_func_done(() => { + assert_true(happened); + }); + client.onerror = t.unreached_func("XMLHttpRequest should have succeeded"); + client.onabort = t.unreached_func("XMLHttpRequest should have succeeded"); + client.ontimeout = t.unreached_func("XMLHttpRequest should have succeeded"); + client.send(); + + frame.contentDocument.open(); + happened = true; + }); + frame.src = "resources/meta-refresh.py?1"; +}, "document.open() does NOT abort documents that are queued for navigation through refresh with 1-sec timeout (XMLHttpRequest)"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + frame.contentWindow.fetch("/common/blank.html").then( + t.step_func_done(() => { + assert_true(happened); + }), + t.unreached_func("Fetch should have succeeded") + ); + frame.contentDocument.open(); + happened = true; + }); + frame.src = "resources/meta-refresh.py?1"; +}, "document.open() does NOT abort documents that are queued for navigation through refresh with 1-sec timeout (fetch())"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + const img = frame.contentDocument.createElement("img"); + img.src = new URL("resources/slow-png.py", document.URL); + img.onload = t.step_func_done(() => { + assert_true(happened); + }); + img.onerror = t.unreached_func("Image loading should not have errored"); + // The image fetch starts in a microtask, so let's be sure to test after + // the fetch has started. + t.step_timeout(() => { + frame.contentDocument.open(); + happened = true; + }); + }); + frame.src = "resources/meta-refresh.py?4"; +}, "document.open() does NOT abort documents that are queued for navigation through refresh with 4-sec timeout (image loading)"); diff --git a/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-while-navigating.window.js b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-while-navigating.window.js new file mode 100644 index 0000000000000..e3efeffb8b3af --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort-while-navigating.window.js @@ -0,0 +1,179 @@ +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + const client = new frame.contentWindow.XMLHttpRequest(); + client.open("GET", "/common/blank.html"); + // The abort event handler is called synchronously in Chrome but + // asynchronously in Firefox. See https://crbug.com/879620. + client.onabort = t.step_func_done(); + client.send(); + frame.contentWindow.location.href = new URL("resources/dummy.html", document.URL); + frame.contentDocument.open(); + }); + frame.src = "/common/blank.html"; +}, "document.open() aborts documents that are navigating through Location (XMLHttpRequest)"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + frame.contentWindow.fetch("/common/blank.html").then( + t.unreached_func("Fetch should have been aborted"), + t.step_func_done(() => { + assert_true(happened); + })); + frame.contentWindow.location.href = new URL("resources/dummy.html", document.URL); + frame.contentDocument.open(); + happened = true; + }); + frame.src = "/common/blank.html"; +}, "document.open() aborts documents that are navigating through Location (fetch())"); + +// We cannot test for img element's error event for this test, as Firefox does +// not fire the event if the fetch is aborted while Chrome does. +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + const img = frame.contentDocument.createElement("img"); + img.src = new URL("resources/slow-png.py", document.URL); + img.onload = t.unreached_func("Image loading should not have succeeded"); + // The image fetch starts in a microtask, so let's be sure to test after + // the fetch has started. + t.step_timeout(() => { + frame.contentWindow.location.href = new URL("resources/dummy.html", document.URL); + frame.contentDocument.open(); + happened = true; + }); + // If 3 seconds have passed and the image has still not loaded, we consider + // it aborted. slow-png.py only sleeps for 2 wallclock seconds. + t.step_timeout(t.step_func_done(() => { + assert_true(happened); + }), 3000); + }); + frame.src = "/common/blank.html"; +}, "document.open() aborts documents that are navigating through Location (image loading)"); + +async_test(t => { + const div = document.body.appendChild(document.createElement("div")); + t.add_cleanup(() => div.remove()); + div.innerHTML = ""; + const frame = div.childNodes[0]; + const client = new frame.contentWindow.XMLHttpRequest(); + client.open("GET", "/common/blank.html"); + client.onabort = t.step_func_done(); + client.send(); + frame.contentDocument.open(); +}, "document.open() aborts documents that are navigating through iframe loading (XMLHttpRequest)"); + +async_test(t => { + const div = document.body.appendChild(document.createElement("div")); + t.add_cleanup(() => div.remove()); + div.innerHTML = ""; + const frame = div.childNodes[0]; + frame.contentWindow.fetch("/common/blank.html").then( + t.unreached_func("Fetch should have been aborted"), + t.step_func_done()); + frame.contentDocument.open(); +}, "document.open() aborts documents that are navigating through iframe loading (fetch())"); + +// We cannot test for img element's error event for this test, as Firefox does +// not fire the event if the fetch is aborted while Chrome does. +// +// We use /common/slow.py here as the source of the iframe, to prevent the +// situation where when document.open() is called the initial about:blank +// document has already become inactive. +async_test(t => { + const div = document.body.appendChild(document.createElement("div")); + t.add_cleanup(() => div.remove()); + div.innerHTML = ""; + const frame = div.childNodes[0]; + let happened = false; + const img = frame.contentDocument.createElement("img"); + img.src = new URL("resources/slow-png.py", document.URL); + img.onload = t.unreached_func("Image loading should not have succeeded"); + // The image fetch starts in a microtask, so let's be sure to test after + // the fetch has started. + t.step_timeout(() => { + frame.contentDocument.open(); + happened = true; + }); + // If 3 seconds have passed and the image has still not loaded, we consider + // it aborted. slow-png.py only sleeps for 2 wallclock seconds. + t.step_timeout(t.step_func_done(() => { + assert_true(happened); + }), 3000); +}, "document.open() aborts documents that are navigating through iframe loading (image loading)"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + const link = frame.contentDocument.body.appendChild(frame.contentDocument.createElement("a")); + link.href = new URL("resources/dummy.html", document.URL); + + const client = new frame.contentWindow.XMLHttpRequest(); + client.open("GET", "/common/blank.html"); + client.onabort = t.step_func_done(); + client.send(); + + link.click(); + frame.contentDocument.open(); + }); + frame.src = "/common/blank.html"; +}, "document.open() aborts documents that are queued for navigation through .click() (XMLHttpRequest)"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + const link = frame.contentDocument.body.appendChild(frame.contentDocument.createElement("a")); + link.href = new URL("resources/dummy.html", document.URL); + + frame.contentWindow.fetch("/common/blank.html").then( + t.unreached_func("Fetch should have been aborted"), + t.step_func_done()); + + link.click(); + frame.contentDocument.open(); + }); + frame.src = "/common/blank.html"; +}, "document.open() aborts documents that are queued for navigation through .click() (fetch())"); + +// We cannot test for img element's error event for this test, as Firefox does +// not fire the event if the fetch is aborted while Chrome does. +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + const link = frame.contentDocument.body.appendChild(frame.contentDocument.createElement("a")); + link.href = new URL("resources/dummy.html", document.URL); + + let happened = false; + const img = frame.contentDocument.createElement("img"); + img.src = new URL("resources/slow-png.py", document.URL); + img.onload = t.unreached_func("Image loading should not have succeeded"); + // The image fetch starts in a microtask, so let's be sure to test after + // the fetch has started. + t.step_timeout(() => { + link.click(); + frame.contentDocument.open(); + happened = true; + }); + // If 3 seconds have passed and the image has still not loaded, we consider + // it aborted. slow-png.py only sleeps for 2 wallclock seconds. + t.step_timeout(t.step_func_done(() => { + assert_true(happened); + }), 3000); + }); + frame.src = "/common/blank.html"; +}, "document.open() aborts documents that are queued for navigation through .click() (image loading)"); diff --git a/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort.sub.window.js b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort.sub.window.js new file mode 100644 index 0000000000000..b2f05cf056d54 --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/abort.sub.window.js @@ -0,0 +1,104 @@ +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + const client = new frame.contentWindow.XMLHttpRequest(); + client.open("GET", "/common/blank.html"); + client.onload = t.step_func_done(e => { + assert_true(happened); + }); + client.onerror = t.unreached_func("XMLHttpRequest should have succeeded"); + client.onabort = t.unreached_func("XMLHttpRequest should have succeeded"); + client.ontimeout = t.unreached_func("XMLHttpRequest should have succeeded"); + client.send(); + frame.contentDocument.open(); + happened = true; + }); + frame.src = "/common/blank.html"; +}, "document.open() does not abort documents that are not navigating (XMLHttpRequest)"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + frame.contentWindow.fetch("/common/blank.html").then( + t.step_func_done(() => { + assert_true(happened); + }), + t.unreached_func("Fetch should have succeeded") + ); + frame.contentDocument.open(); + happened = true; + }); + frame.src = "/common/blank.html"; +}, "document.open() does not abort documents that are not navigating (fetch())"); + +async_test(t => { + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + const img = frame.contentDocument.createElement("img"); + img.src = new URL("resources/slow-png.py", document.URL); + img.onload = t.step_func_done(() => { + assert_true(happened); + }); + img.onerror = t.unreached_func("Image loading should not have errored"); + // The image fetch starts in a microtask, so let's be sure to test after + // the fetch has started. + t.step_timeout(() => { + frame.contentDocument.open(); + happened = true; + }); + }); + frame.src = "/common/blank.html"; +}, "document.open() does not abort documents that are not navigating (image loading)"); + +async_test(t => { + const __SERVER__NAME = "{{host}}"; + const __PORT = {{ports[ws][0]}}; + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + const ws = new frame.contentWindow.WebSocket(`ws://${__SERVER__NAME}:${__PORT}/echo`); + ws.onopen = t.step_func_done(() => { + assert_true(happened); + }); + ws.onclose = t.unreached_func("WebSocket fetch should have succeeded"); + ws.onerror = t.unreached_func("WebSocket should have no error"); + frame.contentDocument.open(); + happened = true; + }); + frame.src = "/common/blank.html"; +}, "document.open() does not abort documents that are not navigating (establish a WebSocket connection)"); + +// An already established WebSocket connection shouldn't be terminated during +// an "abort a document" anyway. Test just for completeness. +async_test(t => { + const __SERVER__NAME = "{{host}}"; + const __PORT = {{ports[ws][0]}}; + const frame = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => frame.remove()); + frame.onload = t.step_func(() => { + frame.onload = null; + let happened = false; + const ws = new frame.contentWindow.WebSocket(`ws://${__SERVER__NAME}:${__PORT}/echo`); + ws.onopen = t.step_func(() => { + t.step_timeout(t.step_func_done(() => { + assert_true(happened); + }), 100); + frame.contentDocument.open(); + happened = true; + }); + ws.onclose = t.unreached_func("WebSocket should not be closed"); + ws.onerror = t.unreached_func("WebSocket should have no error"); + }); + frame.src = "/common/blank.html"; +}, "document.open() does not abort documents that are not navigating (already established WebSocket connection)"); diff --git a/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/http-refresh.py b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/http-refresh.py new file mode 100644 index 0000000000000..d2acd4361f92f --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/http-refresh.py @@ -0,0 +1,3 @@ +def main(request, response): + time = request.url_parts.query if request.url_parts.query else '0' + return 200, [['Refresh', time]], '' diff --git a/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/meta-refresh.py b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/meta-refresh.py new file mode 100644 index 0000000000000..dd3cef44b4425 --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/meta-refresh.py @@ -0,0 +1,5 @@ +import time + +def main(request, response): + time = request.url_parts.query if request.url_parts.query else '0' + return 200, [['Content-Type', 'text/html']], '' % time diff --git a/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/slow-png.py b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/slow-png.py new file mode 100644 index 0000000000000..5fa2fd9a9d850 --- /dev/null +++ b/testing/web-platform/tests/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/resources/slow-png.py @@ -0,0 +1,8 @@ +from base64 import decodestring +import time + +png_response = decodestring('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg==') + +def main(request, response): + time.sleep(2) + return 200, [], png_response