diff options
Diffstat (limited to 'testing/web-platform/tests/html/semantics/scripting-1')
909 files changed, 20456 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/semantics/scripting-1/META.yml b/testing/web-platform/tests/html/semantics/scripting-1/META.yml new file mode 100644 index 0000000000..0f3cf59653 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/META.yml @@ -0,0 +1,2 @@ +suggested_reviewers: + - domenic diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-noscript-element/non-html-noscript.html b/testing/web-platform/tests/html/semantics/scripting-1/the-noscript-element/non-html-noscript.html new file mode 100644 index 0000000000..2f85d1d47d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-noscript-element/non-html-noscript.html @@ -0,0 +1,16 @@ +<!doctype html> +<title>noscript rules don't apply to non-html elements</title> +<link rel="author" title="Emilio Cobos Ãlvarez" href="mailto:emilio@crisal.io"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-noscript-element"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1470150"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<script> +test(function() { + let non_html_noscript = document.createElementNS("http://www.w3.org/2000/svg", "noscript"); + document.body.appendChild(non_html_noscript); + assert_not_equals(getComputedStyle(non_html_noscript).display, "none"); +}, "Non-HTML <noscript> element shouldn't be undisplayed by a UA rule"); +</script> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/README.md b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/README.md new file mode 100644 index 0000000000..ab4a4820af --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/README.md @@ -0,0 +1,16 @@ +# Script tests + +## Import attributes & JSON/CSS modules + +The import attributes proposal changed the keyword from `assert` to `with`, after that it was already been implemented and shipped in some browsers. Thus, there are some implementations that only support the `assert` syntax and others that only support the `with` syntax. + +For this reason, the import attributes, JSON modules and CSS modules are duplicated to use both keywords: +| `with` keyword | `assert` keyword | +|:----------------------|:---------------------------| +| `./import-attributes` | `./import-assertions` | +| `./json-module` | `./json-module-assertions` | +| `./css-module` | `./css-module-assertions` | + +All changes in one folder should be reflected in the corresponding folder, because the two syntaxes have the same semantics. + +The web compatibility of removing the `assert` keyword is being investigated. If it will be deemed feasible, it will be removed from the proposal and the `assert` tests can be deleted. diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_001.htm b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_001.htm new file mode 100644 index 0000000000..370152683b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_001.htm @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<html> + <head> + <title>Async property on a dynamically-created script is true by default</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test checks the Async property on a dynamically-created script element. By default it should be true." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-script-async"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + test(function() {assert_true(document.createElement("script").async)}, "Async property on a dynamically-created script is true by default"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_002.htm b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_002.htm new file mode 100644 index 0000000000..e1850ff6e1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_002.htm @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html> + <head> + <title>Changes to the 'async' attribute are reflected in the async property</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures changes to the 'async' attribute are reflected in the async property." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-script-async"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + test(function() { + var s = document.createElement("script"); + s.async = false; + s.setAttribute('async', ''); /*Should change s.async to true*/ + assert_true(s.async) + }, "Test 'async' attribute are reflected in the async property with setAttribute"); + + test(function() { + var s = document.createElement("script"); + s.async = false; + s.setAttribute('async', ''); /*Should change s.async to true*/ + s.removeAttribute('async'); /*Should change s.async to false*/ + assert_false(s.async) + }, "Test 'async' attribute are reflected in the async property with removeAttribute"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_003.htm b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_003.htm new file mode 100644 index 0000000000..c6d84f9a87 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_003.htm @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> + <head> + <title>An async script does not block the parser while downloading</title> + <meta name="timeout" content="long"> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures an async script does not block the parser while downloading." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-script-async"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("An async script does not block the parser while downloading"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "21")}); + t.done(); + } + + var timer = setTimeout(timeout, 4000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + + <script src="log.py?sec=3&id=1" async></script> + <script> + log('2'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_004.htm b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_004.htm new file mode 100644 index 0000000000..5d9df099b7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_004.htm @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> + <head> + <title>An async script executes as soon as possible after a download is complete</title> + <meta name="timeout" content="long"> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures an async script executes as soon as possible after a download is complete." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-script-async"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("async script executes as soon as possible after a download is complete"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "21")}); + t.done(); + } + + var timer = setTimeout(timeout, 4000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + + <script src="log.py?sec=3&id=1" async></script> + <script src="log.py?sec=1&id=2" async></script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_005.htm b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_005.htm new file mode 100644 index 0000000000..03f9adeb67 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_005.htm @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html> + <head> + <title>A script element with both async and defer set should execute asynchronously</title> + <meta name="timeout" content="long"> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures a script element with both async and defer set should execute asynchronously." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-script-async"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("A script element with both async and defer set should execute asynchronously"); + + function timeout() + { + t.step(function(){ + var actual = document.getElementById("testresult").innerHTML; + assert_in_array(actual, ["2134", "2341"]); + }); + t.done(); + } + + var timer = setTimeout(timeout, 5000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + + <script type="text/javascript" src="log.py?sec=1&id=1" defer async></script> + <script type="text/javascript">log('2');</script> + <script type="text/javascript" src="log.py?sec=3&id=3"></script> + <script type="text/javascript">log('4');</script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_006.htm b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_006.htm new file mode 100644 index 0000000000..ed3d8b22c6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_006.htm @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html> + <head> + <title>A dynamically created external script executes asynchronously</title> + <meta name="timeout" content="long"> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures a dynamically created external script executes asynchronously." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#force-async"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("dynamically created external script executes asynchronously"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "321")}); + t.done(); + } + + var timer = setTimeout(timeout, 4000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + <script type="text/javascript"> + var one = document.createElement("script"); + one.src="log.py?sec=3&id=1"; + document.head.appendChild(one); + + var two = document.createElement("script"); + two.src="log.py?sec=1&id=2"; + document.head.appendChild(two); + + log('3'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_007.htm b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_007.htm new file mode 100644 index 0000000000..6c4ae29e06 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_007.htm @@ -0,0 +1,49 @@ +<!DOCTYPE html> +<html> + <head> + <title>Ordered async script execution when script.async == false</title> + <meta name="timeout" content="long"> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures Ordered async script execution when script.async == false" /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#script-processing-src-sync"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("Ordered async script execution when script.async == false"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "312")}); + t.done(); + } + + var timer = setTimeout(timeout, 8000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + <script type="text/javascript"> + var one = document.createElement("script"); + one.src="log.py?sec=3&id=1"; + one.async = false; + document.head.appendChild(one); + + var two = document.createElement("script"); + two.src="log.py?sec=1&id=2"; + two.async = false; + document.head.appendChild(two); + </script> + <script type="text/javascript"> + log('3'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_008.htm b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_008.htm new file mode 100644 index 0000000000..73529cc318 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_008.htm @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html> + <head> + <title>Async script element execution delays the window's load event</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures an async script element's execution delays the window's load event." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#delay-the-load-event"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script type="text/javascript"> + var t = async_test("Async script element execution delays the window's load event"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "213")}); + t.done(); + } + + var timer = setTimeout(timeout, 8000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + + <span id="testresult"></span> + <script type="text/javascript"> + window.addEventListener("load", function() { + log("3"); + timeout(); + }, false); + + var s1 = document.createElement("script"); + s1.src = "log.py?sec=2&id=1"; + document.head.appendChild(s1); + </script> + <script type="text/javascript"> + log('2'); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_009.htm b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_009.htm new file mode 100644 index 0000000000..307aa46412 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_009.htm @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> + <head> + <title>Document.write() silently fails from an Async script</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures Document.write() silently fails from an Async script." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script type="text/javascript"> + var t = async_test("Document.write() silently fails from an Async script"); + + var log = t.step_func(function() { + document.write("<span id='writtenText'></span>"); + assert_equals(null, document.getElementById('writtenText')); + t.done(); + }); + </script> + </head> + <body> + <div id=log></div> + <script type="text/javascript" src="log.py?sec=1&id=1" async></script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_010.htm b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_010.htm new file mode 100644 index 0000000000..c54defc00d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_010.htm @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<html> + <head> + <title>Removing an async script before execution</title> + <meta name="timeout" content="long"> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="This test ensures that an async script still executes if it is removed from a markup before the download is complete. The other two scripts that come after it in insertion order should execute as well." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script type="text/javascript"> + var t = async_test("Removing an async script before execution"); + + function timeout() + { + t.step(function(){ assert_equals(document.getElementById("testresult").innerHTML, "4123")}); + t.done(); + } + + var timer = setTimeout(timeout, 8000); + + function log(text) + { + var textNode = document.createTextNode(text); + document.getElementById("testresult").appendChild(textNode); + } + </script> + </head> + <body> + <div id=log></div> + <span id="testresult"></span> + <script type="text/javascript"> + var s1 = document.createElement("script"); + s1.src="log.py?sec=2&id=1"; + s1.async = false; + document.body.appendChild(s1); + + var s2 = document.createElement("script"); + s2.src="log.py?sec=1&id=2"; + s2.async = false; + document.body.appendChild(s2); + + var s3 = document.createElement("script"); + s3.id = "s3"; + s3.src="log.py?sec=0&id=3"; + s3.async = false; + document.body.appendChild(s3); + + //Remove s1 (Should still execute) + document.body.removeChild(s1); + </script> + <script type="text/javascript">log('4');</script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_011.htm b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_011.htm new file mode 100644 index 0000000000..d80e463cee --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/async_011.htm @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> + <head> + <title>An empty parser-inserted script element should return async=true</title> + <meta http-equiv="content-type" content="text/html; charset=UTF-8" /> + <meta description="An empty parser-inserted script element should return async=true." /> + <link rel="author" title="Microsoft" href="http://www.microsoft.com/" /> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"/> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <div id=log></div> + <script></script> + <script type="text/javascript"> + test(function() { assert_true(document.getElementsByTagName("script")[2].async)}, "An empty parser-inserted script element should return async=true"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/cacheable-script-throw.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/cacheable-script-throw.py new file mode 100644 index 0000000000..b315afed56 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/cacheable-script-throw.py @@ -0,0 +1,4 @@ +def main(request, response): + headers = [(b"Content-Type", b"text/javascript"), (b"Cache-control", b"public, max-age=100")] + body = u"throw('fox');" + return 200, headers, body diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/charset-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/charset-2.html new file mode 100644 index 0000000000..aaa2960aaf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/charset-2.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset="windows-1250"> +<title>CSS modules: UTF-8 decoding</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script type="module"> + import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/utf-8.css" assert { type: "css"}; + test(() => { + assert_equals(styleSheet.rules[0].style.content, "\"�湿�\""); + }, "CSS module should be loaded as utf-8 even though document's encoding is windows-1250"); +</script> +<script type="module"> + import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/windows-1250.css&ct=text/css%3Bcharset=windows-1250" assert { type: "css"}; + test(() => { + assert_not_equals(styleSheet.rules[0].style.content, "\"�湿�\"", + 'Should be decoded as UTF-8'); + }, "CSS module should be loaded as utf-8 even if it is encoded in windows-1250 and served with a windows-1250 charset response header, and this document's encoding is windows-1250"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/charset-bom.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/charset-bom.html new file mode 100644 index 0000000000..e26ee08d31 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/charset-bom.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<title>CSS Module scripts should ignore BOMs and always use UTF-8</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="module"> + import utf8BOMSheet from './resources/bom-utf-8.css' assert { type: 'css' }; + test(function() { + assert_equals(utf8BOMSheet.rules[0].selectorText, 'div', 'No UTF-8 BOM expected in selector'); + }, 'UTF-8 BOM should be stripped when decoding JSON module script'); + + import utf16BEBOMSheet from './resources/bom-utf-16be.css' assert { type: 'css' }; + test(function() { + assert_equals(utf16BEBOMSheet.rules[0].selectorText, '\ufffd\ufffd\ufffdd\ufffdi\ufffdv\ufffd \ufffd', 'Expected UTF-8 decoded selectorText with 0xfffd replacement characters'); + }, 'UTF-16BE BOM should be ignored, so CSS module should be UTF-8 decoded'); + + import utf16LEBOMSheet from './resources/bom-utf-16le.css' assert { type: 'css' }; + test(function() { + assert_equals(utf16LEBOMSheet.rules[0].selectorText, '\ufffd\ufffdd\ufffdi\ufffdv\ufffd \ufffd', 'Expected UTF-8 decoded selectorText with 0xfffd replacement characters'); + }, 'UTF-16LE BOM should be ignored, so CSS module should be UTF-8 decoded'); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/charset.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/charset.html new file mode 100644 index 0000000000..2127ec7280 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/charset.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>CSS modules: UTF-8 decoding</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script type="module" onerror="unreachable()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/utf-8.css&ct=text/css%3Bcharset=utf-8" assert { type: "css"}; + test(() => { + assert_equals(styleSheet.rules[0].style.content, "\"śćążź\""); + }, "CSS module should be loaded as utf-8 when charset=utf8 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/utf-8.css&ct=text/css%3Bcharset=shift-jis" assert { type: "css"}; + test(() => { + assert_equals(styleSheet.rules[0].style.content, "\"śćążź\""); + }, "CSS module should be loaded as utf-8 when charset=shift-jis is specified"); +</script> +<script type="module" onerror="unreachable()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/utf-8.css&ct=text/css%3Bcharset=windows-1252" assert { type: "css"}; + test(() => { + assert_equals(styleSheet.rules[0].style.content, "\"śćążź\""); + }, "CSS module should be loaded as utf-8 when charset=windows-1252 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/utf-8.css&ct=text/css%3Bcharset=utf-7" assert { type: "css"};; + test(() => { + assert_equals(styleSheet.rules[0].style.content, "\"śćążź\""); + }, "CSS module should be loaded as utf-8 when charset=utf-7 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/windows-1250.css&ct=text/css%3Bcharset=windows-1250" assert { type: "css"}; + test(() => { + assert_not_equals(styleSheet.rules[0].style.content, "\"śćążź\"", + 'Should be decoded as UTF-8'); + }, "CSS module should be loaded as utf-8 even if it is encoded in windows-1250 and served with a windows-1250 charset response header"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/content-type-checking.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/content-type-checking.html new file mode 100644 index 0000000000..3ade863305 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/content-type-checking.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>CSS modules: Content-Type</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +function check(t, styleSheet) { + t.step(() => { + assert_equals(styleSheet.rules[0].cssText, "#test { background-color: rgb(255, 0, 0); }"); + t.done(); + }); +} +const t1 = async_test("text/css"); +const t2 = async_test("application/css"); +const t3 = async_test("text/html+css"); +const t4 = async_test("text/css;boundary=something"); +const t5 = async_test("text/css;foo=bar"); +</script> +<script type="module" onerror="t1.unreached_func()()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/basic.css&ct=text/css" assert { type: "css"}; + check(t1, styleSheet); +</script> +<script type="module" onerror="t2.step_func_done()()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/basic.css&ct=application/css" assert { type: "css"}; + t2.unreached_func("Should not have loaded with MIME type application/css")(); +</script> +<script type="module" onerror="t3.step_func_done()()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/basic.css&ct=text/html+css" assert { type: "css"}; + t3.unreached_func("Should not have loaded with MIME type text/html+css")(); +</script> +<script type="module" onerror="t4.unreached_func()()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/basic.css&ct=text/css;boundary=something" assert { type: "css"}; + check(t4, styleSheet); +</script> +<script type="module" onerror="t5.unreached_func()()"> +import styleSheet from "../serve-with-content-type.py?fn=css-module-assertions/resources/basic.css&ct=text/css;foo=bar" assert { type: "css"}; +check(t5, styleSheet); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/cors-crossorigin-requests.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/cors-crossorigin-requests.html new file mode 100644 index 0000000000..b9de562b72 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/cors-crossorigin-requests.html @@ -0,0 +1,33 @@ +<!doctype html> +<html> +<head> + <title>css-module-assertions-crossorigin</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <h1>css-module-assertions-crossorigin</h1> + <iframe id="import-WithCORS" src="resources/crossorigin-import-with-cors.sub.html"></iframe> + <iframe id="import-NoCORS" src="resources/crossorigin-import-without-cors.sub.html"></iframe> + <iframe id="import-parseerror-WithCors" src="resources/crossorigin-import-parse-error-with-cors.sub.html"></iframe> + <script> + + var tests = [ + { "obj": async_test("Imported CSS module, cross-origin with CORS"), "id": "import-WithCORS", "expected": "imported CSS: #test { background-color: rgb(255, 0, 0); }" }, + { "obj": async_test("Imported CSS module, cross-origin, missing CORS ACAO header"), "id": "import-NoCORS", "expected": "error" }, + { "obj": async_test("Imported CSS module with parse error, cross-origin, with CORS"), "id": "import-parseerror-WithCors", "expected": "imported CSS rules count: 0" }, + ]; + + window.addEventListener("load", function () { + tests.forEach(function (test) { + var target = document.getElementById(test.id); + test.obj.step(function () { + assert_equals(target.contentDocument._log, test.expected, "Unexpected _log value"); + }); + test.obj.done(); + }); + }); + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/credentials.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/credentials.sub.html new file mode 100644 index 0000000000..8c2f0f8073 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/credentials.sub.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +document.cookie = 'milk=1'; + +const setCookiePromise = fetch( + 'http://{{domains[www2]}}:{{ports[http][0]}}/cookies/resources/set-cookie.py?name=milk&path=/html/semantics/scripting-1/the-script-element/css-module-assertions/', + { + mode: 'no-cors', + credentials: 'include', + }); + +const windowLoadPromise = new Promise(resolve => { + window.addEventListener('load', () => { + resolve(); + }); +}); + +promise_test(t => { + const iframe = document.createElement('iframe'); + + return Promise.all([setCookiePromise, windowLoadPromise]).then(() => { + const messagePromise = new Promise(resolve => { + window.addEventListener('message', event => { + resolve(); + }); + }); + + iframe.src = 'resources/credentials-iframe.sub.html'; + document.body.appendChild(iframe); + + return messagePromise; + }).then(() => { + const w = iframe.contentWindow; + + assert_equals(w.sameOriginNoneDescendant, true, + 'Descendant CSS modules should be loaded with the credentials when the crossOrigin attribute is not specified and the target is same-origin'); + assert_equals(w.sameOriginAnonymousDescendant, true, + 'Descendant CSS modules should be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is same-origin'); + assert_equals(w.sameOriginUseCredentialsDescendant, true, + 'Descendant CSS modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is same-origin'); + assert_equals(w.crossOriginNoneDescendant, false, + 'Descendant CSS modules should not be loaded with the credentials when the crossOrigin attribute is not specified and the target is cross-origin'); + assert_equals(w.crossOriginAnonymousDescendant, false, + 'Descendant CSS modules should not be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is cross-origin'); + assert_equals(w.crossOriginUseCredentialsDescendant, true, + 'Descendant CSS modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is cross-origin'); +}); +}, 'CSS Modules should be loaded with or without the credentials based on the same-origin-ness and the crossOrigin attribute'); +</script> +<body> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/css-module-worker-test.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/css-module-worker-test.html new file mode 100644 index 0000000000..7ff672da6a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/css-module-worker-test.html @@ -0,0 +1,54 @@ +<!doctype html> + +<head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/utils.js"></script> +</head> + +<body> + <script> + setup({allow_uncaught_exception: true}); + promise_test(function (test) { + const uuid = token(); + const worker = new Worker(`./resources/worker.sub.js?key=${uuid}`, { + type: "module" + }); + return new Promise((resolve, reject) => { + worker.addEventListener("error", resolve); + worker.addEventListener("message", reject); + }).then(async () => { + const fetchResponse = await fetch(`./resources/record-fetch.py?key=${uuid}&action=getCount`); + const fetchData = await fetchResponse.json(); + assert_equals(fetchData.count, 0, "Shouldn't have tried fetching CSS module in worker"); + }); + }, "A static import CSS Module within a web worker should not load and should not attempt to fetch the module."); + + promise_test(function (test) { + const uuid = token(); + const worker = new Worker(`./resources/worker-dynamic-import.sub.js?key=${uuid}`, { + type: "module" + }); + + return new Promise(resolve => { + worker.addEventListener("message", resolve); + }).then(async (event) => { + assert_equals(event.data, "NOT LOADED"); + const fetchResponse = await fetch(`./resources/record-fetch.py?key=${uuid}&action=getCount`); + const fetchData = await fetchResponse.json(); + assert_equals(fetchData.count, 0, "Shouldn't have tried fetching CSS module in worker"); + }); + }, "A dynamic import CSS Module within a web worker should not load and should not attempt to fetch the module."); + + promise_test(function (test) { + const worker = new Worker("./resources/basic.css", { + type: "module" + }); + return new Promise(resolve => { + worker.onerror = resolve; + }); + }, "An attempt to load a CSS module as a worker should fail."); + + </script> + +</body>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/import-css-module-basic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/import-css-module-basic.html new file mode 100644 index 0000000000..4ea1790aab --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/import-css-module-basic.html @@ -0,0 +1,83 @@ +<!doctype html> +<head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <div id="test">I am a test div.</div> + <div id="test2">I am a test div.</div> + <div id="test3">I am a test div.</div> + <div id="test3b">I am a test div.</div> + <div id="test4">I am a test div.</div> + <div id="test4b">I am a test div.</div> + <script> + window.errorCount = 0; + window.onerror = (errorMsg, url, lineNumber, column, errorObj) => { + window.errorCount++; + }; + </script> + <script type="module" onerror="unreachable()"> + import sheet from "./resources/basic.css" assert { type: "css" }; + test(() => { + document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]; + assert_equals(getComputedStyle(document.querySelector('#test')) + .backgroundColor, "rgb(255, 0, 0)", "CSS module import should succeed"); + }, "A CSS Module should load"); + </script> + <script type="module" onerror="unreachable()"> + import sheet from "./resources/basic-large.css" assert { type: "css" }; + test(() => { + // This tests potential streaming compilation of modules in + // Chromium that is triggered only for large (32>KiB) files in older + // versions. + document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]; + assert_equals(getComputedStyle(document.querySelector('#test2')) + .backgroundColor, "rgb(255, 0, 0)", + "CSS module import should succeed"); + }, "A large CSS Module should load"); + </script> + <script type="module" onerror="unreachable()"> + import sheet from "./resources/bad-import.css" assert { type: "css" }; + test(() => { + document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]; + assert_equals(window.errorCount, 0); + assert_equals(sheet.cssRules.length, 1, "Parser should skip @import rule"); + assert_equals(getComputedStyle(document.querySelector('#test3b')) + .backgroundColor, "rgba(0, 0, 0, 0)", + "CSS module @import should not succeed"); + assert_equals(getComputedStyle(document.querySelector('#test3')) + .backgroundColor, "rgb(0, 255, 0)", + "Rule after @import should still be applied"); + }, "An @import CSS Module should not load, but should not throw an exception"); + </script> + <script type="module" onerror="unreachable()"> + import sheet from "./resources/malformed.css" assert { type: "css" }; + test(() => { + document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]; + assert_equals(window.errorCount, 0); + assert_equals(sheet.cssRules.length, 1, "Import of malformed CSS should succeed and rules after the parse error should still be parsed"); + assert_equals(getComputedStyle(document.querySelector('#test4')) + .backgroundColor, "rgba(0, 0, 0, 0)", + "Malformed CSS rule should not be applied"); + assert_equals(getComputedStyle(document.querySelector('#test4b')) + .backgroundColor, "rgb(0, 255, 0)", + "Parsing should recover and rules after malformed rules should be applied"); + }, "A parse error should not prevent subsequent rules from being included in a CSS module"); + </script> + <script type="module"> + promise_test(function (test) { + const iframe = document.createElement("iframe"); + iframe.src = "resources/css-module-without-assertion-iframe.html"; + return new Promise(resolve => { + iframe.onload = resolve; + document.body.appendChild(iframe); + }).then(event => { + assert_equals(iframe.contentDocument.window_onerror, undefined); + assert_equals(iframe.contentDocument.script_onerror.type, "error"); + assert_equals(getComputedStyle(iframe.contentDocument.querySelector('#test')) + .backgroundColor, "rgba(0, 0, 0, 0)", + "CSS module without type assertion should result in a fetch error"); + }); + }, "CSS module without type assertion should result in a fetch error"); + </script> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/import-css-module-dynamic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/import-css-module-dynamic.html new file mode 100644 index 0000000000..13967858cb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/import-css-module-dynamic.html @@ -0,0 +1,23 @@ +<!doctype html> + +<head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + +<body> + <script> + promise_test(async function (test) { + const css_module = await import("./resources/basic.css", { assert: { type: "css" }}); + assert_true(css_module.default instanceof CSSStyleSheet); + assert_equals(css_module.default.cssRules[0].cssText, + "#test { background-color: rgb(255, 0, 0); }"); + }, "Load a CSS module with dynamic import()"); + + promise_test(function (test) { + return promise_rejects_js(test, TypeError, + import("./resources/basic.css"), + "Attempting to import() a CSS module without a type assertion should fail"); + }, "Ensure that loading a CSS module with dymnamic import() fails without a type assertion"); + </script> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/integrity.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/integrity.html new file mode 100644 index 0000000000..1dd0dad470 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/integrity.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title><script> integrity="" with CSS modules</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +window.matchesLog = []; +window.matchesEvents = []; + +window.mismatchesLog = []; +window.mismatchesEvents = []; +</script> +<script type="module" src="resources/integrity-matches.js" integrity="sha384-xvbfmg9iJFHqmCoOS4VNMCwnFPPxEoIlW1Ojzl+fgEd+Wf8Pyez+SMWue+KNovjA" onload="window.matchesEvents.push('load');" onerror="window.matchesEvents.push('error')"></script> +<script type="module" src="resources/integrity-mismatches.js" integrity="sha384-doesnotmatch" onload="window.mismatchesEvents.push('load');" onerror="window.mismatchesEvents.push('error')"></script> + +<script type="module"> +test(() => { + assert_array_equals(window.matchesLog, ["integrity-matches,css:#test { background-color: rgb(255, 0, 0); }"], "The module and its dependency must have executed"); + assert_array_equals(window.matchesEvents, ["load"], "The load event must have fired"); +}, "The integrity attribute must be verified on the top-level of a module loading a CSS module and allow it to execute when it matches"); + +test(() => { + assert_array_equals(window.mismatchesLog, [], "The module and its dependency must not have executed"); + assert_array_equals(window.mismatchesEvents, ["error"], "The error event must have fired"); +}, "The integrity attribute must be verified on the top-level of a module loading a CSS module and not allow it to execute when there's a mismatch"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/load-error-events.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/load-error-events.html new file mode 100644 index 0000000000..3457452c93 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/load-error-events.html @@ -0,0 +1,67 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<head> +<title>load/error events for CSS modules</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/load-error-events-helpers.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +</head> +<script> + "use strict"; + + var test1_load = event_test('inline, 200, parser-inserted', false, false); + var test1_error = event_test('inline, 404, parser-inserted', false, true); + + var test2_load = event_test('src, 200, parser-inserted', true, false); + var test2_error = event_test('src, 404, parser-inserted', false, true); + + var test3_dynamic_load = event_test('src, 200, not parser-inserted', true, false); + var test3_dynamic_error = event_test('src, 404, not parser-inserted', false, true); + + var test4_dynamic_load = event_test('inline, 200, not parser-inserted', false, false); + var test4_dynamic_error = event_test('inline, 404, not parser-inserted', false, true); + + var script3_dynamic_load = document.createElement('script'); + script3_dynamic_load.setAttribute('type', 'module'); + script3_dynamic_load.onload = () => onLoad(test3_dynamic_load); + script3_dynamic_load.onerror = () => onError(test3_dynamic_load); + script3_dynamic_load.src = "./resources/load-error-events.py?test=test3_dynamic_load"; + document.head.appendChild(script3_dynamic_load); + + var script3_dynamic_error = document.createElement('script'); + script3_dynamic_error.setAttribute('type', 'module'); + script3_dynamic_error.onload = () => onLoad(test3_dynamic_error); + script3_dynamic_error.onerror = () => onError(test3_dynamic_error); + script3_dynamic_error.src = "./resources/load-error-events.py?test=test3_dynamic_error"; + document.head.appendChild(script3_dynamic_error); + + var script4_dynamic_load = document.createElement('script'); + script4_dynamic_load.setAttribute('type', 'module'); + script4_dynamic_load.onload = () => onLoad(test4_dynamic_load); + script4_dynamic_load.onerror = () => onError(test4_dynamic_load); + script4_dynamic_load.async = true; + script4_dynamic_load.appendChild(document.createTextNode(` + import "./resources/basic.css" assert { type: "css" }; + onExecute(test4_dynamic_load);` + )); + document.head.appendChild(script4_dynamic_load); + + var script4_dynamic_error = document.createElement('script'); + script4_dynamic_error.setAttribute('type', 'module'); + script4_dynamic_error.onload = () => onLoad(test4_dynamic_error); + script4_dynamic_error.onerror = () => onError(test4_dynamic_error); + script4_dynamic_error.async = true; + script4_dynamic_error.appendChild(document.createTextNode(`import "./not_found.css" assert { type: "css" };`)); + document.head.appendChild(script4_dynamic_error); +</script> +<script onload="onLoad(test1_load);" onerror="onError(test1_load);" type="module"> + import "./resources/basic.css" assert { type: "css"}; + onExecute(test1_load); +</script> +<script onload="onLoad(test1_error);" onerror="onError(test1_error);" type="module"> + import "./not_found.css" assert { type: "css"}; + onExecute(test1_error); +</script> +<script src="./resources/load-error-events.py?test=test2_load" onload="onLoad(test2_load);" onerror="onError(test2_load);" type="module"></script> +<script src="./resources/load-error-events.py?test=test2_error" onload="onLoad(test2_error);" onerror="onError(test2_error);" type="module"></script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/referrer-policies.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/referrer-policies.sub.html new file mode 100644 index 0000000000..f078437e09 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/referrer-policies.sub.html @@ -0,0 +1,84 @@ +<!DOCTYPE html> +<html> +<head> +<title>Referrers with CSS module requests</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> + // "name" parameter is necessary for bypassing the module map. + import referrerSame from "./resources/referrer-checker.py?name=sameNoReferrerPolicy" assert { type: "css"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/referrer-checker.py?name=remoteNoReferrerPolicy" assert { type: "css"}; + + const origin = (new URL(location.href)).origin + "/"; + const originUrl = location.href; + + test(t => { + assert_equals( + referrerSame.rules[0].style.content, '"' + originUrl + '"', + "Referrer URL should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the default referrer policy."); + + test(t => { + assert_equals( + referrerRemote.rules[0].style.content, '"' + origin + '"', + "Referrer origin should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the default referrer policy."); +</script> +<script type="module" referrerpolicy="origin"> + import referrerSame from "./resources/referrer-checker.py?name=sameReferrerPolicyOrigin" assert { type: "css"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/referrer-checker.py?name=remoteReferrerPolicyOrigin" assert { type: "css"}; + + const origin = (new URL(location.href)).origin + "/"; + + test(t => { + assert_equals( + referrerSame.rules[0].style.content, '"' + origin + '"', + "Referrer origin should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the origin policy."); + + test(t => { + assert_equals( + referrerRemote.rules[0].style.content, '"' + origin + '"', + "Referrer origin should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the origin policy."); + +</script> +<script type="module" referrerpolicy="no-referrer"> + import referrerSame from "./resources/referrer-checker.py?name=sameReferrerPolicyNoReferrer" assert { type: "css"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/referrer-checker.py?name=remoteReferrerPolicyNoReferrer" assert { type: "css"}; + + test(t => { + assert_equals( + referrerSame.rules[0].style.content, '""', + "No referrer should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the no-referrer policy."); + + test(t => { + assert_equals( + referrerRemote.rules[0].style.content, '""', + "No referrer should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the no-referrer policy."); + +</script> +<script type="module" referrerpolicy="unsafe-url"> + import referrerSame from "./resources/referrer-checker.py?name=sameNoReferrerPolicyUnsafeUrl" assert { type: "css"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/referrer-checker.py?name=remoteNoReferrerPolicyUnsafeUrl" assert { type: "css"}; + + const originUrl = location.href; + + test(t => { + assert_equals( + referrerSame.rules[0].style.content, '"' + originUrl + '"', + "Referrer URL should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the unsafe-url referrer policy."); + + test(t => { + assert_equals( + referrerRemote.rules[0].style.content, '"' + originUrl + '"', + "Referrer URL should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the unsafe-url referrer policy."); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/relative-urls.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/relative-urls.html new file mode 100644 index 0000000000..22971d28d9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/relative-urls.html @@ -0,0 +1,18 @@ +<!doctype html> +<head> + <title>Test resolution of relative URL in CSS module</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <div id="target"></div> + <script type="module"> + import styleSheet from "./resources/load-relative-url.css" assert { type: "css"}; + test(() => { + const target = document.querySelector("#target"); + document.adoptedStyleSheets = [ styleSheet ]; + let backgroundStyle = window.getComputedStyle(target).background; + assert_not_equals(backgroundStyle.indexOf("css-module-assertions/resources/image.png"), -1); + }, "A relative URL in a CSS module should be resolved relative to the CSS file's URL, not the importing document's URL"); + </script> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/atImported.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/atImported.css new file mode 100644 index 0000000000..8629a846d1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/atImported.css @@ -0,0 +1,3 @@ +#test3b { + background-color: #FF0000; +}
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bad-import.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bad-import.css new file mode 100644 index 0000000000..a6e1a0f395 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bad-import.css @@ -0,0 +1,4 @@ +@import "atImported.css"; +#test3 { + background-color:#00FF00; +}
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/basic-large.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/basic-large.css new file mode 100644 index 0000000000..555ab70d2e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/basic-large.css @@ -0,0 +1,7 @@ +#test2 { + background-color:red; +} + +#test:before { + content: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/basic.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/basic.css new file mode 100644 index 0000000000..e034ed9ac7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/basic.css @@ -0,0 +1,3 @@ +#test { + background-color: #FF0000; +}
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bom-utf-16be.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bom-utf-16be.css Binary files differnew file mode 100644 index 0000000000..9e17902a1d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bom-utf-16be.css diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bom-utf-16le.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bom-utf-16le.css Binary files differnew file mode 100644 index 0000000000..ef90843d8e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bom-utf-16le.css diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bom-utf-8.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bom-utf-8.css new file mode 100644 index 0000000000..5cf81232b7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/bom-utf-8.css @@ -0,0 +1 @@ +div { background-color: blue; }
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/credentials-iframe.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/credentials-iframe.sub.html new file mode 100644 index 0000000000..cf1d621ce3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/credentials-iframe.sub.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<meta charset="utf-8"> + +<script type="module"> + import styleSheet from "./cross-origin.py?id=sameOriginNoneDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "css" }; + window.sameOriginNoneDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> +<script type="module" crossOrigin="anonymous"> + import styleSheet from "./cross-origin.py?id=sameOriginAnonymousDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "css" }; + window.sameOriginAnonymousDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> +<script type="module" crossOrigin="use-credentials"> + import styleSheet from "./cross-origin.py?id=sameOriginUseCredentialsDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "css" }; + window.sameOriginUseCredentialsDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> +<script type="module"> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/cross-origin.py?id=crossOriginNoneDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "css" }; + window.crossOriginNoneDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> +<script type="module" crossOrigin="anonymous"> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/cross-origin.py?id=crossOriginAnonymousDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "css" }; + window.crossOriginAnonymousDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> +<script type="module" crossOrigin="use-credentials"> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/cross-origin.py?id=crossOriginUseCredentialsDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "css" }; + window.crossOriginUseCredentialsDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> + +<script type="text/javascript"> +window.addEventListener('load', event => { + window.parent.postMessage({}, '*'); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/cross-origin.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/cross-origin.py new file mode 100644 index 0000000000..d744fc9514 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/cross-origin.py @@ -0,0 +1,17 @@ +def main(request, response): + + headers = [ + (b"Content-Type", b"text/css"), + (b"Access-Control-Allow-Origin", request.GET.first(b"origin")), + (b"Access-Control-Allow-Credentials", b"true") + ] + + milk = request.cookies.first(b"milk", None) + + # Send back + if milk is None: + return headers, u'.requestDidNotHaveCookies { }' + elif milk.value == b"1": + return headers, u'.requestHadCookies { }' + + return headers, u'.requestDidNotHaveCookies { }' diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/crossorigin-import-parse-error-with-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/crossorigin-import-parse-error-with-cors.sub.html new file mode 100644 index 0000000000..3afb8edeb1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/crossorigin-import-parse-error-with-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>css-module-assertions-import-cross-domain-parse-error-WithCORS</title> + <script src="../../module/crossorigin-common.js"></script> +</head> +<body> + <h1>css-module-assertions-import-cross-domain-parse-error-WithCORS</h1> + <script type="module" crossorigin> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/parse-error.css?pipe=header(Access-Control-Allow-Origin,*)" assert { type: "css" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported CSS rules count: ${styleSheet.rules.length}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/crossorigin-import-with-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/crossorigin-import-with-cors.sub.html new file mode 100644 index 0000000000..f8754c2a56 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/crossorigin-import-with-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>css-module-assertions-import-cross-domain-WithCORS</title> + <script src="../../module/crossorigin-common.js"></script> +</head> +<body> + <h1>css-module-assertions-import-cross-domain-WithCORS</h1> + <script type="module" crossorigin> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/basic.css?pipe=header(Access-Control-Allow-Origin,*)" assert { type: "css" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported CSS: ${styleSheet.rules[0].cssText}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/crossorigin-import-without-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/crossorigin-import-without-cors.sub.html new file mode 100644 index 0000000000..ab70b73573 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/crossorigin-import-without-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>css-module-assertions-import-cross-domain-NoCORS</title> + <script src="../../module/crossorigin-common.js"></script> +</head> +<body> + <h1>css-module-assertions-import-cross-domain-NoCORS</h1> + <script type="module" onerror="document._log.push('error');"> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/basic.css" assert { type: "css" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported CSS: ${styleSheet.rules[0].cssText}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/css-module-without-assertion-iframe.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/css-module-without-assertion-iframe.html new file mode 100644 index 0000000000..3d1be841ce --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/css-module-without-assertion-iframe.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<body> + <script> + window.onerror = function (errorMsg, url, lineNumber, column, errorObj) + { + document.window_onerror = errorObj.name; + return true; + }; + + function scriptErrorHandler(e) { + document.script_onerror = e; + } + </script> + <script type="module" onerror="scriptErrorHandler(event)"> + import v from "./basic.css"; + document.adoptedStyleSheets = [v]; + </script> + + <div id="test"> + I am a test div. + </div> +</body>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/integrity-matches.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/integrity-matches.js new file mode 100644 index 0000000000..95be445311 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/integrity-matches.js @@ -0,0 +1,2 @@ +import styleSheet from "./basic.css" assert { type: "css" }; +window.matchesLog.push(`integrity-matches,css:${styleSheet.cssRules[0].cssText}`); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/integrity-mismatches.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/integrity-mismatches.js new file mode 100644 index 0000000000..af6fc24de4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/integrity-mismatches.js @@ -0,0 +1,2 @@ +import styleSheet from "./basic.css" assert { type: "css" }; +window.matchesLog.push(`integrity-mismatches,css:${styleSheet.cssRules[0].cssText}`); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/load-error-events.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/load-error-events.py new file mode 100644 index 0000000000..b61b1ca834 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/load-error-events.py @@ -0,0 +1,14 @@ +import re + +def main(request, response): + headers = [(b"Content-Type", b"text/javascript")] + test = request.GET.first(b'test') + assert(re.match(b'^[a-zA-Z0-9_]+$', test)) + + status = 200 + if test.find(b'_load') >= 0: + content = b'import "./basic.css" assert { type: "css"}; %s.executed = true;' % test + else: + content = b'import "./not_found.css" assert { type: "css"}; %s.test.step(function() { assert_unreached("404 script should not be executed"); });' % test + + return status, headers, content diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/load-relative-url.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/load-relative-url.css new file mode 100644 index 0000000000..27f2987610 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/load-relative-url.css @@ -0,0 +1,5 @@ + +#target { + /* image.png doesn't exist, but that's irrelevant to the test. */ + background: url('./image.png'); +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/malformed.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/malformed.css new file mode 100644 index 0000000000..28819bfdf5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/malformed.css @@ -0,0 +1,7 @@ +#test4 } { + background-color: #FF0000; +} + +#test4b { + background-color: #00FF00; +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/parse-error.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/parse-error.css new file mode 100644 index 0000000000..2bee3ff996 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/parse-error.css @@ -0,0 +1,2 @@ +div /* Opening bracket skipped intentionally. */ } + diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/record-fetch.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/record-fetch.py new file mode 100644 index 0000000000..4928cb4acb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/record-fetch.py @@ -0,0 +1,20 @@ +def main(request, response): + try: + stash_key = request.GET.first(b"key") + action = request.GET.first(b"action") + + run_count = request.server.stash.take(stash_key) + if not run_count: + run_count = 0 + + if action == b"incCount": + request.server.stash.put(stash_key, run_count + 1) + response.headers.set(b"Content-Type", b"text/css") + response.content = b'#test { background-color: #FF0000; }' + elif action == b"getCount": + response.headers.set(b"Content-Type", b"text/json") + response.content = b'{"count": %d }' % run_count + else: + response.set_error(400, u"Invalid action") + except: + response.set_error(400, u"Not enough parameters") diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/referrer-checker.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/referrer-checker.py new file mode 100644 index 0000000000..c1eaed8e46 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/referrer-checker.py @@ -0,0 +1,7 @@ +def main(request, response): + referrer = request.headers.get(b"referer", b"") + response_headers = [(b"Content-Type", b"text/css"), + (b"Access-Control-Allow-Origin", b"*")] + # Put the referrer in a CSS rule that can be read by the importer through CSSOM + return (200, response_headers, + b'.referrer { content: "' + referrer + b'" }') diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/utf-8.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/utf-8.css new file mode 100644 index 0000000000..0a8b46656f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/utf-8.css @@ -0,0 +1,3 @@ +#test { + content: "śćążź"; +}
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/windows-1250.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/windows-1250.css new file mode 100644 index 0000000000..9beac4d618 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/windows-1250.css @@ -0,0 +1,3 @@ +#test { + content: "�湿�"; +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/worker-dynamic-import.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/worker-dynamic-import.sub.js new file mode 100644 index 0000000000..791bd7d3f9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/worker-dynamic-import.sub.js @@ -0,0 +1,3 @@ +import("./record-fetch.py?key={{GET[key]}}&action=incCount", { assert: { type: "css" } }) + .then(() => postMessage("LOADED")) + .catch(e => postMessage("NOT LOADED"));
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/worker.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/worker.sub.js new file mode 100644 index 0000000000..ffee312d21 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/resources/worker.sub.js @@ -0,0 +1,2 @@ +import "./record-fetch.py?key={{GET[key]}}&action=incCount" assert { type: "css" }; +postMessage("Unexpectedly loaded");
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/script-element-css-src.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/script-element-css-src.html new file mode 100644 index 0000000000..231d02db47 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module-assertions/script-element-css-src.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<title><script> with CSS src</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test that <script> doesn't load when the src is CSS."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, ["error"]); + })); +</script> +<script type="module" src="./resources/basic.css" onload="t.unreached_func('CSS src should fail to load')" onerror="log.push('error')"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/charset-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/charset-2.html new file mode 100644 index 0000000000..fb25b1ffb3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/charset-2.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset="windows-1250"> +<title>CSS modules: UTF-8 decoding</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script type="module"> + import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/utf-8.css" with { type: "css"}; + test(() => { + assert_equals(styleSheet.rules[0].style.content, "\"�湿�\""); + }, "CSS module should be loaded as utf-8 even though document's encoding is windows-1250"); +</script> +<script type="module"> + import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/windows-1250.css&ct=text/css%3Bcharset=windows-1250" with { type: "css"}; + test(() => { + assert_not_equals(styleSheet.rules[0].style.content, "\"�湿�\"", + 'Should be decoded as UTF-8'); + }, "CSS module should be loaded as utf-8 even if it is encoded in windows-1250 and served with a windows-1250 charset response header, and this document's encoding is windows-1250"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/charset-bom.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/charset-bom.html new file mode 100644 index 0000000000..113ae63ea4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/charset-bom.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<title>CSS Module scripts should ignore BOMs and always use UTF-8</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="module"> + import utf8BOMSheet from './resources/bom-utf-8.css' with { type: 'css' }; + test(function() { + assert_equals(utf8BOMSheet.rules[0].selectorText, 'div', 'No UTF-8 BOM expected in selector'); + }, 'UTF-8 BOM should be stripped when decoding JSON module script'); + + import utf16BEBOMSheet from './resources/bom-utf-16be.css' with { type: 'css' }; + test(function() { + assert_equals(utf16BEBOMSheet.rules[0].selectorText, '\ufffd\ufffd\ufffdd\ufffdi\ufffdv\ufffd \ufffd', 'Expected UTF-8 decoded selectorText with 0xfffd replacement characters'); + }, 'UTF-16BE BOM should be ignored, so CSS module should be UTF-8 decoded'); + + import utf16LEBOMSheet from './resources/bom-utf-16le.css' with { type: 'css' }; + test(function() { + assert_equals(utf16LEBOMSheet.rules[0].selectorText, '\ufffd\ufffdd\ufffdi\ufffdv\ufffd \ufffd', 'Expected UTF-8 decoded selectorText with 0xfffd replacement characters'); + }, 'UTF-16LE BOM should be ignored, so CSS module should be UTF-8 decoded'); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/charset.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/charset.html new file mode 100644 index 0000000000..e7010c2f57 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/charset.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>CSS modules: UTF-8 decoding</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script type="module" onerror="unreachable()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/utf-8.css&ct=text/css%3Bcharset=utf-8" with { type: "css"}; + test(() => { + assert_equals(styleSheet.rules[0].style.content, "\"śćążź\""); + }, "CSS module should be loaded as utf-8 when charset=utf8 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/utf-8.css&ct=text/css%3Bcharset=shift-jis" with { type: "css"}; + test(() => { + assert_equals(styleSheet.rules[0].style.content, "\"śćążź\""); + }, "CSS module should be loaded as utf-8 when charset=shift-jis is specified"); +</script> +<script type="module" onerror="unreachable()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/utf-8.css&ct=text/css%3Bcharset=windows-1252" with { type: "css"}; + test(() => { + assert_equals(styleSheet.rules[0].style.content, "\"śćążź\""); + }, "CSS module should be loaded as utf-8 when charset=windows-1252 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/utf-8.css&ct=text/css%3Bcharset=utf-7" with { type: "css"};; + test(() => { + assert_equals(styleSheet.rules[0].style.content, "\"śćążź\""); + }, "CSS module should be loaded as utf-8 when charset=utf-7 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/windows-1250.css&ct=text/css%3Bcharset=windows-1250" with { type: "css"}; + test(() => { + assert_not_equals(styleSheet.rules[0].style.content, "\"śćążź\"", + 'Should be decoded as UTF-8'); + }, "CSS module should be loaded as utf-8 even if it is encoded in windows-1250 and served with a windows-1250 charset response header"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/content-type-checking.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/content-type-checking.html new file mode 100644 index 0000000000..5be0d50c38 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/content-type-checking.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>CSS modules: Content-Type</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +function check(t, styleSheet) { + t.step(() => { + assert_equals(styleSheet.rules[0].cssText, "#test { background-color: rgb(255, 0, 0); }"); + t.done(); + }); +} +const t1 = async_test("text/css"); +const t2 = async_test("application/css"); +const t3 = async_test("text/html+css"); +const t4 = async_test("text/css;boundary=something"); +const t5 = async_test("text/css;foo=bar"); +</script> +<script type="module" onerror="t1.unreached_func()()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/basic.css&ct=text/css" with { type: "css"}; + check(t1, styleSheet); +</script> +<script type="module" onerror="t2.step_func_done()()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/basic.css&ct=application/css" with { type: "css"}; + t2.unreached_func("Should not have loaded with MIME type application/css")(); +</script> +<script type="module" onerror="t3.step_func_done()()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/basic.css&ct=text/html+css" with { type: "css"}; + t3.unreached_func("Should not have loaded with MIME type text/html+css")(); +</script> +<script type="module" onerror="t4.unreached_func()()"> + import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/basic.css&ct=text/css;boundary=something" with { type: "css"}; + check(t4, styleSheet); +</script> +<script type="module" onerror="t5.unreached_func()()"> +import styleSheet from "../serve-with-content-type.py?fn=css-module/resources/basic.css&ct=text/css;foo=bar" with { type: "css"}; +check(t5, styleSheet); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/cors-crossorigin-requests.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/cors-crossorigin-requests.html new file mode 100644 index 0000000000..e699ef927e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/cors-crossorigin-requests.html @@ -0,0 +1,33 @@ +<!doctype html> +<html> +<head> + <title>css-module-crossorigin</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <h1>css-module-crossorigin</h1> + <iframe id="import-WithCORS" src="resources/crossorigin-import-with-cors.sub.html"></iframe> + <iframe id="import-NoCORS" src="resources/crossorigin-import-without-cors.sub.html"></iframe> + <iframe id="import-parseerror-WithCors" src="resources/crossorigin-import-parse-error-with-cors.sub.html"></iframe> + <script> + + var tests = [ + { "obj": async_test("Imported CSS module, cross-origin with CORS"), "id": "import-WithCORS", "expected": "imported CSS: #test { background-color: rgb(255, 0, 0); }" }, + { "obj": async_test("Imported CSS module, cross-origin, missing CORS ACAO header"), "id": "import-NoCORS", "expected": "error" }, + { "obj": async_test("Imported CSS module with parse error, cross-origin, with CORS"), "id": "import-parseerror-WithCors", "expected": "imported CSS rules count: 0" }, + ]; + + window.addEventListener("load", function () { + tests.forEach(function (test) { + var target = document.getElementById(test.id); + test.obj.step(function () { + assert_equals(target.contentDocument._log, test.expected, "Unexpected _log value"); + }); + test.obj.done(); + }); + }); + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/credentials.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/credentials.sub.html new file mode 100644 index 0000000000..0da573dad2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/credentials.sub.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +document.cookie = 'milk=1'; + +const setCookiePromise = fetch( + 'http://{{domains[www2]}}:{{ports[http][0]}}/cookies/resources/set-cookie.py?name=milk&path=/html/semantics/scripting-1/the-script-element/css-module/', + { + mode: 'no-cors', + credentials: 'include', + }); + +const windowLoadPromise = new Promise(resolve => { + window.addEventListener('load', () => { + resolve(); + }); +}); + +promise_test(t => { + const iframe = document.createElement('iframe'); + + return Promise.all([setCookiePromise, windowLoadPromise]).then(() => { + const messagePromise = new Promise(resolve => { + window.addEventListener('message', event => { + resolve(); + }); + }); + + iframe.src = 'resources/credentials-iframe.sub.html'; + document.body.appendChild(iframe); + + return messagePromise; + }).then(() => { + const w = iframe.contentWindow; + + assert_equals(w.sameOriginNoneDescendant, true, + 'Descendant CSS modules should be loaded with the credentials when the crossOrigin attribute is not specified and the target is same-origin'); + assert_equals(w.sameOriginAnonymousDescendant, true, + 'Descendant CSS modules should be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is same-origin'); + assert_equals(w.sameOriginUseCredentialsDescendant, true, + 'Descendant CSS modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is same-origin'); + assert_equals(w.crossOriginNoneDescendant, false, + 'Descendant CSS modules should not be loaded with the credentials when the crossOrigin attribute is not specified and the target is cross-origin'); + assert_equals(w.crossOriginAnonymousDescendant, false, + 'Descendant CSS modules should not be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is cross-origin'); + assert_equals(w.crossOriginUseCredentialsDescendant, true, + 'Descendant CSS modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is cross-origin'); +}); +}, 'CSS Modules should be loaded with or without the credentials based on the same-origin-ness and the crossOrigin attribute'); +</script> +<body> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/css-module-worker-test.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/css-module-worker-test.html new file mode 100644 index 0000000000..7ff672da6a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/css-module-worker-test.html @@ -0,0 +1,54 @@ +<!doctype html> + +<head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/utils.js"></script> +</head> + +<body> + <script> + setup({allow_uncaught_exception: true}); + promise_test(function (test) { + const uuid = token(); + const worker = new Worker(`./resources/worker.sub.js?key=${uuid}`, { + type: "module" + }); + return new Promise((resolve, reject) => { + worker.addEventListener("error", resolve); + worker.addEventListener("message", reject); + }).then(async () => { + const fetchResponse = await fetch(`./resources/record-fetch.py?key=${uuid}&action=getCount`); + const fetchData = await fetchResponse.json(); + assert_equals(fetchData.count, 0, "Shouldn't have tried fetching CSS module in worker"); + }); + }, "A static import CSS Module within a web worker should not load and should not attempt to fetch the module."); + + promise_test(function (test) { + const uuid = token(); + const worker = new Worker(`./resources/worker-dynamic-import.sub.js?key=${uuid}`, { + type: "module" + }); + + return new Promise(resolve => { + worker.addEventListener("message", resolve); + }).then(async (event) => { + assert_equals(event.data, "NOT LOADED"); + const fetchResponse = await fetch(`./resources/record-fetch.py?key=${uuid}&action=getCount`); + const fetchData = await fetchResponse.json(); + assert_equals(fetchData.count, 0, "Shouldn't have tried fetching CSS module in worker"); + }); + }, "A dynamic import CSS Module within a web worker should not load and should not attempt to fetch the module."); + + promise_test(function (test) { + const worker = new Worker("./resources/basic.css", { + type: "module" + }); + return new Promise(resolve => { + worker.onerror = resolve; + }); + }, "An attempt to load a CSS module as a worker should fail."); + + </script> + +</body>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/import-css-module-basic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/import-css-module-basic.html new file mode 100644 index 0000000000..8e9b84691a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/import-css-module-basic.html @@ -0,0 +1,83 @@ +<!doctype html> +<head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <div id="test">I am a test div.</div> + <div id="test2">I am a test div.</div> + <div id="test3">I am a test div.</div> + <div id="test3b">I am a test div.</div> + <div id="test4">I am a test div.</div> + <div id="test4b">I am a test div.</div> + <script> + window.errorCount = 0; + window.onerror = (errorMsg, url, lineNumber, column, errorObj) => { + window.errorCount++; + }; + </script> + <script type="module" onerror="unreachable()"> + import sheet from "./resources/basic.css" with { type: "css" }; + test(() => { + document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]; + assert_equals(getComputedStyle(document.querySelector('#test')) + .backgroundColor, "rgb(255, 0, 0)", "CSS module import should succeed"); + }, "A CSS Module should load"); + </script> + <script type="module" onerror="unreachable()"> + import sheet from "./resources/basic-large.css" with { type: "css" }; + test(() => { + // This tests potential streaming compilation of modules in + // Chromium that is triggered only for large (32>KiB) files in older + // versions. + document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]; + assert_equals(getComputedStyle(document.querySelector('#test2')) + .backgroundColor, "rgb(255, 0, 0)", + "CSS module import should succeed"); + }, "A large CSS Module should load"); + </script> + <script type="module" onerror="unreachable()"> + import sheet from "./resources/bad-import.css" with { type: "css" }; + test(() => { + document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]; + assert_equals(window.errorCount, 0); + assert_equals(sheet.cssRules.length, 1, "Parser should skip @import rule"); + assert_equals(getComputedStyle(document.querySelector('#test3b')) + .backgroundColor, "rgba(0, 0, 0, 0)", + "CSS module @import should not succeed"); + assert_equals(getComputedStyle(document.querySelector('#test3')) + .backgroundColor, "rgb(0, 255, 0)", + "Rule after @import should still be applied"); + }, "An @import CSS Module should not load, but should not throw an exception"); + </script> + <script type="module" onerror="unreachable()"> + import sheet from "./resources/malformed.css" with { type: "css" }; + test(() => { + document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]; + assert_equals(window.errorCount, 0); + assert_equals(sheet.cssRules.length, 1, "Import of malformed CSS should succeed and rules after the parse error should still be parsed"); + assert_equals(getComputedStyle(document.querySelector('#test4')) + .backgroundColor, "rgba(0, 0, 0, 0)", + "Malformed CSS rule should not be applied"); + assert_equals(getComputedStyle(document.querySelector('#test4b')) + .backgroundColor, "rgb(0, 255, 0)", + "Parsing should recover and rules after malformed rules should be applied"); + }, "A parse error should not prevent subsequent rules from being included in a CSS module"); + </script> + <script type="module"> + promise_test(function (test) { + const iframe = document.createElement("iframe"); + iframe.src = "resources/css-module-without-attribute-iframe.html"; + return new Promise(resolve => { + iframe.onload = resolve; + document.body.appendChild(iframe); + }).then(event => { + assert_equals(iframe.contentDocument.window_onerror, undefined); + assert_equals(iframe.contentDocument.script_onerror.type, "error"); + assert_equals(getComputedStyle(iframe.contentDocument.querySelector('#test')) + .backgroundColor, "rgba(0, 0, 0, 0)", + "CSS module without type attribute should result in a fetch error"); + }); + }, "CSS module without type attribute should result in a fetch error"); + </script> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/import-css-module-dynamic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/import-css-module-dynamic.html new file mode 100644 index 0000000000..5774a31cb2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/import-css-module-dynamic.html @@ -0,0 +1,23 @@ +<!doctype html> + +<head> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> + +<body> + <script> + promise_test(async function (test) { + const css_module = await import("./resources/basic.css", { with: { type: "css" }}); + assert_true(css_module.default instanceof CSSStyleSheet); + assert_equals(css_module.default.cssRules[0].cssText, + "#test { background-color: rgb(255, 0, 0); }"); + }, "Load a CSS module with dynamic import()"); + + promise_test(function (test) { + return promise_rejects_js(test, TypeError, + import("./resources/basic.css"), + "Attempting to import() a CSS module without a type attribute should fail"); + }, "Ensure that loading a CSS module with dymnamic import() fails without a type attribute"); + </script> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/integrity.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/integrity.html new file mode 100644 index 0000000000..1dd0dad470 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/integrity.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title><script> integrity="" with CSS modules</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +window.matchesLog = []; +window.matchesEvents = []; + +window.mismatchesLog = []; +window.mismatchesEvents = []; +</script> +<script type="module" src="resources/integrity-matches.js" integrity="sha384-xvbfmg9iJFHqmCoOS4VNMCwnFPPxEoIlW1Ojzl+fgEd+Wf8Pyez+SMWue+KNovjA" onload="window.matchesEvents.push('load');" onerror="window.matchesEvents.push('error')"></script> +<script type="module" src="resources/integrity-mismatches.js" integrity="sha384-doesnotmatch" onload="window.mismatchesEvents.push('load');" onerror="window.mismatchesEvents.push('error')"></script> + +<script type="module"> +test(() => { + assert_array_equals(window.matchesLog, ["integrity-matches,css:#test { background-color: rgb(255, 0, 0); }"], "The module and its dependency must have executed"); + assert_array_equals(window.matchesEvents, ["load"], "The load event must have fired"); +}, "The integrity attribute must be verified on the top-level of a module loading a CSS module and allow it to execute when it matches"); + +test(() => { + assert_array_equals(window.mismatchesLog, [], "The module and its dependency must not have executed"); + assert_array_equals(window.mismatchesEvents, ["error"], "The error event must have fired"); +}, "The integrity attribute must be verified on the top-level of a module loading a CSS module and not allow it to execute when there's a mismatch"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/load-error-events.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/load-error-events.html new file mode 100644 index 0000000000..703a0734ff --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/load-error-events.html @@ -0,0 +1,67 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<head> +<title>load/error events for CSS modules</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/load-error-events-helpers.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +</head> +<script> + "use strict"; + + var test1_load = event_test('inline, 200, parser-inserted', false, false); + var test1_error = event_test('inline, 404, parser-inserted', false, true); + + var test2_load = event_test('src, 200, parser-inserted', true, false); + var test2_error = event_test('src, 404, parser-inserted', false, true); + + var test3_dynamic_load = event_test('src, 200, not parser-inserted', true, false); + var test3_dynamic_error = event_test('src, 404, not parser-inserted', false, true); + + var test4_dynamic_load = event_test('inline, 200, not parser-inserted', false, false); + var test4_dynamic_error = event_test('inline, 404, not parser-inserted', false, true); + + var script3_dynamic_load = document.createElement('script'); + script3_dynamic_load.setAttribute('type', 'module'); + script3_dynamic_load.onload = () => onLoad(test3_dynamic_load); + script3_dynamic_load.onerror = () => onError(test3_dynamic_load); + script3_dynamic_load.src = "./resources/load-error-events.py?test=test3_dynamic_load"; + document.head.appendChild(script3_dynamic_load); + + var script3_dynamic_error = document.createElement('script'); + script3_dynamic_error.setAttribute('type', 'module'); + script3_dynamic_error.onload = () => onLoad(test3_dynamic_error); + script3_dynamic_error.onerror = () => onError(test3_dynamic_error); + script3_dynamic_error.src = "./resources/load-error-events.py?test=test3_dynamic_error"; + document.head.appendChild(script3_dynamic_error); + + var script4_dynamic_load = document.createElement('script'); + script4_dynamic_load.setAttribute('type', 'module'); + script4_dynamic_load.onload = () => onLoad(test4_dynamic_load); + script4_dynamic_load.onerror = () => onError(test4_dynamic_load); + script4_dynamic_load.async = true; + script4_dynamic_load.appendChild(document.createTextNode(` + import "./resources/basic.css" with { type: "css" }; + onExecute(test4_dynamic_load);` + )); + document.head.appendChild(script4_dynamic_load); + + var script4_dynamic_error = document.createElement('script'); + script4_dynamic_error.setAttribute('type', 'module'); + script4_dynamic_error.onload = () => onLoad(test4_dynamic_error); + script4_dynamic_error.onerror = () => onError(test4_dynamic_error); + script4_dynamic_error.async = true; + script4_dynamic_error.appendChild(document.createTextNode(`import "./not_found.css" with { type: "css" };`)); + document.head.appendChild(script4_dynamic_error); +</script> +<script onload="onLoad(test1_load);" onerror="onError(test1_load);" type="module"> + import "./resources/basic.css" with { type: "css"}; + onExecute(test1_load); +</script> +<script onload="onLoad(test1_error);" onerror="onError(test1_error);" type="module"> + import "./not_found.css" with { type: "css"}; + onExecute(test1_error); +</script> +<script src="./resources/load-error-events.py?test=test2_load" onload="onLoad(test2_load);" onerror="onError(test2_load);" type="module"></script> +<script src="./resources/load-error-events.py?test=test2_error" onload="onLoad(test2_error);" onerror="onError(test2_error);" type="module"></script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/referrer-policies.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/referrer-policies.sub.html new file mode 100644 index 0000000000..a507ee52fc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/referrer-policies.sub.html @@ -0,0 +1,84 @@ +<!DOCTYPE html> +<html> +<head> +<title>Referrers with CSS module requests</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> + // "name" parameter is necessary for bypassing the module map. + import referrerSame from "./resources/referrer-checker.py?name=sameNoReferrerPolicy" with { type: "css"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module/resources/referrer-checker.py?name=remoteNoReferrerPolicy" with { type: "css"}; + + const origin = (new URL(location.href)).origin + "/"; + const originUrl = location.href; + + test(t => { + assert_equals( + referrerSame.rules[0].style.content, '"' + originUrl + '"', + "Referrer URL should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the default referrer policy."); + + test(t => { + assert_equals( + referrerRemote.rules[0].style.content, '"' + origin + '"', + "Referrer origin should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the default referrer policy."); +</script> +<script type="module" referrerpolicy="origin"> + import referrerSame from "./resources/referrer-checker.py?name=sameReferrerPolicyOrigin" with { type: "css"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module/resources/referrer-checker.py?name=remoteReferrerPolicyOrigin" with { type: "css"}; + + const origin = (new URL(location.href)).origin + "/"; + + test(t => { + assert_equals( + referrerSame.rules[0].style.content, '"' + origin + '"', + "Referrer origin should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the origin policy."); + + test(t => { + assert_equals( + referrerRemote.rules[0].style.content, '"' + origin + '"', + "Referrer origin should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the origin policy."); + +</script> +<script type="module" referrerpolicy="no-referrer"> + import referrerSame from "./resources/referrer-checker.py?name=sameReferrerPolicyNoReferrer" with { type: "css"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module/resources/referrer-checker.py?name=remoteReferrerPolicyNoReferrer" with { type: "css"}; + + test(t => { + assert_equals( + referrerSame.rules[0].style.content, '""', + "No referrer should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the no-referrer policy."); + + test(t => { + assert_equals( + referrerRemote.rules[0].style.content, '""', + "No referrer should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the no-referrer policy."); + +</script> +<script type="module" referrerpolicy="unsafe-url"> + import referrerSame from "./resources/referrer-checker.py?name=sameNoReferrerPolicyUnsafeUrl" with { type: "css"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module/resources/referrer-checker.py?name=remoteNoReferrerPolicyUnsafeUrl" with { type: "css"}; + + const originUrl = location.href; + + test(t => { + assert_equals( + referrerSame.rules[0].style.content, '"' + originUrl + '"', + "Referrer URL should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the unsafe-url referrer policy."); + + test(t => { + assert_equals( + referrerRemote.rules[0].style.content, '"' + originUrl + '"', + "Referrer URL should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the unsafe-url referrer policy."); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/relative-urls.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/relative-urls.html new file mode 100644 index 0000000000..0aafb9aae5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/relative-urls.html @@ -0,0 +1,18 @@ +<!doctype html> +<head> + <title>Test resolution of relative URL in CSS module</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <div id="target"></div> + <script type="module"> + import styleSheet from "./resources/load-relative-url.css" with { type: "css"}; + test(() => { + const target = document.querySelector("#target"); + document.adoptedStyleSheets = [ styleSheet ]; + let backgroundStyle = window.getComputedStyle(target).background; + assert_not_equals(backgroundStyle.indexOf("css-module/resources/image.png"), -1); + }, "A relative URL in a CSS module should be resolved relative to the CSS file's URL, not the importing document's URL"); + </script> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/atImported.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/atImported.css new file mode 100644 index 0000000000..8629a846d1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/atImported.css @@ -0,0 +1,3 @@ +#test3b { + background-color: #FF0000; +}
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bad-import.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bad-import.css new file mode 100644 index 0000000000..a6e1a0f395 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bad-import.css @@ -0,0 +1,4 @@ +@import "atImported.css"; +#test3 { + background-color:#00FF00; +}
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/basic-large.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/basic-large.css new file mode 100644 index 0000000000..555ab70d2e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/basic-large.css @@ -0,0 +1,7 @@ +#test2 { + background-color:red; +} + +#test:before { + content: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/basic.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/basic.css new file mode 100644 index 0000000000..e034ed9ac7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/basic.css @@ -0,0 +1,3 @@ +#test { + background-color: #FF0000; +}
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bom-utf-16be.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bom-utf-16be.css Binary files differnew file mode 100644 index 0000000000..9e17902a1d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bom-utf-16be.css diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bom-utf-16le.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bom-utf-16le.css Binary files differnew file mode 100644 index 0000000000..ef90843d8e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bom-utf-16le.css diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bom-utf-8.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bom-utf-8.css new file mode 100644 index 0000000000..5cf81232b7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/bom-utf-8.css @@ -0,0 +1 @@ +div { background-color: blue; }
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/credentials-iframe.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/credentials-iframe.sub.html new file mode 100644 index 0000000000..c71b0e4bb7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/credentials-iframe.sub.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<meta charset="utf-8"> + +<script type="module"> + import styleSheet from "./cross-origin.py?id=sameOriginNoneDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "css" }; + window.sameOriginNoneDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> +<script type="module" crossOrigin="anonymous"> + import styleSheet from "./cross-origin.py?id=sameOriginAnonymousDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "css" }; + window.sameOriginAnonymousDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> +<script type="module" crossOrigin="use-credentials"> + import styleSheet from "./cross-origin.py?id=sameOriginUseCredentialsDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "css" }; + window.sameOriginUseCredentialsDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> +<script type="module"> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module/resources/cross-origin.py?id=crossOriginNoneDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "css" }; + window.crossOriginNoneDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> +<script type="module" crossOrigin="anonymous"> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module/resources/cross-origin.py?id=crossOriginAnonymousDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "css" }; + window.crossOriginAnonymousDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> +<script type="module" crossOrigin="use-credentials"> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module/resources/cross-origin.py?id=crossOriginUseCredentialsDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "css" }; + window.crossOriginUseCredentialsDescendant = (styleSheet.cssRules[0].cssText.indexOf(".requestHadCookies") !== -1); +</script> + +<script type="text/javascript"> +window.addEventListener('load', event => { + window.parent.postMessage({}, '*'); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/cross-origin.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/cross-origin.py new file mode 100644 index 0000000000..d744fc9514 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/cross-origin.py @@ -0,0 +1,17 @@ +def main(request, response): + + headers = [ + (b"Content-Type", b"text/css"), + (b"Access-Control-Allow-Origin", request.GET.first(b"origin")), + (b"Access-Control-Allow-Credentials", b"true") + ] + + milk = request.cookies.first(b"milk", None) + + # Send back + if milk is None: + return headers, u'.requestDidNotHaveCookies { }' + elif milk.value == b"1": + return headers, u'.requestHadCookies { }' + + return headers, u'.requestDidNotHaveCookies { }' diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/crossorigin-import-parse-error-with-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/crossorigin-import-parse-error-with-cors.sub.html new file mode 100644 index 0000000000..59b4afa721 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/crossorigin-import-parse-error-with-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>css-module-import-cross-domain-parse-error-WithCORS</title> + <script src="../../module/crossorigin-common.js"></script> +</head> +<body> + <h1>css-module-import-cross-domain-parse-error-WithCORS</h1> + <script type="module" crossorigin> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module/resources/parse-error.css?pipe=header(Access-Control-Allow-Origin,*)" with { type: "css" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported CSS rules count: ${styleSheet.rules.length}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/crossorigin-import-with-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/crossorigin-import-with-cors.sub.html new file mode 100644 index 0000000000..2a383d8be9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/crossorigin-import-with-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>css-module-import-cross-domain-WithCORS</title> + <script src="../../module/crossorigin-common.js"></script> +</head> +<body> + <h1>css-module-import-cross-domain-WithCORS</h1> + <script type="module" crossorigin> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module/resources/basic.css?pipe=header(Access-Control-Allow-Origin,*)" with { type: "css" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported CSS: ${styleSheet.rules[0].cssText}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/crossorigin-import-without-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/crossorigin-import-without-cors.sub.html new file mode 100644 index 0000000000..256a76a1d9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/crossorigin-import-without-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>css-module-import-cross-domain-NoCORS</title> + <script src="../../module/crossorigin-common.js"></script> +</head> +<body> + <h1>css-module-import-cross-domain-NoCORS</h1> + <script type="module" onerror="document._log.push('error');"> + import styleSheet from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/css-module/resources/basic.css" with { type: "css" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported CSS: ${styleSheet.rules[0].cssText}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/css-module-without-attribute-iframe.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/css-module-without-attribute-iframe.html new file mode 100644 index 0000000000..3d1be841ce --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/css-module-without-attribute-iframe.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<body> + <script> + window.onerror = function (errorMsg, url, lineNumber, column, errorObj) + { + document.window_onerror = errorObj.name; + return true; + }; + + function scriptErrorHandler(e) { + document.script_onerror = e; + } + </script> + <script type="module" onerror="scriptErrorHandler(event)"> + import v from "./basic.css"; + document.adoptedStyleSheets = [v]; + </script> + + <div id="test"> + I am a test div. + </div> +</body>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/integrity-matches.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/integrity-matches.js new file mode 100644 index 0000000000..4bd004ce96 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/integrity-matches.js @@ -0,0 +1,2 @@ +import styleSheet from "./basic.css" with { type: "css" }; +window.matchesLog.push(`integrity-matches,css:${styleSheet.cssRules[0].cssText}`); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/integrity-mismatches.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/integrity-mismatches.js new file mode 100644 index 0000000000..7f3bf54762 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/integrity-mismatches.js @@ -0,0 +1,2 @@ +import styleSheet from "./basic.css" with { type: "css" }; +window.matchesLog.push(`integrity-mismatches,css:${styleSheet.cssRules[0].cssText}`); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/load-error-events.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/load-error-events.py new file mode 100644 index 0000000000..490bdc42aa --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/load-error-events.py @@ -0,0 +1,14 @@ +import re + +def main(request, response): + headers = [(b"Content-Type", b"text/javascript")] + test = request.GET.first(b'test') + assert(re.match(b'^[a-zA-Z0-9_]+$', test)) + + status = 200 + if test.find(b'_load') >= 0: + content = b'import "./basic.css" with { type: "css"}; %s.executed = true;' % test + else: + content = b'import "./not_found.css" with { type: "css"}; %s.test.step(function() { assert_unreached("404 script should not be executed"); });' % test + + return status, headers, content diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/load-relative-url.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/load-relative-url.css new file mode 100644 index 0000000000..27f2987610 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/load-relative-url.css @@ -0,0 +1,5 @@ + +#target { + /* image.png doesn't exist, but that's irrelevant to the test. */ + background: url('./image.png'); +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/malformed.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/malformed.css new file mode 100644 index 0000000000..28819bfdf5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/malformed.css @@ -0,0 +1,7 @@ +#test4 } { + background-color: #FF0000; +} + +#test4b { + background-color: #00FF00; +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/parse-error.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/parse-error.css new file mode 100644 index 0000000000..2bee3ff996 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/parse-error.css @@ -0,0 +1,2 @@ +div /* Opening bracket skipped intentionally. */ } + diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/record-fetch.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/record-fetch.py new file mode 100644 index 0000000000..4928cb4acb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/record-fetch.py @@ -0,0 +1,20 @@ +def main(request, response): + try: + stash_key = request.GET.first(b"key") + action = request.GET.first(b"action") + + run_count = request.server.stash.take(stash_key) + if not run_count: + run_count = 0 + + if action == b"incCount": + request.server.stash.put(stash_key, run_count + 1) + response.headers.set(b"Content-Type", b"text/css") + response.content = b'#test { background-color: #FF0000; }' + elif action == b"getCount": + response.headers.set(b"Content-Type", b"text/json") + response.content = b'{"count": %d }' % run_count + else: + response.set_error(400, u"Invalid action") + except: + response.set_error(400, u"Not enough parameters") diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/referrer-checker.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/referrer-checker.py new file mode 100644 index 0000000000..c1eaed8e46 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/referrer-checker.py @@ -0,0 +1,7 @@ +def main(request, response): + referrer = request.headers.get(b"referer", b"") + response_headers = [(b"Content-Type", b"text/css"), + (b"Access-Control-Allow-Origin", b"*")] + # Put the referrer in a CSS rule that can be read by the importer through CSSOM + return (200, response_headers, + b'.referrer { content: "' + referrer + b'" }') diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/utf-8.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/utf-8.css new file mode 100644 index 0000000000..0a8b46656f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/utf-8.css @@ -0,0 +1,3 @@ +#test { + content: "śćążź"; +}
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/windows-1250.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/windows-1250.css new file mode 100644 index 0000000000..9beac4d618 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/windows-1250.css @@ -0,0 +1,3 @@ +#test { + content: "�湿�"; +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/worker-dynamic-import.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/worker-dynamic-import.sub.js new file mode 100644 index 0000000000..30dc8cde85 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/worker-dynamic-import.sub.js @@ -0,0 +1,3 @@ +import("./record-fetch.py?key={{GET[key]}}&action=incCount", { with: { type: "css" } }) + .then(() => postMessage("LOADED")) + .catch(e => postMessage("NOT LOADED"));
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/worker.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/worker.sub.js new file mode 100644 index 0000000000..dc85c13ed9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/resources/worker.sub.js @@ -0,0 +1,2 @@ +import "./record-fetch.py?key={{GET[key]}}&action=incCount" with { type: "css" }; +postMessage("Unexpectedly loaded");
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/script-element-css-src.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/script-element-css-src.html new file mode 100644 index 0000000000..231d02db47 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/css-module/script-element-css-src.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<title><script> with CSS src</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test that <script> doesn't load when the src is CSS."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, ["error"]); + })); +</script> +<script type="module" src="./resources/basic.css" onload="t.unreached_func('CSS src should fail to load')" onerror="log.push('error')"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/data-url.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/data-url.html new file mode 100644 index 0000000000..6fad505271 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/data-url.html @@ -0,0 +1,32 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Test data URL and scripts errors</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> + setup({allow_uncaught_exception:true}); + async_test(function(t) { + var counter = 1 + window.onerror = t.step_func((message, url, lineno, colno, e) => { + // Test that error is not muted as data URLs have a response type of "default" + // and errors should only be muted if the response type is "opaque" or "opaqueredirect" + assert_not_equals(message, "Script error.") + assert_not_equals(url, null); + assert_not_equals(url, ""); + assert_equals(typeof lineno, "number"); + assert_not_equals(lineno, 0); + assert_equals(typeof colno, "number"); + assert_not_equals(colno, 0); + assert_equals(typeof e, "number") + assert_equals(e, counter) + if (counter == 3) { + t.done() + } + counter++ + }); + }); +</script> +<script src="data:,throw 1"></script> +<script src="data:,throw 2" crossorigin></script> +<script src="data:,throw 3" crossorigin=use-credentials></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/README.md b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/README.md new file mode 100644 index 0000000000..ac5c91c9a2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/README.md @@ -0,0 +1,7 @@ +The tests in this directory is intended for Chromium's DeferAllScript +experiment https://crbug.com/1339112, containing scenarios that would be +affected by DeferAllScript, to monitor the behavior on Chromium and other +browsers. + +The same set of expectations (when async/defer scripts are evaluated) should +already be covered somewhere in WPT. diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/async-script-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/async-script-2.html new file mode 100644 index 0000000000..f7377d847a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/async-script-2.html @@ -0,0 +1,40 @@ +<!doctype html> +<title>Async Script Execution Order</title> +<html> +<head> + <meta charset="utf-8"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="resources/helper.js"></script> +</head> +<body> + <script> + setup({single_test: true}); + function finish() { + assert_array_equals( + window.result, + ["Inline1", "Sync1", "Async1", "Sync2", "EndOfBody", + "DOMContentLoaded"], + "Execution order"); + // Chromium's force-defer order would be: + // ["EndOfBody", "Inline1", "Sync1", "Sync2", + // "DOMContentLoaded", "Async1"] + // + // If we delay async script e.g. after DOMContentLoaded, + // the order would be: + // ["Inline1", "Sync1", "Sync2", "EndOfBody", + // "DOMContentLoaded", "Async1"] + done(); + } + logScript("Inline1"); + window.addEventListener("load", finish); + </script> + <script src="resources/sync-script-1.js"></script> + <!-- To test the async script loaded before force-deferred scripts + should be evaluated after the force-deferred scripts + in Chromium's force-defer order. --> + <script src="resources/async-script-1.js?pipe=trickle(d1)" async></script> + <script src="resources/sync-script-2.js?pipe=trickle(d2)"></script> + <pre id="bodyend">End</pre> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/async-script.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/async-script.html new file mode 100644 index 0000000000..90f657679f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/async-script.html @@ -0,0 +1,22 @@ +<!doctype html> +<title>Async Script Execution Order</title> +<html> +<head> + <meta charset="utf-8"> + <meta name=variant content="?default"> + <meta name=variant content="?reload"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="resources/helper.js"></script> +</head> +<body> + <script> + let child_path = 'support/async-script.html'; + if (location.search == '?reload') { + child_path += '?reload'; + } + const child_window = window.open(child_path); + fetch_tests_from_window(child_window); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/defer-script-xml.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/defer-script-xml.xhtml new file mode 100644 index 0000000000..9d02ff39f5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/defer-script-xml.xhtml @@ -0,0 +1,40 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Defer Script Execution Order</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="resources/helper.js"></script> +</head> +<body> + <div id="scriptlog"/> + <input id="testElement"/> + <script> + setup({single_test: true}); + function finish() { + assert_array_equals( + window.result, + ["Inline1", "Sync1", "Inline2", "Sync2", "EndOfBody", + "Defer1", "Defer2", "DOMContentLoaded"], + "Execution order"); + // Chromium order is (due to https://crbug.com/874749): + // ["Inline1", "Sync1", "Defer1", "Inline2", "Defer2", "Sync2", + // "EndOfBody", "DOMContentLoaded"] + done(); + } + logScript("Inline1"); + window.addEventListener("load", finish); + </script> + + <script src="resources/sync-script-1.js"></script> + <script src="resources/defer-script-1.js" defer="defer"></script> + <script> + logScript("Inline2"); + </script> + <script src="resources/defer-script-2.js" defer="defer"></script> + <script src="resources/sync-script-2.js"></script> + <pre id="bodyend">End</pre> +</body> +</html> + diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/defer-script.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/defer-script.html new file mode 100644 index 0000000000..62c3a74014 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/defer-script.html @@ -0,0 +1,37 @@ +<!doctype html> +<title>Defer Script Execution Order</title> +<html> +<head> + <meta charset="utf-8"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="resources/helper.js"></script> +</head> +<body> + <script> + setup({single_test: true}); + function finish() { + assert_array_equals( + window.result, + ["Inline1", "Sync1", "Inline2", "Sync2", "EndOfBody", + "Defer1", "Defer2", "DOMContentLoaded"], + "Execution order"); + // Chromium's force defer order would be: + // ["EndOfBody", "Inline1", "Sync1", "Inline2", "Sync2", + // "Defer1", "Defer2", "DOMContentLoaded"] + done(); + } + logScript("Inline1"); + window.addEventListener("load", finish); + </script> + + <script src="resources/sync-script-1.js"></script> + <script src="resources/defer-script-1.js" defer></script> + <script> + logScript("Inline2"); + </script> + <script src="resources/defer-script-2.js" defer></script> + <script src="resources/sync-script-2.js"></script> + <pre id="bodyend">End</pre> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/document-write.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/document-write.html new file mode 100644 index 0000000000..63e251bae5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/document-write.html @@ -0,0 +1,67 @@ +<!doctype html> +<title>DeferAllScript: document.write()</title> +<html> +<head> + <meta charset="utf-8"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + const t1 = async_test("document.write()"); + const t2 = async_test("document.write(),close()"); + const t3 = async_test("document.open(),write()"); + const t4 = async_test("document.open(),write(),close()"); + function finish() { + const expected = ["Inline1", "Sync2", "Async1", "Sync1", + "EndOfBody", "DOMContentLoaded", "WindowLoad"]; + t1.step_func_done(() => { + assert_array_equals( + document.getElementById("document-write").contentWindow.result, + expected, + "Execution order"); + })(); + + t2.step_func_done(() => { + assert_array_equals( + document.getElementById("document-write-close").contentWindow.result, + expected, + "Execution order"); + })(); + + t3.step_func_done(() => { + assert_array_equals( + document.getElementById("document-open-write").contentWindow.result, + expected, + "Execution order"); + })(); + + t4.step_func_done(() => { + assert_array_equals( + document.getElementById( + "document-open-write-close").contentWindow.result, + expected, + "Execution order"); + })(); + // For cases where documents are kept open, call `document.close()` here + // to finish the test harness. + for (const iframe of document.querySelectorAll("iframe")) { + iframe.contentDocument.close(); + } + } + + // For cases where documents are kept open (that should never occur in + // non-intervention cases), schedule `finish()` because Window load events + // might be not fired. + setTimeout(finish, 5000); + </script> +</head> +<body onload="finish()"> +<iframe id="document-write" + src="resources/document-write-iframe.sub.html?script=document-write.js"></iframe> +<iframe id="document-write-close" + src="resources/document-write-iframe.sub.html?script=document-write-close.js"></iframe> +<iframe id="document-open-write" + src="resources/document-write-iframe.sub.html?script=document-open-write.js"></iframe> +<iframe id="document-open-write-close" + src="resources/document-write-iframe.sub.html?script=document-open-write-close.js"></iframe> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/async-script-1.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/async-script-1.js new file mode 100644 index 0000000000..267f324aa6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/async-script-1.js @@ -0,0 +1 @@ +logScript("Async1"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/defer-script-1.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/defer-script-1.js new file mode 100644 index 0000000000..1a0524f4fb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/defer-script-1.js @@ -0,0 +1 @@ +logScript("Defer1"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/defer-script-2.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/defer-script-2.js new file mode 100644 index 0000000000..d644e37f18 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/defer-script-2.js @@ -0,0 +1 @@ +logScript("Defer2"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write-close.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write-close.js new file mode 100644 index 0000000000..80703d5c0e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write-close.js @@ -0,0 +1,3 @@ +document.open(); +document.write(`<script src="sync-script-2.js"></script>`); +document.close(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write.js new file mode 100644 index 0000000000..178c374df6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-open-write.js @@ -0,0 +1,2 @@ +document.open(); +document.write(`<script src="sync-script-2.js"></script>`); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-close.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-close.js new file mode 100644 index 0000000000..7cdde0d78f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-close.js @@ -0,0 +1,2 @@ +document.write(`<script src="sync-script-2.js"></script>`); +document.close(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-iframe.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-iframe.sub.html new file mode 100644 index 0000000000..e3022e3bf1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write-iframe.sub.html @@ -0,0 +1,14 @@ +<!doctype html> +<html> +<body> +<script src="helper.js"></script> +<script> +logScript("Inline1"); +window.addEventListener("load", () => logScript("WindowLoad")); +</script> +<script src="{{GET[script]}}?pipe=trickle(d1)"></script> +<script src="async-script-1.js" async></script> +<script src="sync-script-1.js?pipe=trickle(d2)"></script> +<pre id="bodyend">End</pre> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write.js new file mode 100644 index 0000000000..413a9bc621 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/document-write.js @@ -0,0 +1 @@ +document.write(`<script src="sync-script-2.js"></script>`); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/helper.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/helper.js new file mode 100644 index 0000000000..89c6d1e828 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/helper.js @@ -0,0 +1,17 @@ +window.result = []; +function log(msg) { + window.result.push(msg); +} +function checkIfReachedBodyEnd() { + const endelement = document.getElementById("bodyend"); + // `<pre id="bodyend">End</pre>` is needed at the end of HTML. + if (endelement && endelement.textContent === "End") { + log("EndOfBody"); + endelement.textContent = "Detected"; + } +} +function logScript(msg) { + checkIfReachedBodyEnd(); + log(msg); +} +document.addEventListener("DOMContentLoaded", function() { logScript("DOMContentLoaded"); }); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/sync-script-1.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/sync-script-1.js new file mode 100644 index 0000000000..726b56346e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/sync-script-1.js @@ -0,0 +1 @@ +logScript("Sync1"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/sync-script-2.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/sync-script-2.js new file mode 100644 index 0000000000..ba2edfbf27 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/resources/sync-script-2.js @@ -0,0 +1 @@ +logScript("Sync2"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/support/async-script.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/support/async-script.html new file mode 100644 index 0000000000..d513bafe4f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer-script/support/async-script.html @@ -0,0 +1,44 @@ +<!doctype html> +<title>Child Async Script Execution Order</title> +<html> + +<head> + <meta charset="utf-8"> + <script src="/resources/testharness.js"></script> + <script src="../resources/helper.js"></script> +</head> + +<body> + <script> + const reload_key = 'run-after-reload'; + if (location.search == '?reload' && !window.localStorage.getItem(reload_key)) { + window.localStorage.setItem(reload_key, true); + location.reload(); + } else { + window.localStorage.clear(); + test(); + } + + function test() { + setup({ single_test: true }); + function finish() { + assert_array_equals( + window.result, + ["Inline1", "Sync1", "EndOfBody", "DOMContentLoaded", "Async1"], + "Execution order"); + // Chromium's force-defer order would be: + // ["EndOfBody", "Inline1", "Sync1", "DOMContentLoaded", "Async1"] + done(); + } + logScript("Inline1"); + window.addEventListener("load", finish); + } + </script> + <script src="../resources/sync-script-1.js"></script> + <!-- Delays are added to make DOMContentLoaded be fired before + async script load completion --> + <script src="../resources/async-script-1.js?pipe=trickle(d1)" async></script> + <pre id="bodyend">End</pre> +</body> + +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer.js new file mode 100644 index 0000000000..c4449ca7c8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/defer.js @@ -0,0 +1,4 @@ +t.step(() => { + assert_equals(script_run_status, "deferred", "the script run status"); +}); +t.done(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/emptyish-script-elements.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/emptyish-script-elements.html new file mode 100644 index 0000000000..37f4a87c95 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/emptyish-script-elements.html @@ -0,0 +1,75 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Treatment of various empty-ish script elements</title> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#already-started"> +<link rel="help" href="https://github.com/whatwg/html/issues/3419"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script id="no-children"></script> +<script id="whitespace-child"> </script> + +<script id="gets-a-no-text-child"></script> +<script id="gets-an-empty-text-child"></script> +<script id="gets-a-text-child"></script> +<script id="gets-a-comment-child"></script> +<script id="gets-a-text-descendant"></script> + +<script> +"use strict"; + +test(() => { + const el = document.querySelector("#no-children"); + el.appendChild(document.createTextNode("window.noChildrenExecuted = true;")); + assert_true(window.noChildrenExecuted); +}, "A script with no children bails early, before setting already-started, so can be executed when adding text"); + +test(() => { + const el = document.querySelector("#whitespace-child"); + el.appendChild(document.createTextNode("window.whitespaceChildExecuted = true;")); + assert_equals(window.whitespaceChildExecuted, undefined); +}, "A script with a whitespace child executes, setting already-started, so adding text is a no-op"); + +test(() => { + const el = document.querySelector("#gets-a-no-text-child"); + el.appendChild(document.createElement("span")); + el.appendChild(document.createTextNode("window.getsANoTextChildExecuted = true;")); + assert_true(window.getsANoTextChildExecuted); +}, "A script with an empty element inserted bails early, before setting already-started, so can be executed when adding text"); + +test(() => { + const el = document.querySelector("#gets-an-empty-text-child"); + el.appendChild(document.createTextNode("")); + el.appendChild(document.createTextNode("window.getsAnEmptyTextChildExecuted = true;")); + assert_true(window.getsAnEmptyTextChildExecuted); +}, "A script with an empty text node inserted bails early, before setting already-started, so can be executed when adding text"); + +test(() => { + const el = document.querySelector("#gets-a-text-child"); + el.appendChild(document.createTextNode("window.getsATextChildExecuted1 = true;")); + el.appendChild(document.createTextNode("window.getsATextChildExecuted2 = true;")); + assert_true(window.getsATextChildExecuted1); + assert_equals(window.getsATextChildExecuted2, undefined); +}, "A script with a text child inserted executes, setting already-started, so adding text is a no-op"); + +test(() => { + const el = document.querySelector("#gets-a-comment-child"); + el.appendChild(document.createComment("window.getsACommentChild1 = true;")); + el.appendChild(document.createTextNode("window.getsACommentChild2 = true;")); + assert_equals(window.getsACommentChild1, undefined); + assert_true(window.getsACommentChild2); +}, "A script with a comment child inserted bails early, before setting already-started, so can be executed when adding text"); + +test(() => { + const el = document.querySelector("#gets-a-text-descendant"); + const child = document.createElement("span"); + child.appendChild(document.createTextNode("window.getsATextDescendantExecuted1 = true;")); + el.appendChild(child); + el.appendChild(document.createTextNode("window.getsATextDescendantExecuted2 = true;")); + assert_equals(window.getsATextDescendantExecuted1, undefined); + assert_true(window.getsATextDescendantExecuted2); +}, "A script with an element containing text inserted bails early, before setting already-started, so can be executed when adding text"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/001.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/001.html new file mode 100644 index 0000000000..3f54f764f9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/001.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: inline in markup </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1');</script> + <script>log('inline script #2');</script> + + <script type="text/javascript"> + + var t = async_test() + + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'inline script #2' ]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/002.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/002.html new file mode 100644 index 0000000000..df7ca95799 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/002.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: external in markup </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script src="scripts/include-1.js"></script> + <script src="scripts/include-2.js"></script> + + <script type="text/javascript"> + + var t = async_test() + + + function test() { + assert_array_equals(eventOrder, ['external script #1', 'external script #2' ]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/003.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/003.html new file mode 100644 index 0000000000..9c23b7e715 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/003.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: inline+external in markup </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1')</script> + <script src="scripts/include-2.js"></script> + + <script type="text/javascript"> + + var t = async_test() + + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'external script #2' ]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/004.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/004.html new file mode 100644 index 0000000000..a21dd388eb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/004.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: external+inline in markup </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script src="scripts/include-1.js"></script> + <script>log('inline script #2')</script> + + <script type="text/javascript"> + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['external script #1', 'inline script #2' ]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/005.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/005.html new file mode 100644 index 0000000000..ff4a66d25e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/005.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write inline in markup </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.write( '<script>log(\'doc write script\')<\/script>' ); + log('end script #1'); + </script> + + <script type="text/javascript"> + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'doc write script', 'end script #1' ]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/006.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/006.html new file mode 100644 index 0000000000..b8785a60c6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/006.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write inline - multiple</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.write( '<script>log(\'doc write script 1\')<\/script>' ); + document.write( '<script>log(\'doc write script 2\')<\/script>' ); + eval('log(\'eval 1\')'); + document.write( '<script>log(\'doc write script 3\')<\/script>' ); + log('end script #1'); + </script> + + <script type="text/javascript"> + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'doc write script 1','doc write script 2', 'eval 1','doc write script 3', 'end script #1' ]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/007.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/007.html new file mode 100644 index 0000000000..edd9920757 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/007.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write external</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' ); + log('end script #1'); + </script> + + <script type="text/javascript"> + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1' ]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/008.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/008.html new file mode 100644 index 0000000000..dce763987f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/008.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write external - multiple</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' ); + document.write( '<script src="scripts/include-2.js">log(\'ignore this\')<\/script>' ); + log('end script #1'); + </script> + + <script type="text/javascript"> + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1', 'external script #2' ]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/009.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/009.html new file mode 100644 index 0000000000..9d5b2de081 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/009.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write external - multiple with doc.write</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' ); + document.write( '<script src="scripts/include-3.js">log(\'ignore this\')<\/script>' ); + document.write( '<script src="scripts/include-2.js">log(\'ignore this\')<\/script>' ); + log('end script #1'); + </script> + + <script type="text/javascript"> + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1', 'external script before doc write', 'document.write external script', 'external script after doc write', 'external script #2' ]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/010.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/010.html new file mode 100644 index 0000000000..69a462c301 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/010.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write external + inline - multiple with doc.write</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' ); + document.write( '<script>log(\'inline with doc.write #1\')<\/script>' ); + document.write( '<script src="scripts/include-2.js">log(\'ignore this\')<\/script>' ); + log('end script #1'); + </script> + + <script type="text/javascript"> + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1', 'inline with doc.write #1', 'external script #2']); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/011.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/011.html new file mode 100644 index 0000000000..33024ba59e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/011.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write external + inline - multiple with doc.write + subsequent markup</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' ); + document.write( '<script>log(\'inline with doc.write #1\')<\/script>' ); + document.write( '<script src="scripts/include-2.js">log(\'ignore this\')<\/script>' ); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1', 'inline with doc.write #1', 'external script #2', 'inline script #2']); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/012.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/012.html new file mode 100644 index 0000000000..01c9293b20 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/012.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write external and onload events </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.write( '<script src="scripts/include-1.js" onload = "log(\'include-1 load\')">log(\'ignore this\')<\/script>' ) + document.write( '<script src="scripts/include-3.js" onload = "log(\'include-3 load\')"><\/script>' ) + document.write( '<script src="scripts/include-2.js" onload = "log(\'include-2 load\')">log(\'ignore this\')<\/script>' ) + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1', 'include-1 load', 'external script before doc write', 'document.write external script', 'external script after doc write', 'include-3 load', 'external script #2', 'include-2 load', 'inline script #2']); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/013.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/013.html new file mode 100644 index 0000000000..09616a67d4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/013.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added inline script earlier in document</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], false); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'head script #1','end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(function(){setTimeout(t.step_func(test), 100); }) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/014.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/014.html new file mode 100644 index 0000000000..41c90a3421 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/014.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: SCRIPT elements that move themselves in DOM </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.getElementsByTagName('head')[0].appendChild(document.getElementsByTagName('script')[2]); + log('end script #1'); + </script> + + <script type="text/javascript"> + log('script #2'); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'script #2']); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/015.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/015.html new file mode 100644 index 0000000000..1fa67e22ed --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/015.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added inline+external+inline script earlier in document</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], false); + var s = testlib.addScript('', { 'src':'scripts/include-1.js' }, document.getElementsByTagName('head')[0], false); + testlib.addScript('log(\'head script #2\')', {}, document.getElementsByTagName('head')[0], false); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + ///XXX I think the spec allows this case to race + onload = function(){ + setTimeout(t.step_func( + function() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'head script #1', 'head script #2', 'end script #1', 'external script #1', 'inline script #2'], + ['inline script #1', 'head script #1', 'head script #2', 'end script #1', 'inline script #2', 'external script #1']]); + t.done(); + }), + 100);} + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/015a.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/015a.html new file mode 100644 index 0000000000..94763c3542 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/015a.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added inline+external+inline script earlier in document</title> + <meta name="timeout" content="long"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], false); + var s = testlib.addScript('', { 'src':'scripts/include-1.js?pipe=trickle(d1)' }, document.getElementsByTagName('head')[0], false); + testlib.addScript('log(\'head script #2\')', {}, document.getElementsByTagName('head')[0], false); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'head script #1', 'head script #2', 'end script #1', 'inline script #2', 'external script #1']); + t.done(); + } + onload = function(){setTimeout(t.step_func(function() {test.apply(t)}), 2000); } + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/016.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/016.html new file mode 100644 index 0000000000..1149dcc752 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/016.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added inline script later in document</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + testlib.addScript('log(\'body script #1\')', {}, document.body, false); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'body script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(function(){setTimeout(t.step_func(test), 100); }) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/017.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/017.html new file mode 100644 index 0000000000..66675bcf11 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/017.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: multiple DOM added scripts later in document</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + testlib.addScript('log(\'body script #1\')', {}, document.getElementsByTagName('body')[0], false); + testlib.addScript('', { 'src':'scripts/include-1.js' }, document.getElementsByTagName('body')[0], false); + testlib.addScript('log(\'body script #2\')', {}, document.getElementsByTagName('body')[0], false); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + //The order of the external script vs the second inline script is undefined because the added script is async by default + //But we expect most UAs to have the second order + onload = function() {setTimeout(t.step_func(function() { + assert_any(assert_array_equals, eventOrder, [ + ['inline script #1', 'body script #1', 'body script #2', 'end script #1', 'external script #1', 'inline script #2'], + ['inline script #1', 'body script #1', 'body script #2', 'end script #1', 'inline script #2', 'external script #1']]); + t.done(); + }), 100);} + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/018.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/018.html new file mode 100644 index 0000000000..5a349bf556 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/018.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added scripts and doc.write</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + testlib.addScript('', { 'src':'scripts/include-3.js' }, document.getElementsByTagName('head')[0], false); + testlib.addScript('log(\'body script #2\')', {}, document.getElementsByTagName('body')[0], true); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + //XXX Need to test this delaying the document after we insert the external script and delaying the external script itself; afaict the spec allows us to race here on whether the document.write + //ever actually happens or not according to whether the insertion point is defined at the point at which the script is executed. + function test() { + assert_any(assert_array_equals, eventOrder, [ + ['inline script #1', 'body script #2', 'end script #1', 'external script before doc write', 'document.write external script', 'external script after doc write', 'inline script #2'], + ['inline script #1', 'body script #2', 'end script #1', 'inline script #2', 'external script before doc write', 'document.write external script', 'external script after doc write'], + ['inline script #1', 'body script #2', 'end script #1', 'inline script #2', 'external script before doc write', 'external script after doc write'] + ]); + t.done(); +} + onload = t.step_func(function(){setTimeout(test.apply(t), 100); }) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/019.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/019.html new file mode 100644 index 0000000000..64ee4f1c52 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/019.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added scripts and event handling </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script onload="log('inline #1 load')"> + log('inline script #1'); + testlib.addScript('', {'src':'scripts/include-1.js', 'onload':function(){log("external #1 load")}}, document.getElementsByTagName('head')[0], false); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'external #1 load', 'inline script #2'], + ['inline script #1', 'end script #1', 'inline script #2', 'external script #1', 'external #1 load'] + ]); + t.done(); + } + onload = function(){setTimeout(t.step_func(test), 100); } + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/020.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/020.html new file mode 100644 index 0000000000..7d8f953e40 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/020.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added script with data: URL </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <script>log('inline script #1'); + testlib.addScript('', { 'src':'data:text/javascript,log("data URL script")' }, document.getElementsByTagName('body')[0], true); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'data URL script', 'inline script #2'], + ['inline script #1', 'end script #1', 'inline script #2', 'data URL script']]); + t.done(); + } + onload = function() {setTimeout( t.step_func(test), 100); } + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/021.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/021.html new file mode 100644 index 0000000000..34fdc95cb1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/021.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added script with javascript: URL </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <script>log('inline script #1'); + testlib.addScript('', { 'src':'javascript:log("JS URL script")' }, document.getElementsByTagName('body')[0], true); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', /*'JS URL script',*/ 'inline script #2']); + t.done(); + /* pass condition changed 2010-12-01 due to CT-198 */ + } + onload = t.step_func(function(){setTimeout( test, 100); }) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/022.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/022.html new file mode 100644 index 0000000000..ccbcb347dc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/022.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added script, late .src </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <script>log('inline script #1'); + var script = testlib.addScript('', { }, document.getElementsByTagName('body')[0], false); + script.src='scripts/include-1.js'; + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + onload = function() {setTimeout(t.step_func( + function() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'inline script #2'], + ['inline script #1', 'end script #1', 'inline script #2', 'external script #1']]); + t.done() + }), + 100)} + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/023.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/023.html new file mode 100644 index 0000000000..dc687ffe4d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/023.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added script, even later .src </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <script>log('inline script #1'); + var script = testlib.addScript('', { }, document.getElementsByTagName('body')[0], false); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2', 'external script #1']); + t.done(); +} + onload = t.step_func(function(){ + script.src='scripts/include-1.js'; + script.onload = t.step_func(test); + }) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/024.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/024.html new file mode 100644 index 0000000000..ee807b56f9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/024.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added script, .src set twice</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <script>log('inline script #1'); + var script = testlib.addScript('', { }, document.getElementsByTagName('body')[0], false); + script.src='scripts/include-1.js'; + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'inline script #2'], + ['inline script #1', 'end script #1', 'inline script #2', 'external script #1']]); + t.done(); + } + onload = t.step_func(function(){ + script.src='scripts/include-2.js'; // needs to be ignored, script already "is executed" + setTimeout(t.step_func(test), 100); + }) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/025.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/025.html new file mode 100644 index 0000000000..05c6a97284 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/025.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM added script, .src set on script with content</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <script>log('inline script #1'); + var script = testlib.addScript('log("inline DOM script #1")', { }, document.getElementsByTagName('body')[0], false); + script.src='scripts/include-1.js'; + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'inline DOM script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(function(){ + setTimeout(t.step_func(test), 100); + }) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/026.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/026.html new file mode 100644 index 0000000000..34110ff5ba --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/026.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: doc write added script, .src set later</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <script>log('inline script #1'); + var t = async_test(); + document.write('<script><\/script>'); + var scripts = document.getElementsByTagName('script'); + scripts[scripts.length - 1].src = 'scripts/include-1.js'; + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + + onload = function() { + setTimeout( + t.step_func(function() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'inline script #2'], + ['inline script #1', 'end script #1', 'inline script #2', 'external script #1']]); + t.done(); + }), + 100); + } + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/027.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/027.html new file mode 100644 index 0000000000..e9fbe7f15c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/027.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: doc write added script with content, .src set later</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <script>log('inline script #1'); + document.write('<script>log(\'doc.write script\')<\/script>'); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + document.getElementsByTagName('script')[4].src='scripts/include-1.js'; + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'doc.write script', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(function(){ + setTimeout(t.step_func(test), 100); + }) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/028.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/028.html new file mode 100644 index 0000000000..e383d4f1a6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/028.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: javascript: URL</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <script>log('inline script #1'); + window.location.replace('javascript:log(\'JS URL\')'); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_any(assert_array_equals, eventOrder, [ + ['inline script #1', 'end script #1', 'JS URL', 'inline script #2'], + ['inline script #1', 'end script #1', 'inline script #2', 'JS URL']]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/030.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/030.html new file mode 100644 index 0000000000..f01c257e0d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/030.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: javascript: URL in HREF, onclick handler</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <p><a href="javascript:log('JS URL')" onclick="log('click event');return true;"></a></p> + <script>log('inline script #1'); + if(document.links[0].click){ + document.links[0].click(); + }else{ + var evt = document.createEvent("MouseEvents"); + evt.initMouseEvent("click", true, true, window, + 0, 0, 0, 0, 0, false, false, false, false, 0, null); + document.links[0].dispatchEvent(evt); + } + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + var w = window; + onload = function() {setTimeout( + t.step_func(function() { + w.assert_any(w.assert_array_equals, w.eventOrder, + [['inline script #1', 'click event', 'end script #1', 'JS URL', 'inline script #2'], + ['inline script #1', 'click event', 'end script #1', 'inline script #2', 'JS URL']]); + t.done(); + }), 200); + } + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/031.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/031.html new file mode 100644 index 0000000000..3ddb36ab8d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/031.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: focus and blur events</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <form><input type="button" onclick="log('click event')" onfocus="log('focus event')" onblur="log('blur event')"><input type="button" onfocus="log('focus el 2 event')" onblur="log('blur event')"></form> + <script>log('inline script #1'); + document.forms[0][0].focus(); + document.forms[0][1].click(); + document.forms[0][1].focus(); + log('end script #1'); + </script> + + <script type="text/javascript"> + log('inline script #2'); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'focus event', 'blur event', 'focus el 2 event', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(function(){setTimeout(t.step_func(test), 200);}) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/032.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/032.html new file mode 100644 index 0000000000..da3969740c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/032.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: innerHTML and scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div></div> + <script>log('inline script #1'); + // script added with innerHTML should not run.. + document.getElementsByTagName('div')[1].innerHTML = '<script>log("innerHTML script runs")<\/script><script src="scripts/include-1.js"><\/script>'; + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(function(){setTimeout(t.step_func(test), 200);}) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/033.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/033.html new file mode 100644 index 0000000000..5c41effcde --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/033.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: innerHTML and scripts moved in DOM</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div></div> + <script>log('inline script #1'); + // script added with innerHTML should not run.. + document.getElementsByTagName('div')[0].innerHTML = '<script>log("innerHTML script runs")<\/script><script src="scripts/include-1.js"><\/script>'; + try{ + document.body.appendChild( document.getElementsByTagName('div')[0].firstChild ); + document.body.appendChild( document.getElementsByTagName('div')[0].firstChild ); + }catch(e){ + log('ERROR while testing'); + } + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(function(){setTimeout(t.step_func(test), 200);}) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/034.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/034.html new file mode 100644 index 0000000000..13664253a2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/034.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: innerHTML adding frames with JS in</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div></div> + <script>log('inline script #1'); + document.getElementsByTagName('div')[1].innerHTML = '<iframe src="pages/helloworld.html"></iframe>'; + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2', 'frame/popup script']); + t.done(); + } + onload = t.step_func(function(){setTimeout(t.step_func(test), 200);}) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/035.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/035.html new file mode 100644 index 0000000000..406c3c548f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/035.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: innerHTML adding frames with JS in and moving scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div></div> + <script>log('inline script #1'); + document.getElementsByTagName('div')[1].innerHTML = '<iframe src="pages/helloworld.html"></iframe>'; + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2', 'frame/popup script']); + t.done(); + /*, ['inline script #1', 'end script #1', 'frame/popup script', 'inline script #2'] */ + } + onload = t.step_func(function(){ + try{ + document.body.appendChild(document.importNode( top.frames[0].document.getElementsByTagName('script')[0], true )); + }catch(e){ log('ERROR - tested functionality not supported'); } + setTimeout(t.step_func(test), 200); + }); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/036.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/036.html new file mode 100644 index 0000000000..113541dab9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/036.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM cloning</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div></div> + <script>log('inline script #1'); + testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], true); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + try{ + var script = document.getElementsByTagName('script')[0].cloneNode(true); + document.body.appendChild(script); + }catch(e){ log('ERROR - tested functionality not supported'); } + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'head script #1', 'end script #1', 'inline script #2' ]); + t.done(); + } + onload = t.step_func(function(){ + setTimeout(t.step_func(test), 200); + }); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/037.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/037.html new file mode 100644 index 0000000000..15bd8a96e0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/037.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM movement with appendChild, inline</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div></div> + <script>log('inline script #1'); + var script = testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], true); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + try{ + document.body.appendChild(script); + }catch(e){ log('ERROR - tested functionality not supported'); } + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'head script #1', 'end script #1', 'inline script #2' ]); + t.done(); + } + onload = t.step_func(function(){ + setTimeout(t.step_func(test), 200); + }); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/038.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/038.html new file mode 100644 index 0000000000..db6cec3520 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/038.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM movement with appendChild, external</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div></div> + <script>log('inline script #1'); + var script = testlib.addScript('', { 'src':'scripts/include-1.js' }, document.getElementsByTagName('head')[0], true); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + try{ + document.body.appendChild(script); + }catch(e){ log('ERROR - tested functionality not supported'); } + var t = async_test() + + function test() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'inline script #2'], + ['inline script #1', 'end script #1', 'inline script #2', 'external script #1']]); + t.done(); + } + onload = function() { + setTimeout(t.step_func(test), 200); + }; + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/039.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/039.html new file mode 100644 index 0000000000..3720e24866 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/039.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: IFRAMEs added with DOM</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div></div> + <script>log('inline script #1'); + for( var i=0; i<2; i++ ){ + var iframe=document.createElement('iframe'); + document.getElementsByTagName('div')[1].appendChild(iframe); + iframe.src='pages/helloworld.html?'+i+'&'+Math.random(); + } + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + promise_test(() => { + const frames = document.querySelectorAll("iframe"); + return Promise.all([ + new Promise(resolve => window.addEventListener('load', resolve)), + new Promise(resolve => frames[0].addEventListener('load', resolve)), + new Promise(resolve => frames[1].addEventListener('load', resolve)), + ]).then(() => { + assert_equals(eventOrder.length, 5); + assert_array_equals( + eventOrder.slice(0, 3), + ['inline script #1', 'end script #1', 'inline script #2'], + "inline scripts should run first"); + assert_in_array('frame/popup script 0', eventOrder.slice(3, 5), 'iframe should have loaded'); + assert_in_array('frame/popup script 1', eventOrder.slice(3, 5), 'iframe should have loaded'); + }); + }, 'iframes should load asynchronously after inline script run'); + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/040.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/040.html new file mode 100644 index 0000000000..3cdf87f07b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/040.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: IFRAMEs added with DOM (innerHTML), javascript: URL</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div></div> + <script>log('inline script #1'); + document.getElementsByTagName('div')[1].innerHTML = '<iframe src="javascript:parent.log(\'JS URL\');\'<html><script>parent.log(\\\'frame script\\\')<\/script></html>\'"></iframe>'; + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_any(assert_array_equals, eventOrder, [ + ['inline script #1', 'end script #1', 'JS URL', 'inline script #2', 'frame script'], + /* the following combination seems quite unlikely? */ + ['inline script #1', 'end script #1', 'JS URL', 'frame script', 'inline script #2'], + ['inline script #1', 'end script #1', 'inline script #2', 'JS URL', 'frame script']]); + t.done(); + } + onload = t.step_func(function(){ + setTimeout(t.step_func(test), 200); + }); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/041.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/041.html new file mode 100644 index 0000000000..bce7041185 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/041.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write scripts that write scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.write( '<script>log(\'inline with doc.write #1\'); document.write(\'<script src="scripts/include-4.js"><\\\/script>\');log(\'end inline with doc.write\');<\/script>' ); + document.write( '<script src="scripts/include-1.js">log(\'ignore this\')<\/script>' ); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'inline with doc.write #1', 'end inline with doc.write', 'end script #1', 'include-4 before doc write', 'include-4 after doc write', 'external script before doc write', 'document.write external script', 'external script after doc write', 'external script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/042.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/042.html new file mode 100644 index 0000000000..df3a2f88f2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/042.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM mutation events when adding scripts: DOMNodeInserted </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.addEventListener( 'DOMNodeInserted', function(){ log('DOMNodeInserted'); }, false ); + testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], false); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'head script #1', 'DOMNodeInserted', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/043.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/043.html new file mode 100644 index 0000000000..bcfd90cba4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/043.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM mutation events when adding external scripts: DOMNodeInserted </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.addEventListener( 'DOMNodeInserted', function(){ log('DOMNodeInserted'); }, false ); + testlib.addScript('', { src: 'scripts/include-1.js' }, document.getElementsByTagName('head')[0], false); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'DOMNodeInserted', 'end script #1', 'external script #1', 'inline script #2'], + ['inline script #1', 'DOMNodeInserted', 'end script #1', 'inline script #2', 'external script #1']] + ); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/044.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/044.html new file mode 100644 index 0000000000..8d412079e4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/044.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM mutation events when adding scripts: DOMNodeInsertedIntoDocument </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + testlib.addScript('log(\'head script #1\')', {}, document.getElementsByTagName('head')[0], false, function(s){s.addEventListener( 'DOMNodeInsertedIntoDocument', function(){ log('DOMNodeInsertedIntoDocument'); }, false ); } ); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'head script #1', 'DOMNodeInsertedIntoDocument', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/045.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/045.html new file mode 100644 index 0000000000..254e0d1366 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/045.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: DOM mutation events when adding external scripts: DOMNodeInsertedIntoDocument </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + testlib.addScript('', {src:'scripts/include-1.js'}, document.getElementsByTagName('head')[0], false, function(s){s.addEventListener( 'DOMNodeInsertedIntoDocument', function(){ log('DOMNodeInsertedIntoDocument'); }, false);}); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + onload = t.step_func(function() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'DOMNodeInsertedIntoDocument', 'end script #1', 'external script #1', 'inline script #2'], + ['inline script #1', 'DOMNodeInsertedIntoDocument', 'end script #1', 'inline script #2', 'external script #1']]); + t.done(); + }); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/046.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/046.html new file mode 100644 index 0000000000..4f145d63e1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/046.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: no readystatechange events when adding external scripts </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + testlib.addScript('', {src:'scripts/include-1.js', onreadystatechange:function() {log( 'readystatechange '+ this.readyState );}}, document.getElementsByTagName('head')[0], false ); + log('end script #1'); + </script> + + <script type="text/javascript"> + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/047.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/047.html new file mode 100644 index 0000000000..88509e9d43 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/047.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: adding and removing external script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=testlib.addScript('', {src:'scripts/include-1.js'}, document.getElementsByTagName('head')[0], false ); + script.parentNode.removeChild(script); + log('end script #1'); + </script> + + <script type="text/javascript"> + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1']); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/048.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/048.html new file mode 100644 index 0000000000..8879f035d3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/048.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: adding inline script which sets its own .src </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=testlib.addScript('log(\'HEAD script start\');document.getElementsByTagName(\'script\')[0].src=\'scripts/include-1.js\';log(\'HEAD script end\')', {}, document.getElementsByTagName('head')[0], true ); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'HEAD script start', 'HEAD script end', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/049.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/049.html new file mode 100644 index 0000000000..455a20c549 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/049.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: adding external script but removeAttribute( src ) before it runs</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=testlib.addScript('log(\'HEAD script\');', { src:'scripts/include-1.js' }, document.getElementsByTagName('head')[0], false ); + script.removeAttribute('src'); + log('end script #1'); + </script> + + <script type="text/javascript"> + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #1']); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/050.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/050.html new file mode 100644 index 0000000000..a400749f18 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/050.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: adding external script that removes all scripts from document</title> + <meta name="timeout" content="long"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=testlib.addScript('', { src:'scripts/include-5.js' }, document.getElementsByTagName('head')[0], false ); + // caching might affect whether the below script runs or not. Adding Math.random() makes the test a bit more predictable? :-p + var script=testlib.addScript('', { src:'scripts/include-1.js?pipe=trickle(d1)&'+Math.random() }, document.getElementsByTagName('head')[0], false ); + log('end script #1'); + </script> + <script src="scripts/include-2.js?pipe=trickle(d4)"></script> + <script type="text/javascript"> + var t = async_test() + + function test() { + // Per-spec, non-blocking/async scripts can execute at any time. + // Therefore, there are two possibilities for the script order here. + // 1. inline script first, followed by include-5 (async), then + // external script #1 (slow async) and finally external #2 + // (inline). + // 2. inline script, external '2, 'include 5', then include-1. + assert_array_equals(eventOrder.slice(0, 2), [ + 'inline script #1', 'end script #1' + ]); + if (eventOrder[2] == 'include-5 before removing scripts') { + assert_array_equals(eventOrder.slice(3), [ + 'include-5 after removing scripts', 'external script #1', + 'external script #2' + ]); + } else { + assert_array_equals(eventOrder.slice(2), ['external script #2', + 'include-5 before removing scripts', + 'include-5 after removing scripts', + 'external script #1' + ]); + } + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/051.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/051.html new file mode 100644 index 0000000000..a0b674304f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/051.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: interaction of parsing and script execution - script added through DOM</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + testlib.addScript('', { src: 'scripts/count-script-tags.js' }, document.body, true); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'script tags in DOM: 5', 'inline script #2'], + ['inline script #1', 'end script #1', 'inline script #2', 'script tags in DOM: 6']]); + t.done(); + } + onload = function(){setTimeout(t.step_func(test), 100); } + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/052.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/052.html new file mode 100644 index 0000000000..21a151cb79 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/052.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: interaction of parsing and script execution - external script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script src="scripts/count-script-tags.js"></script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['script tags in DOM: 4', 'inline script #2']); + t.done(); + } + onload = t.step_func(function(){setTimeout(t.step_func(test), 100); }) + </script> + +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/053.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/053.html new file mode 100644 index 0000000000..810197437d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/053.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: adding external script that removes itself from document when loading</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=testlib.addScript('', { src:'scripts/include-1.js', onload:function() {this.parentNode.removeChild(this);log('removed ' + this.localName);} }, document.getElementsByTagName('body')[0], true ); + log('end script #1'); + </script> + <script src="scripts/include-2.js"></script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'end script #1', 'external script #1', 'removed script', 'external script #2', 'inline script #2'], + ['inline script #1', 'end script #1', 'external script #2', 'external script #1', 'removed script', 'inline script #2'], + ['inline script #1', 'end script #1', 'external script #2', 'inline script #2', 'external script #1', 'removed script']] + ); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/054.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/054.html new file mode 100644 index 0000000000..29ede23414 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/054.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: removing newly inserted script from DOMNodeInserted handler - external script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.addEventListener( 'DOMNodeInserted', function listener(e){ + log('DOMNodeInserted event'); + e.target.parentNode.removeChild(e.target); + document.removeEventListener('DOMNodeInserted', listener); + }, false ); + var script=testlib.addScript('', { src:'scripts/include-1.js?'+Math.random() }, document.getElementsByTagName('body')[0], true ); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'DOMNodeInserted event', 'end script #1', 'inline script #2', 'external script #1'], + ['inline script #1', 'DOMNodeInserted event', 'end script #1', 'external script #1', 'inline script #2']]); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/055.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/055.html new file mode 100644 index 0000000000..c837d78174 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/055.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: removing newly inserted script from DOMNodeInserted handler - inline script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + document.addEventListener( 'DOMNodeInserted', function listener(e){ + log('DOMNodeInserted event'); + e.target.parentNode.removeChild(e.target); + document.removeEventListener('DOMNodeInserted', listener); + }, false ); + var script=testlib.addScript('log(\'added script\')', { }, document.getElementsByTagName('body')[0], true ); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'added script', 'DOMNodeInserted event', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/056.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/056.html new file mode 100644 index 0000000000..e2d0868034 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/056.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: appending code to initially empty SCRIPT tag in DOM </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=document.getElementsByTagName('script')[3]; + script.appendChild( document.createTextNode('log("injected script code");') ); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + // Test asserts the injected script should run + assert_array_equals(eventOrder, ['inline script #1', 'injected script code', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/057.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/057.html new file mode 100644 index 0000000000..4dc8e1384e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/057.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: appending code to initially non-empty SCRIPT tag in DOM (whitespace only) </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script> + </script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=document.getElementsByTagName('script')[3]; + script.appendChild( document.createTextNode('log("injected script code");') ); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/058.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/058.html new file mode 100644 index 0000000000..15deb785c2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/058.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: appending code to initially non-empty SCRIPT tag in DOM (comment only) </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script>/**/</script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=document.getElementsByTagName('script')[3]; + script.appendChild( document.createTextNode('log("injected script code");') ); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/059.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/059.html new file mode 100644 index 0000000000..b3a34367b2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/059.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: appending code to initially non-empty SCRIPT tag in DOM after removing its initial child </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script>/**/</script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=document.getElementsByTagName('script')[3]; + script.removeChild(script.firstChild); + script.appendChild( document.createTextNode('log("injected script code");') ); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/060.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/060.html new file mode 100644 index 0000000000..905dfe233f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/060.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: appending code to initially non-empty SCRIPT tag in DOM after setting textContent/innerHTML</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script>log('HEAD script');</script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=document.getElementsByTagName('script')[3]; + script.innerHTML=''; + script.appendChild( document.createTextNode('log("injected script code 1");') ); + script.textContent=''; + script.appendChild( document.createTextNode('log("injected script code 2");') ); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['HEAD script', 'inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/061.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/061.html new file mode 100644 index 0000000000..9950b1c7ac --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/061.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: cloneNode and script execution</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script>log('HEAD script');</script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=document.getElementsByTagName('script')[3]; + document.body.appendChild( script.cloneNode(true) ); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['HEAD script', 'inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/062.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/062.html new file mode 100644 index 0000000000..c5e0ee2d46 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/062.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: cloneNode (shallow) and script execution</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script>log('HEAD script');</script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=document.getElementsByTagName('script')[3]; + document.body.appendChild( script.cloneNode(false) ).appendChild(document.createTextNode('log("clone");')); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['HEAD script', 'inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/063.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/063.html new file mode 100644 index 0000000000..6824074a8c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/063.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: cloneNode (deep) of the currently executing script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script>log('HEAD script'); + if( !window.already_cloned ){ + window.already_cloned=true; + var script=document.getElementsByTagName('script')[3]; + document.getElementsByTagName('head')[0].appendChild( script.cloneNode(true) ); + } + </script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['HEAD script', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/064.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/064.html new file mode 100644 index 0000000000..ceedc3da2d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/064.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: cloneNode with external script</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script src="scripts/include-1.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=document.getElementsByTagName('script')[3]; + document.body.appendChild( script.cloneNode(true) ); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['external script #1', 'inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/065.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/065.html new file mode 100644 index 0000000000..5859dc9e0b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/065.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: cloneNode with external script, changed .src</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script src="scripts/include-1.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=document.getElementsByTagName('script')[3].cloneNode(true); + script.src='scripts/include-2.js' + document.body.appendChild( script ); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['external script #1', 'inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/066.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/066.html new file mode 100644 index 0000000000..a8e346dfd8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/066.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: cloneNode with external script, removing .src and adding content</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script src="scripts/include-1.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=document.getElementsByTagName('script')[3].cloneNode(true); + script.removeAttribute('src'); + script.appendChild(document.createTextNode( 'log("cloned script");' )); + document.body.appendChild( script ); + log('end script #1'); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['external script #1', 'inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/067.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/067.html new file mode 100644 index 0000000000..7be0fd0ab0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/067.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: is a script with syntax error marked as "has run"? </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script>setup({allow_uncaught_exception:true}) + var t = async_test() + </script> + <script> + log(This script will never run.. + </script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>t.step(function() { + log('inline script #1'); + var script=document.getElementsByTagName('script')[3].cloneNode(true); + script.removeChild(script.firstChild); + script.appendChild(document.createTextNode( 'log("cloned script");' )); + document.body.appendChild( script ); + log('end script #1'); + }) + </script> + <script type="text/javascript"> + t.step(function() { + log( 'inline script #2' ); + }); + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2']); + t.done(); + } + onload = t.step_func(test); +</script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/068.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/068.html new file mode 100644 index 0000000000..a58158b6c0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/068.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: external script and parsing of markup added with document.write </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script> + log('inline script #1'); + document.write('<script src="scripts/find-foo.js">log(\'inline code in external script (not expected to run!!)\')<\/script>' + '<div id="foo"></div>'); + log('end script #1'); + + var t = async_test() + + + function test() { + if(!window.findFooLoaded) { + return setTimeout(t.step_func(test),200); + } + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'found #foo element: NO']); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/069.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/069.html new file mode 100644 index 0000000000..4d4aed2658 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/069.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: external files added through DOM should not block further parsing while loading</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script> + testlib.addScript('',{src:'scripts/find-body.js?pipe=trickle(d1)'},document.getElementsByTagName('head')[0], true ); + </script> +</head> +<body> + <script> + testlib.addScript('', {src:'scripts/find-foo.js?pipe=trickle(d1)'}, document.getElementsByTagName('head')[0], true); + </script> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <p><span id="foo"></span></p> + + <script type="text/javascript"> + var t = async_test() + + function test() { + if(!(window.findFooLoaded && window.findBodyLoaded)) { + return setTimeout(t.step_func(test), 200); + } + assert_any(assert_array_equals, eventOrder, + [['document.body: <BODY>', 'found #foo element: YES'], + ['found #foo element: YES', 'document.body: <BODY>']]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/070.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/070.html new file mode 100644 index 0000000000..4b82a9e83f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/070.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write into IFRAME a script that adds a SCRIPT through DOM</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <iframe></iframe> + + <script type="text/javascript"> + var doc = document.getElementsByTagName('iframe')[0].contentDocument; + doc.open(); + + log("calling document.write"); + doc.write('<script>top.log("inline script #1");'+ + 'var s=document.createElement("script");'+ + 's.src="scripts/include-6.js?'+new Date().getTime()+'";'+ + 'document.getElementsByTagName("head")[0].appendChild(s);'+ + '<\/script>'+ + '<div id="foo"></div>'+ + '<script>top.log("inline script #2");<\/script>' + ); + + log("calling document.close"); + doc.close(); + + var t = async_test() + + + function test() { + if(!window.include6Loaded) { + return setTimeout(t.step_func(test),200); + } + assert_array_equals(eventOrder, ['calling document.write', 'inline script #1', 'inline script #2', 'calling document.close', 'external script (#foo found? YES)']); + t.done(); + } + + onload = t.step_func(test) + </script> +</head> + +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/071.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/071.html new file mode 100644 index 0000000000..802c4a8ce3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/071.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write several scripts into IFRAME </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <iframe style="width:1px;height:1px"></iframe> + + <script type="text/javascript"> + var doc = document.getElementsByTagName('iframe')[0].contentDocument; + doc.open(); + + var html = '<html><head><title>test</title></head>'+ + '<script>top.log("inline script #1");'+ + '<\/script>'+ + /* made url unique because Chrome will change + order depending on file cached status */ + '<script src="scripts/include-6.js?'+new Date().getTime()+'"><\/script>'+ + '</head>'+ + '<body>'+ + '<div id="foo"></div>'+ + '</body></html>'+ + '<script>top.log("inline script #2");<\/script>'; + log("calling document.write"); + doc.write(html); + + log("calling document.close"); + doc.close(); + + var t = async_test() + + + function test() { + if( !window.include6Loaded )return setTimeout(t.step_func(test),200); // try checking again if external script didn't run yet + assert_array_equals(eventOrder, ['calling document.write', + 'inline script #1', + 'calling document.close', + 'external script (#foo found? NO)', + 'inline script #2' + ]); + t.done(); + } + + onload = t.step_func(test) + </script> +</head> + +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/072.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/072.html new file mode 100644 index 0000000000..e502a35736 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/072.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write into IFRAME a script that creates new inline script in parent </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <iframe style="width:1px;height:1px"></iframe> + + <script type="text/javascript"> + var doc = document.getElementsByTagName('iframe')[0].contentDocument; + doc.open(); + + var html = '<html><head><title>test</title></head>'+ + '<script>top.log("inline script #1");'+ + '<\/script>'+ + '</head>'+ + '<body>'+ + '<div id="foo"></div>'+ + '</body></html>'+ + '<script>top.testlib.addScript( \'log("inline script added to parent")\', null, top.document.body, true )<\/script>'; + log("calling document.write"); + doc.write(html); + + log("calling document.close"); + doc.close(); + + var t = async_test() + + + function test() { + assert_array_equals(eventOrder, ['calling document.write', + 'inline script #1', + 'inline script added to parent', + 'calling document.close', + ]); + t.done(); + } + + onload = t.step_func(test) + </script> +</head> + +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/073.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/073.html new file mode 100644 index 0000000000..6f65c4ae19 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/073.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write into IFRAME a script that creates new external script in parent </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <iframe style="width:1px;height:1px"></iframe> + + <script type="text/javascript"> + var doc = document.getElementsByTagName('iframe')[0].contentDocument; + doc.open(); + + var html = '<html><head><title>test</title></head>'+ + '<script>top.log("inline script #1");'+ + '<\/script>'+ + '</head>'+ + '<body>'+ + '<div id="foo"></div>'+ + '</body></html>'+ + '<script>top.testlib.addScript( \'\', { src:\'scripts/include-1.js\' }, top.document.body, true )<\/script>'; + log("calling document.write"); + doc.write(html); + + log("calling document.close"); + doc.close(); + + var t = async_test() + + + function test() { + + assert_array_equals(eventOrder, ['calling document.write', + 'inline script #1', + 'calling document.close', + 'external script #1' + ]); + + t.done(); + } + + onload = t.step_func(test) + </script> +</head> + +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/074.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/074.html new file mode 100644 index 0000000000..70d7b88b74 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/074.html @@ -0,0 +1,49 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: document.write into IFRAME a script that creates new inline script in parent that again adds script to IFRAME </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <iframe style="width:1px;height:1px"></iframe> + + <script type="text/javascript"> + var doc = document.getElementsByTagName('iframe')[0].contentDocument; + doc.open(); + var str1=''; + var html = '<html><head><title>test</title></head>'+ + '<script>top.log("inline script #1");'+ + '<\/script>'+ + '</head>'+ + '<body>'+ + '<script>top.testlib.addScript( \'top.log("inline script added to parent");top.doc.write( "<script>top.log(\\\\"inline script added to iframe\\\\")<\\\/script>");\', null, top.document.body, true ) <\/script>'+ + '</body></html>'; + log("calling document.write"); + doc.write(html); + + log("calling document.close"); + doc.close(); + + var t = async_test() + + + function test() { + assert_array_equals(eventOrder, ['calling document.write', + 'inline script #1', + 'inline script added to parent', + 'inline script added to iframe', + 'calling document.close', + ]); + t.done(); + } + + onload = t.step_func(test) + </script> +</head> + +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/075.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/075.html new file mode 100644 index 0000000000..40ec9bbb6a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/075.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> + <head> + <title>dispatchEvent from child frame during document.write :-o </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + </head> + <body onclick="log('click event')"> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <iframe></iframe> + <script> + var doc = document.getElementsByTagName("iframe")[0].contentDocument; + doc.open("text/html"); + doc.write('<html><head><title>event dispatcher</title></head><body>Before script<script>top.log("inline script before event");var ev = parent.document.createEvent("MouseEvents");ev.initMouseEvent("click", true, false, null, 0, 0, 0, 0, 0, false, false, false, false, 0, null);parent.document.body.dispatchEvent(ev);top.log("inline script after event");</sc'+'ript> After script</body>'); + log( 'end main script' ); + + + </script> + +<script> + var t = async_test() + + function test() { + if(test.ran)return; test.ran=true; + + assert_array_equals(eventOrder, ['inline script before event', + 'click event', + 'inline script after event', + 'end main script' + ]); + doc.close(); + t.done(); +} + + onload = t.step_func(test) + /* onload doesn't fire in this test, a fallback.. */ + setTimeout(t.step_func(test), 800 ); +</script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/076.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/076.html new file mode 100644 index 0000000000..2b8b692d92 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/076.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: adding and removing external and inline scripts </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script>log('inline script #1'); + var script=testlib.addScript('', {src:'scripts/include-1.js', onload:function(e){ e.target.parentNode.removeChild(e.target); }}, document.getElementsByTagName('head')[0], false ); + var script=testlib.addScript( 'log( "dynamically added inline script" )', null, document.getElementsByTagName('head')[0], false ); + script.parentNode.removeChild(script); + log('end script #1'); + </script> + + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + } + onload = t.step_func(function() { + assert_any(assert_array_equals, eventOrder, [['inline script #1', 'dynamically added inline script', 'end script #1', 'external script #1', 'inline script #2'], + ['inline script #1', 'dynamically added inline script', 'end script #1', 'inline script #2', 'external script #1']]); + t.done(); + }) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/077.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/077.html new file mode 100644 index 0000000000..dbcd16bea5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/077.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> + <head> + <title> adding several types of scripts through the DOM and removing some of them confuses scheduler </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script type="text/javascript"> + var head = document.getElementsByTagName('head')[0]; + function createScript(url, contents) { + props = {}; + if (url) { + props.src = url; + } + return testlib.addScript(contents, props, head, false); + } + var t = async_test() + + function test() { + var script = createScript('data:text\/javascript,log("Script %231 ran")'); + var script2 = createScript('','log("Script #2 ran")'); + if(script2) { + head.removeChild(script2); + } + var script3 = createScript('data:text\/javascript, log("Script %233 ran"); createScript(\'\', \'log("Script %234 ran")\')'); + if(script3) { + head.removeChild(script3); + } + setTimeout(t.step_func(function(){ + assert_array_equals(eventOrder, ['Script #2 ran', 'Script #1 ran', 'Script #3 ran','Script #4 ran']); + t.done(); + }), 400); + + }; + onload = t.step_func(test) + </script> + </head> + <body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + </body> +</html*> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/078.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/078.html new file mode 100644 index 0000000000..da4db4a2e6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/078.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<html> +<head> +<title> adding several types of scripts through the DOM and removing some of them confuses scheduler (slow-loading scripts) </title> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="testlib/testlib.js"></script> +<script type="text/javascript"> + setup({ explicit_done: true }); + var head = document.getElementsByTagName('head')[0]; + function createScript(url, contents) { + props = {}; + if (url) { + props.src = url; + } + return testlib.addScript(contents, props, head, false); + } + var t = async_test() + + function test() { + document.getElementById("log").textContent = "Please wait..." + var url = 'scripts/include-1.js?pipe=trickle(d1)'; + var script = createScript(url); + var script2 = createScript('', 'log("Script #2 ran")'); + head.removeChild(script2); + var url = 'scripts/include-2.js?pipe=trickle(d2)'; + var script3 = createScript(url); + head.removeChild(script3); + + setTimeout(t.step_func(function () { + done(); + assert_array_equals(eventOrder, ['Script #2 ran', 'external script #1', 'external script #2']); + t.done(); + }), 5500); + + }; + onload = t.step_func(test) +</script> +</head> +<body> +<div id="log">FAILED (This TC requires JavaScript enabled)</div> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/079.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/079.html new file mode 100644 index 0000000000..8d684cebf2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/079.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html> +<head> +<title> setting location to javascript URL from event handler </title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="testlib/testlib.js"></script> +<script type="text/javascript"> +log('inline script #1'); +var t = async_test() + +onload = t.step_func(function() { + log('onload handler'); + document.getElementById("log").textContent = 'please wait...'; + window.location='javascript:log("javascript: URL")'; + setTimeout(t.step_func(function(){ + log('timeout'); + assert_array_equals(eventOrder, ['inline script #1', 'onload handler', 'onload ends', 'javascript: URL', 'timeout']); + t.done(); + }), 200); + log('onload ends'); +}); +</script> +</head> +<body> +<div id="log">FAILED (This TC requires JavaScript enabled)</div> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/081.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/081.html new file mode 100644 index 0000000000..1b9bc991c6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/081.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: slow loading external script added with DOM (appendChild)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div></div> + <script> + var t = async_test() + log('inline script #1'); + testlib.addScript('', { src:'scripts/include-1.js?pipe=trickle(d1)&'+Math.random() }, document.getElementsByTagName('head')[0], false ); + log('end script #1'); + </script> + <script src="scripts/include-2.js"></script> + <script> + log( 'inline script #2' ); + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'external script #2', 'inline script #2', 'external script #1']); + t.done(); + } + onload = t.step_func(function() { + setTimeout(t.step_func(test), 12); + }); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/082.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/082.html new file mode 100644 index 0000000000..3e88fc73d4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/082.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: multiple slow loading external scripts added with DOM (appendChild)</title> + <meta name="timeout" content="long"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div></div> + <script> + + log('inline script #1'); + function scriptLoadListener(){ + log( 'load on '+this.src.match( /include-\d\.js/ ) ); + } + var script=testlib.addScript('', { src:'scripts/include-1.js?pipe=trickle(d1)&' + Math.random(), onload:scriptLoadListener }, document.getElementsByTagName('head')[0], false ); + var script=testlib.addScript('', { src:'scripts/include-2.js?pipe=trickle(d3)&' + Math.random(), onload:scriptLoadListener }, document.getElementsByTagName('head')[0], false ); + var script=testlib.addScript('', { src:'scripts/include-7.js?pipe=trickle(d2)&' + Math.random() , onload:scriptLoadListener }, document.getElementsByTagName('head')[0], false ); + log('end script #1'); + </script> + <script type="text/javascript"> + log('inline script #2'); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'end script #1', 'inline script #2', 'external script #1', 'load on include-1.js', 'external script #7', 'load on include-7.js', 'external script #2', 'load on include-2.js']); + t.done(); + } + onload = function() {setTimeout(t.step_func(test), 12)}; + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/083.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/083.html new file mode 100644 index 0000000000..2ac0015c8b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/083.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: event listener defined by script in a document in history</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <iframe src="about:blank"></iframe> + <script> + log('inline script #1'); + function fireFooEvent(){ + var evt=document.createEvent('Event'); + evt.initEvent('foo', true, true); + document.dispatchEvent(evt); + } + var doc = frames[0].document; + doc.open('text/html'); + doc.write('<script>top.log("IFRAME script");top.document.addEventListener("foo", function(e){ top.log("event: "+e.type); }, false)<\/script>'); + log('end script #1'); + </script> + <script> + fireFooEvent(); + frames[0].location='about:blank'; // returning to about:blank should de-activate document that defined event listener..? + </script> + <script> + fireFooEvent(); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_equals(frames[0].location.toString(), "about:blank"); + assert_array_equals(eventOrder, ['inline script #1', + 'IFRAME script', + 'end script #1', + 'event: foo', + 'inline script #2' + ]); + t.done(); + } + onload = function() {setTimeout(t.step_func(function() {fireFooEvent(); test()}), 80)}; + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/084.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/084.html new file mode 100644 index 0000000000..3027fa1994 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/084.html @@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: event listener defined by script in a removed IFRAME</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <iframe src="about:blank"></iframe> + <script> + log('inline script #1'); + function fireFooEvent(){ + var evt=document.createEvent('Event'); + evt.initEvent('foo', true, true); + document.dispatchEvent(evt); + } + var doc=frames[0].document; + doc.open( 'text/html' ); + doc.write( '<script>top.log("IFRAME script");top.document.addEventListener("foo", function(e){ top.log("event: "+e.type); }, false)<\/script>' ); + log('end script #1'); + </script> + <script> + fireFooEvent(); + frames[0].frameElement.parentNode.removeChild( frames[0].frameElement ); // removing the IFRAME should de-activate document that defined event listener..? + </script> + <script> + fireFooEvent(); + </script> + <script type="text/javascript"> + log( 'inline script #2' ); + var t = async_test() + + function test() { + assert_array_equals(eventOrder, ['inline script #1', + 'IFRAME script', + 'end script #1', + 'event: foo', + 'inline script #2' + ]); + t.done(); + } + onload = t.step_func(test) + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/085.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/085.html new file mode 100644 index 0000000000..6577527a8e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/085.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: async script and slow-loading defer script</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script src="scripts/include-1.js?pipe=trickle(d1)" defer></script> + <script src="scripts/include-2.js" async></script> + + <script type="text/javascript"> + var t = async_test(); + function test() { + assert_array_equals(eventOrder, ['external script #2', 'external script #1']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/086.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/086.html new file mode 100644 index 0000000000..4ccd16de89 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/086.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: async script and slow-loading async script</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script src="scripts/include-1.js?pipe=trickle(d2)" async></script> + <script src="scripts/include-2.js" async></script> + + <script type="text/javascript"> + var t = async_test(); + function test() { + assert_array_equals(eventOrder, ['external script #2', 'external script #1']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/087.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/087.html new file mode 100644 index 0000000000..8e225f48ae --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/087.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: multiple defer scripts, one slow loading</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script src="scripts/include-1.js?pipe=trickle(d2)" defer></script> + <script src="scripts/include-2.js" defer></script> + + <script type="text/javascript"> + var t = async_test(); + function test() { + assert_array_equals(eventOrder, ['external script #1', 'external script #2']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/088.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/088.html new file mode 100644 index 0000000000..f41f3d5be2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/088.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: multiple scripts with defer and async attributes</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script src="scripts/include-1.js?pipe=trickle(d2)" defer async></script> + <script src="scripts/include-2.js" defer async></script> + + <script type="text/javascript"> + var t = async_test(); + function test() { + assert_array_equals(eventOrder, ['external script #2', 'external script #1']); + t.done(); + } + onload = t.step_func(test); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/089.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/089.html new file mode 100644 index 0000000000..9ed5e0e1da --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/089.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: async attribute on inline script</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script async> + var t = async_test(); + log('inline script #1'); + t.step(function() { + assert_array_equals(eventOrder, ['inline script #1']); + }); + </script> + <script async> + log('inline script #2'); + t.step(function() { + assert_array_equals(eventOrder, ['inline script #1', 'inline script #2']); + }); + </script> + + <script> + log('inline script #3'); + t.step(function() { + assert_array_equals(eventOrder, ['inline script #1', 'inline script #2', 'inline script #3']); + }); + onload = function() {t.done()}; + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/090.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/090.html new file mode 100644 index 0000000000..17d1d1effe --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/090.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: defer attribute on inline script</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script defer> + var t = async_test(); + log('inline script #1'); + t.step(function() { + assert_array_equals(eventOrder, ['inline script #1']); + }); + </script> + <script defer> + log('inline script #2'); + t.step(function() { + assert_array_equals(eventOrder, ['inline script #1', 'inline script #2']); + }); + </script> + + <script> + log('inline script #3'); + t.step(function() { + assert_array_equals(eventOrder, ['inline script #1', 'inline script #2', 'inline script #3']); + }); + onload = function() {t.done()}; + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/091.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/091.html new file mode 100644 index 0000000000..f706cd31f5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/091.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: force-async off on non-parser-inserted script</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script> + var t = async_test(); + + sources = ["scripts/include-1.js?pipe=trickle(d2)", "scripts/include-2.js?pipe=trickle(d1)"]; + sources.forEach(function(x) { + var script = document.createElement("script"); + script.src = x; + t.step(function() {assert_equals(script.async, true, "async IDL attribute on script creation")}); + script.async = false; + t.step(function() {assert_equals(script.async, false, "async IDL attribute after setting")}); + t.step(function() {assert_equals(script.getAttribute("async"), null, "async content attribute after setting")}); + document.head.appendChild(script); + }); + + onload = t.step_func(function() { + assert_array_equals(eventOrder, ['external script #1', 'external script #2']); + t.done(); + }); + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/092.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/092.html new file mode 100644 index 0000000000..40fda5a0c0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/092.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: defer script and slow-loading non-async external script</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script> + var t = async_test(); + + var script = document.createElement("script"); + script.src = "scripts/include-2.js?pipe=trickle(d2)"; + script.async = false; + document.head.appendChild(script); + + onload = t.step_func(function() { + assert_array_equals(eventOrder, ['external script #1', 'external script #2']); + t.done(); + }); + </script> + <script defer src="scripts/include-1.js"></script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/094.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/094.html new file mode 100644 index 0000000000..cc9d1bf0fb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/094.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: parser-created defer script after document load</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <iframe id="myFrame"></iframe> + + <script> + var t = async_test(); + onload = t.step_func(function() { + var doc = document.getElementById("myFrame").contentDocument; + var win = document.getElementById("myFrame").contentWindow; + doc.open(); + doc.write("<title> scheduler: parser-created defer script after document load</title><script src='/resources/testharness.js'><\/script><script src='/resources/testharnessreport.js'><\/script><script src='testlib/testlib.js'><\/script><script>var t=async_test()<\/script><div id=log></div><script defer src='data:text/javascript,parent.t.done();'><\/script>"); + doc.close(); + }) + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/095.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/095.html new file mode 100644 index 0000000000..5e3b388cf1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/095.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: slow-loading script added from defer blocking load event</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script> + var t = async_test(); + function test() { + t.step(function() { + assert_array_equals(eventOrder, ['external script #8', 'external script #9']); + t.done(); + }); + } + //assert that the test is completed before onload fires + onload = t.step_func(function() {assert_unreached()}); + </script> + <script defer src="scripts/include-8.js"></script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/096.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/096.html new file mode 100644 index 0000000000..a2e15b782a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/096.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: defer script added from document.write relative to DOMContentLoaded</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script> + log("inline script #1"); + document.write("<script defer src='scripts/include-1.js'><\/script>") + </script> + <script> + log("inline script #2"); + var t = async_test(); + + addEventListener("DOMContentLoaded", t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "external script #1"]); + log("inline script #3"); + }), false); + + onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "external script #1", "inline script #3"]); + t.done(); + }); + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/097.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/097.html new file mode 100644 index 0000000000..a31d49e5b0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/097.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: slow-loading async script added from document.write</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script> + log("inline script #1"); + document.write("<script async src='scripts/include-1.js?pipe=trickle(d2)'><\/script>") + </script> + <script> + log("inline script #2"); + var t = async_test(); + + addEventListener("DOMContentLoaded", t.step_func(function() {assert_array_equals(eventOrder, ["inline script #1", "inline script #2"])}), false); + + onload = t.step_func( + function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "external script #1"]); + t.done(); + }); + + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/099.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/099.html new file mode 100644 index 0000000000..987fcc7c71 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/099.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: defer adding iframe containing script</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script defer src="scripts/include-11.js"></script> + <script> + var t = async_test(); + + onload = t.step_func(function() {assert_array_equals(eventOrder, ["external script before adding iframe", "script in iframe"]); t.done();}); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/101.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/101.html new file mode 100644 index 0000000000..b868f9a447 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/101.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: defer script after initial onload event</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <iframe id="myFrame"></iframe> + + <script> + var t = async_test(); + onload = t.step_func( + function() { + var doc = document.getElementById("myFrame").contentDocument; + var win = document.getElementById("myFrame").contentWindow; + doc.open(); + doc.write("<title> scheduler: defer script after initial onload event</title><script src='testlib/testlib.js'><\/script><div id='log'>document.written content</div><script>log('inline script #1');<\/script><script src='scripts/include-1.js'><\/script><script defer src='scripts/include-2.js'><\/script>"); + doc.close(); + //Note that the *window* object has changed but the *global scope* of the script has not. + var run_t = window.t.step_func(function() { + if (!win.eventOrder || win.eventOrder.length != 3) { + window.setTimeout(run_t, 100); + return; + } + window.assert_array_equals(win.eventOrder, ['inline script #1', 'external script #1', 'external script #2']); + window.t.done(); + }); + run_t(); + }); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/102.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/102.html new file mode 100644 index 0000000000..439023833f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/102.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: defer script after initial onload event</title> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script> + onload = function() { + document.open(); + document.write("<title> scheduler: defer script after initial onload event</title><script src='/resources/testharness.js'><\/script><script src='/resources/testharnessreport.js'><\/script><script src='testlib/testlib.js'><\/script><div id='log'>document.written content</div><script>var t = async_test(); log('inline script #1')<\/script><script src='scripts/include-1.js'><\/script><script async src='scripts/include-2.js'><\/script>"); + document.close(); + window.setTimeout(function() { + window.t.step(function() { + window.assert_any(window.assert_array_equals, window.eventOrder, + [['inline script #1', 'external script #1', 'external script #2'], + ['inline script #1', 'external script #2', 'external script #1']]); + window.t.done(); + })}, + 1000); + }; + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/103.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/103.html new file mode 100644 index 0000000000..f619472a4f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/103.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: removing defer attribute at runtime</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="test"></div> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script id="defer-script" defer src="scripts/include-2.js"></script> + <script src="scripts/include-1.js"></script> + + <script> + var t = async_test(); + + t.step(function() { + document.getElementById("defer-script").removeAttribute("defer"); + }); + + var ran_defer_check = false; + + document.addEventListener("readystatechange", t.step_func(function () { + if (document.readyState == "interactive") { + ran_defer_check = true; + assert_array_equals(eventOrder, ["external script #1"]); + } + }), false); + + addEventListener("load", t.step_func(function () { + assert_true(ran_defer_check); + assert_array_equals(eventOrder, ["external script #1", "external script #2"]); + t.done(); + }), false); + + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/104.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/104.html new file mode 100644 index 0000000000..95a5a22237 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/104.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: adding defer attribute at runtime</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="test"></div> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script id="defer-script" src="scripts/include-1.js"></script> + <script src="scripts/include-2.js"></script> + + <script> + var t = async_test(); + + t.step(function() { + document.getElementById("defer-script").setAttribute("defer", "defer"); + }); + + var ran_defer_check = false; + + document.addEventListener("readystatechange", t.step_func(function () { + if (document.readyState == "interactive") { + ran_defer_check = true; + assert_array_equals(eventOrder, ["external script #1", "external script #2"]); + } + }), false); + + addEventListener("load", t.step_func(function () { + assert_true(ran_defer_check); + assert_array_equals(eventOrder, ["external script #1", "external script #2"]); + t.done(); + }), false); + + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/105.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/105.html new file mode 100644 index 0000000000..19be9e1d03 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/105.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: adding async attribute at runtime</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script> + var t = async_test(); + + var sources = ["scripts/include-1.js?pipe=trickle(d2)", + "scripts/include-2.js"] + var scripts = sources.map(function(x) { + var script = document.createElement("script"); + script.src = x; + script.async = false; + document.body.appendChild(script); + return script; + }); + scripts[0].async = true; + + addEventListener("load", t.step_func(function () { + assert_array_equals(eventOrder, ["external script #1", "external script #2"]); + t.done(); + }), false); + + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-defer-import.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-defer-import.html new file mode 100644 index 0000000000..451e218ef7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-defer-import.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking defer scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/import.css?pipe=trickle(d2)"> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <script defer src="scripts/check-style-sheet.js"></script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-defer-noimport.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-defer-noimport.html new file mode 100644 index 0000000000..704b880bcf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-defer-noimport.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking defer scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/background.css?pipe=trickle(d2)"> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <script defer src="scripts/check-style-sheet.js"></script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-import.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-import.html new file mode 100644 index 0000000000..4fe526a274 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-import.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking external parser-blocking scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/import.css?pipe=trickle(d2)"> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <script src="scripts/check-style-sheet.js"></script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-module-import.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-module-import.html new file mode 100644 index 0000000000..ea873746e0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-module-import.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking external module scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/import.css?pipe=trickle(d2)"> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <script src="scripts/check-style-sheet.js" type="module"></script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-module-noimport.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-module-noimport.html new file mode 100644 index 0000000000..71c59fb4d6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-module-noimport.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking external module scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/background.css?pipe=trickle(d2)"> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <script src="scripts/check-style-sheet.js" type="module"></script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-noimport.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-noimport.html new file mode 100644 index 0000000000..3694481b86 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-external-noimport.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking external parser-blocking scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/background.css?pipe=trickle(d2)"> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <script src="scripts/check-style-sheet.js"></script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-import-xhtml.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-import-xhtml.xhtml new file mode 100644 index 0000000000..3b2e8b5296 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-import-xhtml.xhtml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Stylesheet in XHTML HEAD with @import blocking scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/import.css?pipe=trickle(d2)" /> +</head> +<body> + <div id="test">Test</div> + <script> + test(function() { + assert_equals(getComputedStyle(document.getElementById("test")).position, + "fixed"); + }); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-import.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-import.html new file mode 100644 index 0000000000..b8afeda135 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-import.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/import.css?pipe=trickle(d2)"> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <script> + test(function() { + assert_equals(getComputedStyle(document.getElementById("test")).position, + "fixed"); + }); + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-module-import.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-module-import.html new file mode 100644 index 0000000000..d3f02ffd19 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-module-import.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking module scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/import.css?pipe=trickle(d2)"> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <script type="module"> + test(function() { + assert_equals(getComputedStyle(document.getElementById("test")).position, + "fixed"); + }); + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-module-noimport.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-module-noimport.html new file mode 100644 index 0000000000..83cd29f267 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-module-noimport.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking module scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/background.css?pipe=trickle(d2)"> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <script type="module"> + test(function() { + assert_equals(getComputedStyle(document.getElementById("test")).position, + "fixed"); + }); + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-noimport-xhtml.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-noimport-xhtml.xhtml new file mode 100644 index 0000000000..1cae3c9965 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-noimport-xhtml.xhtml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Stylesheet in XHTML HEAD blocking scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/background.css?pipe=trickle(d2)" /> +</head> +<body> + <div id="test">Test</div> + <script> + test(function() { + assert_equals(getComputedStyle(document.getElementById("test")).position, + "fixed"); + }); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-noimport.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-noimport.html new file mode 100644 index 0000000000..bd8ec8633e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/106-noimport.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/background.css?pipe=trickle(d2)"> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <script> + test(function() { + assert_equals(getComputedStyle(document.getElementById("test")).position, + "fixed"); + }); + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/107-import.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/107-import.html new file mode 100644 index 0000000000..0b572b0724 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/107-import.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking scripts document.write</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <!-- this stylesheet blocks scripts --> + <script> + test(function() { + document.write("<link rel='stylesheet' href='css/import.css?pipe=trickle(d2)'>"); + // note that the pass condition here is not per spec (but does match implementations) as of 2012-06-26 + assert_equals(getComputedStyle(document.getElementById("test")).position, + "static"); + }); + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/107-noimport.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/107-noimport.html new file mode 100644 index 0000000000..ce57d1f1c5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/107-noimport.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: stylesheets blocking scripts document.write</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + + <!-- this stylesheet blocks scripts --> + <script> + test(function() { + document.write("<link rel='stylesheet' href='css/background.css?pipe=trickle(d2)'>"); + // note that the pass condition here is not per spec (but does match implementations) as of 2012-06-26 + assert_equals(getComputedStyle(document.getElementById("test")).position, + "static"); + }); + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/108.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/108.html new file mode 100644 index 0000000000..79be9721d2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/108.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: javascript URL in iframe</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + <div id="log">Not tested</div> + <script> + var t = async_test(); + var iframe_onload = false; + + t.step(function() { + log('inline script #1'); + document.write("<iframe src='javascript:void(top.log("iframe script #1"));'></iframe>"); + log('inline script #2') + }) + + onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "iframe script #1"]); + t.done(); + }); + </script> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/109.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/109.html new file mode 100644 index 0000000000..d103ffcbd7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/109.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: javascript URL in iframe, src set via DOM</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + <div id="log">Not tested</div> + <script> + var t = async_test(); + + t.step(function() { + var iframe_onload = false; + log("inline script #1"); + var iframe = document.createElement("iframe"); + iframe.src = "javascript:void(top.log('JS URL'));"; + log("inline script #2"); + iframe.onload = function () { log("iframe onload") }; + document.body.appendChild(iframe); + log("inline script #3"); + }) + + onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3", "JS URL", "iframe onload"]); + t.done(); + }); + </script> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/110.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/110.html new file mode 100644 index 0000000000..5affb9ed23 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/110.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: removing defer script at runtime</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="test"></div> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script id="defer-script" defer src="scripts/include-2.js"></script> + <script src="scripts/include-1.js"></script> + + <script> + var t = async_test(); + + t.step(function() { + var s = document.getElementById("defer-script"); + s.parentNode.removeChild(s); + }); + + addEventListener("load", t.step_func(function () { + assert_array_equals(eventOrder, ["external script #1", "external script #2"]); + t.done(); + }), false); + + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/111.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/111.html new file mode 100644 index 0000000000..c932a7b95c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/111.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: removing async attribute at runtime</title> + <meta name="timeout" content="long"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="test"></div> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script id="async-script" async src="scripts/include-2.js?pipe=trickle(d3)"></script> + + <script> + var t = async_test(); + + t.step(function() { + document.getElementById("async-script").removeAttribute("async"); + var s = document.createElement("script"); + s.async = false; + s.src = "scripts/include-1.js"; + document.body.appendChild(s); + }); + + addEventListener("load", t.step_func(function () { + assert_array_equals(eventOrder, ["external script #1", "external script #2"]); + t.done(); + }), false); + + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/112.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/112.html new file mode 100644 index 0000000000..a0cc647e0d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/112.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: removing async attribute at runtime, script also has defer attribute</title> + <meta name="timeout" content="long"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="test"></div> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script id="async-script" async defer src="scripts/include-1.js?pipe=trickle(d3)"></script> + + <script> + var t = async_test(); + document.getElementById("async-script").removeAttribute("async"); + + addEventListener("DOMContentLoaded", t.step_func(function () { + assert_array_equals(eventOrder, []); + }), false); + + addEventListener("load", t.step_func(function () { + assert_array_equals(eventOrder, ["external script #1"]); + t.done(); + }), false); + + </script> +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/113.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/113.html new file mode 100644 index 0000000000..32740be37e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/113.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: Altering DOM using innerHTML during parse </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="test"></div> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script> + var t = async_test(); + + addEventListener("load", t.step_func(function () { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2"]); + t.done(); + }), false); + + </script> + <div id="container"> + <script>t.step(function() { + log("inline script #1"); + document.getElementById("container").innerHTML = ""; + }); + </script> + <script>t.step(function() {log("inline script #2")});</script> + </div> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/114.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/114.html new file mode 100644 index 0000000000..ce3733208b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/114.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: Changing src of defer script before it runs </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="test"></div> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script id="defer-script" defer src="scripts/include-1.js"></script> + + <script> + var t = async_test(); + + document.getElementById("defer-script").src = "scripts/include-2.js" + + addEventListener("load", t.step_func(function () { + assert_array_equals(eventOrder, ["external script #1"]); + t.done(); + }), false); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/115.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/115.html new file mode 100644 index 0000000000..6234e02020 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/115.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html><head> + <title> scheduler: Removing src of defer script before it runs </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + + <div id="test"></div> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + + <script id="defer-script" defer src="scripts/include-1.js">t.step(function() {assert_unreached()})</script> + + <script> + var t = async_test(); + + document.getElementById("defer-script").removeAttribute("src"); + + addEventListener("load", t.step_func(function () { + assert_array_equals(eventOrder, ["external script #1"]); + t.done(); + }), false); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/116.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/116.html new file mode 100644 index 0000000000..62da398868 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/116.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: adding script to head of frameset document</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> + <script> + // add a script that looks for document.body as first child of HEAD + testlib.addScript('',{src:'scripts/find-body.js'},document.getElementsByTagName('head')[0], true ); + var div = document.createElement("div"); + div.id = "log"; + var t = async_test(); + function test() { + if(!(window.findBodyLoaded)) { + return setTimeout(t.step_func(test),200); + } + document.body.appendChild(div); + assert_array_equals(eventOrder, ['document.body: <FRAMESET>']); + t.done(); + } + onload = t.step_func(test) + </script> +</head> +<frameset> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/117.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/117.html new file mode 100644 index 0000000000..46a9900c94 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/117.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: inline script created with createContextualFragment</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> + <div id="log"></div> + <script> + log('inline script #1'); + var t = async_test(); + + t.step(function() { + var range = document.createRange(); + var fragment = range.createContextualFragment("<script>log('fragment script #1')<\/script>"); + document.body.appendChild(fragment.firstChild); + }); + + function test() { + assert_array_equals(eventOrder, ['inline script #1', 'fragment script #1', 'end inline script #1']); + t.done(); + } + onload = t.step_func(test) + log('end inline script #1'); + </script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/118.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/118.html new file mode 100644 index 0000000000..e002ea9601 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/118.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: external script created with createContextualFragment</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> + <div id="log"></div> + <script> + log('inline script #1'); + var t = async_test(); + + t.step(function() { + var range = document.createRange(); + var fragment = range.createContextualFragment("<script src='scripts/include-1.js'><\/script>"); + document.body.appendChild(fragment.firstChild); + }); + + addEventListener("load", t.step_func(function() { + assert_array_equals(eventOrder, ['inline script #1', 'end inline script #1', 'external script #1']); + t.done(); + }), false); + + log('end inline script #1'); + </script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/119.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/119.html new file mode 100644 index 0000000000..d1ed823093 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/119.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: external defer script created with createContextualFragment</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + <div id="log"></div> + <script> + log('inline script #1'); + var t = async_test(); + + t.step(function () { + var range = document.createRange(); + var fragment = range.createContextualFragment("<script defer src='scripts/include-1.js?pipe=trickle(d1)'><\/script>"); + document.body.appendChild(fragment.firstChild); + }); + + addEventListener("DOMContentLoaded", t.step_func(function () { + assert_array_equals(eventOrder, ['inline script #1', 'end inline script #1']); + })); + + addEventListener("load", t.step_func_done(function () { + assert_array_equals(eventOrder, ['inline script #1', 'end inline script #1', 'external script #1']); + })); + + log('end inline script #1'); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/120.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/120.html new file mode 100644 index 0000000000..2cfe5221dd --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/120.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: script created without a window </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); + + var doc = document.implementation.createHTMLDocument(""); + doc.write("<script>t.step(function() {assert_unreached()})<\/script>"); + + document.body.appendChild(doc.head.firstChild); + + onload = function() {t.done()} +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/121.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/121.html new file mode 100644 index 0000000000..d6de27025f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/121.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: altering the type attribute </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<script id="test" type="text/plain">t.step(function() {assert_unreached()}</script> +<script> +t.step(function() { + document.getElementById("test").removeAttribute("type"); + setTimeout(t.step_func(function() {t.done()}), 100); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/122.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/122.html new file mode 100644 index 0000000000..a8994c6aeb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/122.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: altering the type attribute and adding/removing external script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<script id="test" type="text/plain" src="scripts/include-1.js?pipe=trickle(d1)"></script> +<script> +t.step(function() { + var script = document.getElementById("test"); + script.removeAttribute("type"); + var marker = document.createElement("script"); + marker.src = "scripts/include-2.js?pipe=trickle(d2)"; + marker.async = false; + script.parentNode.appendChild(marker); + script.parentNode.appendChild(script); + test(function() {assert_true(script.async)}, "Reinserted script async IDL attribute"); +}); +onload = t.step_func(function () { + assert_array_equals(eventOrder, ["external script #1", "external script #2"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/123.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/123.html new file mode 100644 index 0000000000..dc145eb550 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/123.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: altering the type attribute and adding/removing external script with async=false </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<script id="test" type="text/plain" src="scripts/include-2.js?pipe=trickle(d1)"></script> +<script> +t.step(function() { + var script = document.getElementById("test"); + script.removeAttribute("type"); + script.async = false; + var marker = document.createElement("script"); + marker.src = "scripts/include-1.js?pipe=trickle(d2)"; + marker.async = false; + script.parentNode.appendChild(marker); + script.parentNode.appendChild(script); +}); +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["external script #1", "external script #2"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/124.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/124.html new file mode 100644 index 0000000000..5c7208dfde --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/124.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: altering the type attribute and changing script data inline script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<script id="test" type="text/plain">t.step(function() {log("inline script #1")});</script> +<script> +t.step(function() { + log("inline script #2"); + var script = document.getElementById("test"); + script.removeAttribute("type"); + script.appendChild(document.createTextNode("")); + log("end inline script #2"); +}); +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #2", "inline script #1", "end inline script #2"]); + t.done(); +}) +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/125.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/125.html new file mode 100644 index 0000000000..5074f2a107 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/125.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: altering the type attribute and changing script data external script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<script id="test" type="text/plain" src="scripts/include-1.js?pipe=trickle(d1)"></script> +<script> +t.step(function() { + var script = document.getElementById("test"); + script.removeAttribute("type"); + var marker = document.createElement("script"); + marker.src = "scripts/include-2.js?pipe=trickle(d2)"; + marker.async = false; + script.parentNode.appendChild(marker); + script.appendChild(document.createTextNode("")); +}); + +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["external script #1", "external script #2"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/126.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/126.html new file mode 100644 index 0000000000..1b2bb17634 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/126.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: altering the type attribute and changing script data external script async=false </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<script id="test" type="text/plain" src="scripts/include-2.js"></script> +<script> +t.step(function() { + var script = document.getElementById("test"); + script.removeAttribute("type"); + script.async = false; + var marker = document.createElement("script"); + marker.src = "scripts/include-1.js?pipe=trickle(d2)"; + marker.async = false; + script.parentNode.appendChild(marker); + script.appendChild(document.createTextNode("")); +}); + +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["external script #1", "external script #2"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/127.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/127.html new file mode 100644 index 0000000000..149078a327 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/127.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: appending non-text children to script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<script id="test"></script> +<script> +t.step(function() { + log("inline script #1"); + var script = document.getElementById("test"); + + var frag = document.createDocumentFragment(); + var div = document.createElement("div"); + + div.textContent = "assert_unreached();" + frag.appendChild(document.createTextNode("t.step(function() {log('inline script #2');\n")); + frag.appendChild(div); + frag.appendChild(document.createTextNode("log('end inline script #2');})")); + + script.appendChild(frag); + log("end inline script #1"); +}); + +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "end inline script #2", "end inline script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/128.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/128.html new file mode 100644 index 0000000000..39ec24f681 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/128.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: appending script element to script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<script id="test"></script> +<script> +t.step(function() { + log("inline script #1"); + var script = document.getElementById("test"); + + var frag = document.createDocumentFragment(); + var inner_script = document.createElement("script"); + + inner_script.textContent = "t.step(function() {log('inline script #3');});" + frag.appendChild(document.createTextNode("t.step(function() {log('inline script #2');\n")); + frag.appendChild(inner_script); + frag.appendChild(document.createTextNode("log('end inline script #2');})")); + + script.appendChild(frag); + log("end inline script #1"); +}); + +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #3", "inline script #2", "end inline script #2", "end inline script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/129.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/129.html new file mode 100644 index 0000000000..8c12735677 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/129.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: appending multiple script elements</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<div id="container"></div> +<script> +t.step(function() { + log("inline script #1"); + + var frag = document.createDocumentFragment(); + + scripts = ["2", "3", "4"].map(function(x) { + var s = document.createElement("script"); + s.textContent = "t.step(function() {log('inline script #" + x + "')});"; + return s + }); + + + frag.appendChild(scripts[0]); + var div = document.createElement(div); + div.appendChild(scripts[1]); + frag.appendChild(div); + frag.appendChild(scripts[2]); + + document.getElementById("container").appendChild(frag); + log("end inline script #1"); +}); + +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3", "inline script #4", "end inline script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/130.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/130.html new file mode 100644 index 0000000000..c6643d9fdf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/130.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: appending external script element to script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<script id="test"></script> +<script> +t.step(function() { + log("inline script #1"); + var script = document.getElementById("test"); + + var frag = document.createDocumentFragment(); + var inner_script = document.createElement("script"); + + inner_script.src = "scripts/include-1.js?pipe=trickle(d1)"; + frag.appendChild(document.createTextNode("t.step(function() {log('inline script #2');\n")); + frag.appendChild(inner_script); + frag.appendChild(document.createTextNode("log('end inline script #2');})")); + + script.appendChild(frag); + log("end inline script #1"); +}); + +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "end inline script #2", "end inline script #1", "external script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/131.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/131.html new file mode 100644 index 0000000000..541483ed6b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/131.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: inline svg script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); + log("inline script #1") +</script> +<svg> +<script>log("inline script #2")</script> +</svg> +<script> +log("inline script #3"); +t.step(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/132.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/132.html new file mode 100644 index 0000000000..3edb959594 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/132.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: external svg script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); + log("inline script #1") +</script> +<svg> +<script xlink:href="scripts/include-1.js"></script> +</svg> +<script> +log("inline script #2"); +t.step(function() { + assert_array_equals(eventOrder, ["inline script #1", "external script #1", "inline script #2"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/133.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/133.html new file mode 100644 index 0000000000..e6b327f709 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/133.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: inline HTML script added by SVG script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); + log("inline script #1") +</script> +<svg> +<script> +log("inline script #2") +var s = document.createElement("script"); +s.textContent = "log('inline script #3');"; +document.getElementsByTagName("svg")[0].appendChild(s); +log("end inline script #2"); +</script> +</svg> +<script> +log("inline script #4"); +t.step(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3", + "end inline script #2", "inline script #4"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/134.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/134.html new file mode 100644 index 0000000000..bb2ad4f66b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/134.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: external HTML script added by SVG script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); + log("inline script #1") +</script> +<svg> +<script> +log("inline script #2") +var s = document.createElement("script"); +s.src = "scripts/include-1.js" +document.getElementsByTagName("svg")[0].appendChild(s); +log("end inline script #2"); +</script> +</svg> +<script> +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", + "end inline script #2", "external script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/135.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/135.html new file mode 100644 index 0000000000..dd8b895218 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/135.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: external SVG script added by SVG script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); + log("inline script #1") +</script> +<svg> +<script> +log("inline script #2") +var s = document.createElementNS("http://www.w3.org/2000/svg", "script"); +s.setAttributeNS("http://www.w3.org/1999/xlink", "href", "scripts/include-1.js"); +document.getElementsByTagName("svg")[0].appendChild(s); +log("end inline script #2"); +</script> +</svg> +<script> +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", + "end inline script #2", "external script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/136.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/136.html new file mode 100644 index 0000000000..b08a8b9798 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/136.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: DOM added external SVG script, force-async? </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<svg> +<script> + +var s1 = document.createElement("script"); +s1.src = "scripts/include-1.js"; +s1.async = false; + +var s = document.createElementNS("http://www.w3.org/2000/svg", "script"); +s.setAttributeNS("http://www.w3.org/1999/xlink", "href", "scripts/include-2.js?pipe=trickle(d2)"); + +document.getElementsByTagName("svg")[0].appendChild(s); +document.getElementsByTagName("svg")[0].appendChild(s1); + +</script> +</svg> +<script> +onload = t.step_func(function() { + <!-- assumes that the SVg script should be async --> + assert_array_equals(eventOrder, ["external script #1", "external script #2"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/137.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/137.html new file mode 100644 index 0000000000..35a49b806d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/137.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: SVG script empty xlink:href</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<svg> +<script xlink:href=""> +t.step(function() {assert_unreached()}); +</script> +</svg> +<script> +onload = t.step_func(function() { + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/138.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/138.html new file mode 100644 index 0000000000..0ff25471e0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/138.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: SVG script nested inlines</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<svg> +<script> +t.step(function() { +log("inline script #2"); +var a = { + <script> + t.step(function() {log("inline script #1")}) + </script> +a:1} +log("end inline script #2"); +}); +</script> +</svg> +<script> +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "end inline script #2"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/139.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/139.html new file mode 100644 index 0000000000..7bb703d8a2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/139.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: SVG script nested external in inline</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<svg> +<script> +t.step(function() { +log("inline script #1"); +var a = { + <script xlink:href="scripts/include-1.js"> + t.step(function() {assert_unreached()}) + </script> +a:1} +log("end inline script #1"); +}); +</script> +</svg> +<script> +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["external script #1", "inline script #1", "end inline script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/140.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/140.html new file mode 100644 index 0000000000..9b54d09d58 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/140.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: SVG script nested inline in external</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<svg> +<script xlink:href="scripts/include-1.js"> + <script> + t.step(function() {log("inline script #1")}); + </script> +</script> +</svg> +<script> +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "external script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/141.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/141.html new file mode 100644 index 0000000000..54aa3f3686 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/141.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: SVG inline script that document.writes inline script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<svg> +<script> + t.step(function() { + log('inline script #1'); + document.write("<" + "script>t.step(function() {log('inline script #2')})<" + "/script>"); + log('end inline script #1'); + }); +</script> +</svg> +<script> +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "end inline script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/142.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/142.html new file mode 100644 index 0000000000..d314eddb90 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/142.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: SVG inline script that document.writes external script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<svg> +<script> + t.step(function() { + log('inline script #1'); + document.write("<" + "script xlink:href='scripts/include-1.js'><" + "/script>"); + log('end inline script #1'); + }); +</script> +<script>t.step(function() {log("inline script #2")});</script> +</svg> +<script> +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "end inline script #1", "external script #1", "inline script #2"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/143.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/143.html new file mode 100644 index 0000000000..a0d9012f68 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/143.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: SVG nested inline script that document.writes inline script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<svg> +<script> + t.step(function() { + log('inline script #3'); + }); + <script> + log("inline script #1") + document.write("<" + "script>t.step(function() {log('inline script #2')})<" + "/script><" + "/script>"); + </script> + t.step(function() { + assert_unreached(): + }); +</script> +</svg> +<script> +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/144.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/144.html new file mode 100644 index 0000000000..3962c4d692 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/144.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: SVG inline script changing the type attribute </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<svg> +<script type="text/plain"> +t.step(function() {assert_unreached()}); +</script> +</svg> +<script> +t.step(function() { + var s = document.querySelector("svg > script"); + s.textContent = "t.step(function() {log('inline script #1')})"; + s.type = ""; + s.parentNode.appendChild(s); +}); +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/145.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/145.html new file mode 100644 index 0000000000..9e2d73bafc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/145.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: SVG inline script adding text to empty script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script> + var t = async_test(); +</script> +<svg> +<script></script> +</svg> +<script> +t.step(function() { + var s = document.querySelector("svg > script"); + s.textContent = "t.step(function() {log('inline script #1')})"; +}); +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/146-href.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/146-href.html new file mode 100644 index 0000000000..6c0869db54 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/146-href.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: SVG script adding src attribute </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script>var t = async_test();</script> +<svg> +<script></script> +</svg> +<script> +t.step(function() { + var s = document.querySelector("svg > script"); + s.setAttribute("href", "scripts/include-1.js"); +}); +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["external script #1"]); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/146.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/146.html new file mode 100644 index 0000000000..333ac3fa0f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/146.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: SVG script adding src attribute </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<div id="log"></div> +<script>var t = async_test();</script> +<svg> +<script></script> +</svg> +<script> +t.step(function() { + var s = document.querySelector("svg > script"); + s.src = "scripts/include-1.js"; +}); +onload = t.step_func(function() { + // SVG <script> element uses href attribute, so src attribute is ignored. + assert_array_equals(eventOrder, []); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/147.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/147.html new file mode 100644 index 0000000000..07dc4d97c9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/147.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: insert multiple inline scripts; first script moves subsequent scripts </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> +<div id="log"></div> +<script> +var t = async_test(); +</script> +<div id="container"></div> +<script> +t.step(function() { + log("inline script #1"); + var container = document.getElementById("container"); + + var frag = document.createDocumentFragment(); + var frag_script_1 = document.createElement("script"); + var frag_script_2 = document.createElement("script"); + frag_script_2.id = "movee"; + var frag_script_3 = document.createElement("script"); + + frag_script_1.textContent = "t.step(function() {log('inline script #2'); var s = document.getElementById('movee'); s.parentNode.appendChild(s)});"; + frag_script_2.textContent = "t.step(function() {log('inline script #3');})"; + frag_script_3.textContent = "t.step(function() {log('inline script #4');})"; + + [frag_script_1, frag_script_2, frag_script_3].forEach(function(x) {frag.appendChild(x)}); + + container.appendChild(frag); +}); + +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3", "inline script #4"]); + t.done(); +}); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/148.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/148.html new file mode 100644 index 0000000000..e2da8e8f0b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/148.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: insert multiple inline scripts; first script deletes subsequent script </title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> +<div id="log"></div> +<script> +var t = async_test(); +</script> +<div id="container"></div> +<script> +t.step(function() { + log("inline script #1"); + var container = document.getElementById("container"); + + var frag = document.createDocumentFragment(); + var frag_script_1 = document.createElement("script"); + var frag_script_2 = document.createElement("script"); + frag_script_2.id = "delete"; + var frag_script_3 = document.createElement("script"); + + frag_script_1.textContent = "t.step(function() {log('inline script #2'); var s = document.getElementById('delete'); s.parentNode.removeChild(s)});"; + frag_script_2.textContent = "t.step(function() {log('inline script #3');})"; + frag_script_3.textContent = "t.step(function() {log('inline script #4');})"; + + [frag_script_1, frag_script_2, frag_script_3].forEach(function(x) {frag.appendChild(x)}); + + container.appendChild(frag); +}); + +onload = t.step_func(function() { + assert_array_equals(eventOrder, ["inline script #1", "inline script #2", "inline script #3", "inline script #4"]); + t.done(); +}); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/149.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/149.html new file mode 100644 index 0000000000..40594d8048 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/149.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<html><head> + <title>scheduler: event/for attribute on script</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> +<div id="log"></div> +<script> + +attributes = [ + {for:"window", event:"onload()", expect:true}, + {for:"window", event:"onload", expect:true}, + {for:" WINdow\t\n", event:"ONload\t\n", expect:true}, + {for:"window", event:"load", expect:false}, + {for:"window", event:"onpageshow", expect:false}, + {for:"document", event:"onload", expect:false}, +] + +function test_maker(array_name) { + return function(x, i) { + var title = "for='" + x.for + "' event='" + x.event + "' " + array_name.replace("_", " ") + " " + (x.expect ? "executes immediately" : "does not execute"); + script_content = "var d =" + array_name + "[" + i + "];" + script_content += x.expect?"d[1].step(function() {d[3] = true});":"d[1].step(function() {assert_unreached()});" + return [x, async_test(title), script_content, false]; + } +} + +parser_inserted = attributes.map(test_maker("parser_inserted")); +dom_inserted = attributes.map(test_maker("dom_inserted")); + +parser_inserted.forEach(function(x) { + var d = x[0]; + document.write("<script for='" + d.for + "' event='" + d.event + "'>" + x[2] + "<\/script>"); +}); + +dom_inserted.forEach(function(x) { + var d = x[0]; + var s = document.createElement("script"); + s.setAttribute("event", d.event); + s.setAttribute("for", d.for); + s.textContent = x[2]; + document.body.appendChild(s); +}); +</script> + +<script> +var all_tests = parser_inserted.concat(dom_inserted); + +all_tests.filter(function(x) {return x[0]["expect"]}).forEach(function(x) {var t = x[1]; t.step(function() {assert_true(x[3])});}) + +onload = function() { + all_tests.forEach(function(x) {var t = x[1]; t.step(function() {t.done()})}); +} +</script> + +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-import-xhtml.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-import-xhtml.xhtml new file mode 100644 index 0000000000..d6144795db --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-import-xhtml.xhtml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Stylesheet in XHTML BODY with @import blocking scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + <div id="log">FAILED (This TC requires JavaScript enabled)</div> + <div id="test">Test</div> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/import.css?pipe=trickle(d2)" /> + <script> + test(function() { + assert_equals(getComputedStyle(document.getElementById("test")).position, + "fixed"); + }); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-import.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-import.html new file mode 100644 index 0000000000..40223ed104 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-import.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<head> + <title>Stylesheet in BODY with @import blocking scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + <div id="test">Test</div> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/import.css?pipe=trickle(d2)"> + <script> + test(function() { + assert_equals(getComputedStyle(document.getElementById("test")).position, + "fixed"); + }); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-noimport-xhtml.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-noimport-xhtml.xhtml new file mode 100644 index 0000000000..fa587a2ddb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-noimport-xhtml.xhtml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Stylesheet in XHTML BODY blocking scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + <div id="test">Test</div> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/background.css?pipe=trickle(d2)" /> + <script> + test(function() { + assert_equals(getComputedStyle(document.getElementById("test")).position, + "fixed"); + }); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-noimport.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-noimport.html new file mode 100644 index 0000000000..b5829d4da5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/150-noimport.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> +<head> + <title>Stylesheet in BODY blocking scripts</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="testlib/testlib.js"></script> +</head> +<body> + <div id="test">Test</div> + <!-- this stylesheet blocks scripts --> + <link rel="stylesheet" href="css/background.css?pipe=trickle(d2)"> + <script> + test(function() { + assert_equals(getComputedStyle(document.getElementById("test")).position, + "fixed"); + }); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/css/background.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/css/background.css new file mode 100644 index 0000000000..86a155b811 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/css/background.css @@ -0,0 +1 @@ +#test {position:fixed}
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/css/import.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/css/import.css new file mode 100644 index 0000000000..d1664c29a1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/css/import.css @@ -0,0 +1 @@ +@import url("background.css")
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/non-external-no-import.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/non-external-no-import.html new file mode 100644 index 0000000000..50836e0d7b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/non-external-no-import.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html> +<head> + <title>Module scripts with no imports always execute asynchronously</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <link rel="help" href="https://github.com/whatwg/html/issues/3746"> +</head> +<body> +<script> +async_test(t => { + window.results = []; + window.logExecution = msg => window.results.push(msg); + + const script = document.createElement('script'); + script.type = 'module'; + script.textContent = "window.logExecution('module')"; + document.body.append(script); + window.logExecution('classic'); + + window.onload = t.step_func_done(e => { + assert_array_equals(window.results, ['classic', 'module']); + }); +}); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/pages/helloworld-postMessage.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/pages/helloworld-postMessage.html new file mode 100644 index 0000000000..2ed8731ceb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/pages/helloworld-postMessage.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html><head> + <title> TC component </title> +</head> +<body> + + <p>This page should appear in popup or frame</p> + + <script type="text/javascript"> + var target = opener || top; + var id = location.search?' '+location.search.substring(1) : ''; + target.log('frame/popup script'+id); + window.onload=function(){ + target.log('load event inside frame/popup script'+id); + target.postMessage('msg evt frame/popup script'+id, '*'); + } + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/pages/helloworld.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/pages/helloworld.html new file mode 100644 index 0000000000..271bc8f569 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/pages/helloworld.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html><head> + <title> TC component </title> +</head> +<body> + + <p>This page should appear in popup or frame</p> + + <script type="text/javascript"> + var target = top || opener; + var id = location.search?' '+parseInt(location.search.substring(1)) : ''; + target.log('frame/popup script'+id); + </script> + +</body></html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/check-style-sheet.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/check-style-sheet.js new file mode 100644 index 0000000000..cbab154f5a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/check-style-sheet.js @@ -0,0 +1,4 @@ +test(function() { + assert_equals(getComputedStyle(document.getElementById("test")).position, + "fixed"); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/count-script-tags.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/count-script-tags.js new file mode 100644 index 0000000000..8fba4ecb3c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/count-script-tags.js @@ -0,0 +1 @@ +log('script tags in DOM: '+document.getElementsByTagName('script').length);
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/find-body.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/find-body.js new file mode 100644 index 0000000000..1ce198f13e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/find-body.js @@ -0,0 +1,4 @@ +log( + 'document.body: ' + + (document.body ? '<' + document.body.localName.toUpperCase() + '>' : null)); +var findBodyLoaded=true; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/find-foo.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/find-foo.js new file mode 100644 index 0000000000..52d0ec91cb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/find-foo.js @@ -0,0 +1,2 @@ +log('found #foo element: ' + ( document.getElementById('foo') ? 'YES' : 'NO' )); +var findFooLoaded=true;
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-1.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-1.js new file mode 100644 index 0000000000..8ff291ad57 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-1.js @@ -0,0 +1 @@ +log('external script #1');
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-10.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-10.js new file mode 100644 index 0000000000..8dc770ddc0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-10.js @@ -0,0 +1 @@ +document.write("<script src='scripts/include-9.js?pipe=trickle(d2)' defer></script>"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-11.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-11.js new file mode 100644 index 0000000000..016913c4b8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-11.js @@ -0,0 +1,4 @@ +log("external script before adding iframe"); +var iframe = document.createElement("iframe"); +iframe.srcdoc = "<script>parent.log('script in iframe')</script>" +document.body.appendChild(iframe); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-2.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-2.js new file mode 100644 index 0000000000..31319423af --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-2.js @@ -0,0 +1 @@ +log('external script #2');
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-3.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-3.js new file mode 100644 index 0000000000..53352e0f83 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-3.js @@ -0,0 +1,3 @@ +log('external script before doc write'); +document.write( '<script>log(\'document.write external script\');</script>'); +log('external script after doc write');
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-4.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-4.js new file mode 100644 index 0000000000..0597a22624 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-4.js @@ -0,0 +1,3 @@ +log('include-4 before doc write'); +document.write( '<script src="scripts/include-3.js"></script>'); +log('include-4 after doc write');
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-5.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-5.js new file mode 100644 index 0000000000..52952d7379 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-5.js @@ -0,0 +1,7 @@ +log('include-5 before removing scripts'); +var scripts=[].slice.call(document.getElementsByTagName('script'), 3); +for(var i = 0; i < scripts.length; i++) { + var s = scripts[i]; + s.parentNode.removeChild(s); +} +log('include-5 after removing scripts'); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-6.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-6.js new file mode 100644 index 0000000000..77da2af232 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-6.js @@ -0,0 +1,6 @@ +top.log( + 'external script (#foo found? ' + + (document.getElementById('foo') ? 'YES' : 'NO' ) + + ')' +); +top.include6Loaded=true;
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-7.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-7.js new file mode 100644 index 0000000000..57c5508015 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-7.js @@ -0,0 +1 @@ +log('external script #7');
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-8.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-8.js new file mode 100644 index 0000000000..960f2129fe --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-8.js @@ -0,0 +1,4 @@ +log("external script #8"); +var s = document.createElement("script") +s.src='scripts/include-9.js?pipe=trickle(d2)' +document.body.appendChild(s); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-9.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-9.js new file mode 100644 index 0000000000..9042882024 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/scripts/include-9.js @@ -0,0 +1,2 @@ +log("external script #9"); +test();
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/testlib/testlib.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/testlib/testlib.js new file mode 100644 index 0000000000..a6fd39426b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/testlib/testlib.js @@ -0,0 +1,43 @@ +/* +* Utility functions for script scheduler test +*/ +(function(){ /* namespace hiding local variables like arOrderOfAllEvents from global scope */ + window.testlib = {}; + window.eventOrder = []; + var arNumberOfScriptsParsedPerEvent=[]; + window.log = function (str){ + eventOrder.push(str); + arNumberOfScriptsParsedPerEvent.push(document.getElementsByTagName('script').length); + } + + window.testlib.addScript = function(source, attributes, parent, firstInParent,funcPrepare) { + try{ + parent = parent||document.body; + var script = document.createElement('script'); + if(funcPrepare) { + funcPrepare(script); + } + if(source)script.appendChild( document.createTextNode(source) ); + for( var name in attributes){ + if(/^on/i.test(name)) { + script[name] = attributes[name]; + } else { + script.setAttribute(name, attributes[name]); + } + } + if (firstInParent && parent.firstChild) { + parent.insertBefore(script, parent.firstChild); + } else { + parent.appendChild(script); + } + } catch(e) { + log('ERROR when adding script to DOM!'); + alert(e); + } + return script; + } + + window.testlib.urlParam = function(relativeURL) { + return location.href.replace( /\d*\.html$/, relativeURL); + } +})(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/external-script-utf8.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/external-script-utf8.js new file mode 100644 index 0000000000..eb442c97bc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/external-script-utf8.js @@ -0,0 +1,5 @@ +(function() { + window.getSomeString = function() { + return "śćążź"; //<- these are five Polish letters, similar to scazz. It can be read correctly only with windows 1250 encoding. + }; +})(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/external-script-windows1250.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/external-script-windows1250.js new file mode 100644 index 0000000000..50de6932ba --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/external-script-windows1250.js @@ -0,0 +1,5 @@ +(function() { + window.getSomeString = function() { + return "œæ¹¿Ÿ"; //<- these are five Polish letters, similar to scazz. It can be read correctly only with windows 1250 encoding. + }; +})(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/alpha/base.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/alpha/base.html new file mode 100644 index 0000000000..dc0fa9dabb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/alpha/base.html @@ -0,0 +1,15 @@ +<!doctype html> +<meta charset=utf-8> +<title>Script src with a base URL</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<base href=../beta/> +<div id=log></div> +<script> +function do_test(path) { + test(function() { + assert_equals(path, "beta"); + }); +} +</script> +<script src=test.js></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/alpha/test.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/alpha/test.js new file mode 100644 index 0000000000..3cbbb12e2e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/alpha/test.js @@ -0,0 +1 @@ +do_test("alpha"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/beta/test.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/beta/test.js new file mode 100644 index 0000000000..4ce0f5338d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/beta/test.js @@ -0,0 +1 @@ +do_test("beta"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/empty-with-base.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/empty-with-base.html new file mode 100644 index 0000000000..edc2c3d6f8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/empty-with-base.html @@ -0,0 +1,27 @@ +<!doctype html> +<meta charset=utf-8> +<title>Script src with an empty URL</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<base href=unreachable.js> +<div id=log></div> +<script> +async_test(function(t) { + window.unreachable = this.unreached_func("Should not load unreachable.js"); + var queued = false; + var script = document.createElement("script"); + script.onerror = this.step_func_done(function(ev) { + assert_equals(ev.type, "error"); + assert_false(ev.bubbles, "bubbles"); + assert_false(ev.cancelable, "cancelable"); + assert_true(ev.isTrusted, "isTrusted"); + assert_equals(ev.target, script); + assert_true(ev instanceof Event, "instanceof Event"); + assert_class_string(ev, "Event"); + assert_true(queued, "event should not be dispatched synchronously"); + }); + script.setAttribute("src", ""); + document.body.appendChild(script); + queued = true; +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/empty.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/empty.html new file mode 100644 index 0000000000..d127f1eb3b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/empty.html @@ -0,0 +1,32 @@ +<!doctype html> +<meta charset=utf-8> +<title>Script src with an empty URL</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +// For a better error message in case the UA tries to load "" (which resolves +// to this document). +setup({ + "allow_uncaught_exception": true, +}); +async_test(function(t) { + window.onerror = this.unreached_func("Should not get an error reported to " + + "the window before the script"); + var queued = false; + var script = document.createElement("script"); + script.onerror = this.step_func_done(function(ev) { + assert_equals(ev.type, "error"); + assert_false(ev.bubbles, "bubbles"); + assert_false(ev.cancelable, "cancelable"); + assert_true(ev.isTrusted, "isTrusted"); + assert_equals(ev.target, script); + assert_true(ev instanceof Event, "instanceof Event"); + assert_class_string(ev, "Event"); + assert_true(queued, "event should not be dispatched synchronously"); + }); + script.setAttribute("src", ""); + document.body.appendChild(script); + queued = true; +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/failure.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/failure.html new file mode 100644 index 0000000000..b49e51740f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/failure.html @@ -0,0 +1,25 @@ +<!doctype html> +<meta charset=utf-8> +<title>Script src with an invalid URL</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div id=log></div> +<script> +async_test(function(t) { + var queued = false; + var script = document.createElement("script"); + script.onerror = this.step_func_done(function(ev) { + assert_equals(ev.type, "error"); + assert_false(ev.bubbles, "bubbles"); + assert_false(ev.cancelable, "cancelable"); + assert_true(ev.isTrusted, "isTrusted"); + assert_equals(ev.target, script); + assert_true(ev instanceof Event, "instanceof Event"); + assert_class_string(ev, "Event"); + assert_true(queued, "event should not be dispatched synchronously"); + }); + script.setAttribute("src", "//[]"); + document.body.appendChild(script); + queued = true; +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/unreachable.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/unreachable.js new file mode 100644 index 0000000000..ca7fdba71f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/fetch-src/unreachable.js @@ -0,0 +1 @@ +unreachable(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/historical.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/historical.html new file mode 100644 index 0000000000..1f1a91228c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/historical.html @@ -0,0 +1,53 @@ +<!doctype html> +<title>Historical script element features should not be supported</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +function t(property) { + test(function() { + assert_false(property in document.createElement('script')); + }, 'script.' + property + ' should not be supported'); +} +// added in https://github.com/whatwg/html/commit/69f83cf2eacf4543860ccb7abab0ff5bb1e8b594 +// removed in https://github.com/whatwg/html/commit/1a0b5e8377d59462e05a5cffda4b8592324a2785 +t('onbeforescriptexecute'); +t('onafterscriptexecute'); + +var t_onbeforescriptexecute_attr = async_test('onbeforescriptexecute content attribute should not be supported'); +var t_onafterscriptexecute_attr = async_test('onafterscriptexecute content attribute should not be supported'); +var t_beforescriptexecute_event = async_test(function() { + addEventListener('beforescriptexecute', this.step_func(function() { + assert_unreached(); + }), true); +}, 'beforescriptexecute event should not be supported'); +var t_afterscriptexecute_event = async_test(function() { + addEventListener('afterscriptexecute', this.step_func(function() { + assert_unreached(); + }), true); +}, 'afterscriptexecute event should not be supported'); + +var a = false; + +onload = function() { + t_onbeforescriptexecute_attr.step(function() { + assert_true(a); + this.done(); + }); + t_onafterscriptexecute_attr.step(function() { + assert_true(a); + this.done(); + }); + t_beforescriptexecute_event.step(function() { + assert_true(a); + this.done(); + }); + t_afterscriptexecute_event.step(function() { + assert_true(a); + this.done(); + }); +}; +</script> +<script onbeforescriptexecute="t_onbeforescriptexecute_attr.step(function() { assert_unreached(); });" + onafterscriptexecute="t_onafterscriptexecute_attr.step(function() { assert_unreached(); });"> +a = true; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/dynamic-import-with-assertion-argument.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/dynamic-import-with-assertion-argument.any.js new file mode 100644 index 0000000000..7efb2050b7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/dynamic-import-with-assertion-argument.any.js @@ -0,0 +1,18 @@ +// META: global=window,dedicatedworker,sharedworker + +promise_test(async test => { + const result = await import("./export-hello.js", { assert: { } }); + assert_equals(result.default, "hello"); +}, "Dynamic import with an empty assert clause should succeed"); + +promise_test(async test => { + return promise_rejects_js(test, TypeError, + import("./export-hello.js", { assert: { unsupportedAssertionKey: "unsupportedAssertionValue"} }), + "Dynamic import with an unsupported import assertion should fail"); +}, "Dynamic import with an unsupported import assertion should fail"); + +promise_test(test => { + return promise_rejects_js(test, TypeError, + import("./export-hello.js", { assert: { type: "notARealType"} } ), + "Dynamic import with an unsupported type assertion should fail"); +}, "Dynamic import with an unsupported type assertion should fail"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/empty-assertion-clause.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/empty-assertion-clause.html new file mode 100644 index 0000000000..3a7c371189 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/empty-assertion-clause.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<title>Handling of empty import assertion clause</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that no error occurs when an empty import assertion clause is provided."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(window.log, ["hello", "empty-assertion-clause"]); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./empty-assertion-clause.js" onerror="unreachable()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/empty-assertion-clause.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/empty-assertion-clause.js new file mode 100644 index 0000000000..6913dd61df --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/empty-assertion-clause.js @@ -0,0 +1,2 @@ +import "./hello.js" assert { }; +log.push("empty-assertion-clause"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/empty-type-assertion.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/empty-type-assertion.js new file mode 100644 index 0000000000..5bb9b1ddb8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/empty-type-assertion.js @@ -0,0 +1,2 @@ +import "./hello.js#2" assert { type: "" }; +log.push("empty-type-assertion"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/export-hello.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/export-hello.js new file mode 100644 index 0000000000..34b58e6e12 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/export-hello.js @@ -0,0 +1 @@ +export default "hello"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/hello.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/hello.js new file mode 100644 index 0000000000..2f34844460 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/hello.js @@ -0,0 +1 @@ +log.push("hello");
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/invalid-import-errors-order.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/invalid-import-errors-order.html new file mode 100644 index 0000000000..17c95faea0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/invalid-import-errors-order.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<title>Handling of invalid module type import attributes</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + var log = []; + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that the errors order for invalid import declarations is" + + " specifier, then attribute key, and then type attribute value."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 3); + assert_equals(log[0].constructor, SyntaxError); + assert_equals(log[1].constructor, SyntaxError); + assert_equals(log[2].constructor, SyntaxError); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" onerror="unreachable()"> + // unknown attribute is reported before invalid specifier + import "INVALID" assert { unknown: "foo" }; +</script> +<script type="module" onerror="unreachable()"> + // unknown attribute is reported before unknown type + import "./valid" assert { unknown: "foo", type: "unknown" }; +</script> +<script type="module" onerror="unreachable()"> + // unknown attribute is reported before invalid specifier in subsequent import + import "./valid" assert { unknown: "foo" }; + import "INVALID"; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/invalid-type-assertion-error.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/invalid-type-assertion-error.html new file mode 100644 index 0000000000..0adcc47569 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/invalid-type-assertion-error.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Handling of invalid module type import assertions</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that invalid module type assertion leads to TypeError on window."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 4); + assert_equals(log[0].constructor, TypeError); + assert_equals(log[1].constructor, TypeError); + assert_equals(log[2].constructor, TypeError); + assert_equals(log[3].constructor, TypeError); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./invalid-type-assertion.js" onerror="unreachable()"></script> +<script type="module" src="./empty-type-assertion.js" onerror="unreachable()"></script> +<script type="module" src="./js-type-assertion.js" onerror="unreachable()"></script> +<script type="module" src="./javascript-type-assertion.js" onerror="unreachable()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/invalid-type-assertion.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/invalid-type-assertion.js new file mode 100644 index 0000000000..e28c0176d5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/invalid-type-assertion.js @@ -0,0 +1,2 @@ +import "./hello.js#1" assert { type: "notARealType" }; +log.push("invalid-type-assertion"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/javascript-type-assertion.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/javascript-type-assertion.js new file mode 100644 index 0000000000..cc0f531026 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/javascript-type-assertion.js @@ -0,0 +1,2 @@ +import "./hello.js#4" assert { type: "javascript" }; +log.push("javascript-type-assertion"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/js-type-assertion.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/js-type-assertion.js new file mode 100644 index 0000000000..c649c95ffe --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/js-type-assertion.js @@ -0,0 +1,2 @@ +import "./hello.js#3" assert { type: "js" }; +log.push("js-type-assertion"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/unsupported-assertion.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/unsupported-assertion.html new file mode 100644 index 0000000000..72977347a7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/unsupported-assertion.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<title>Handling of unsupported assertion</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that invalid module assertion leads to SyntaxError on window."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 1); + assert_equals(log[0].constructor, SyntaxError); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./unsupported-assertion.js" onerror="unreachable()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/unsupported-assertion.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/unsupported-assertion.js new file mode 100644 index 0000000000..45f6d60c9d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-assertions/unsupported-assertion.js @@ -0,0 +1,2 @@ +import "./hello.js" assert { unsupportedAssertionKey: "unsupportedAssertionValue" }; +log.push("unsupported-assertion"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/dynamic-import-with-attributes-argument.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/dynamic-import-with-attributes-argument.any.js new file mode 100644 index 0000000000..2addb0fcb9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/dynamic-import-with-attributes-argument.any.js @@ -0,0 +1,18 @@ +// META: global=window,dedicatedworker,sharedworker + +promise_test(async test => { + const result = await import("./export-hello.js", { with: { } }); + assert_equals(result.default, "hello"); +}, "Dynamic import with an empty with clause should succeed"); + +promise_test(async test => { + return promise_rejects_js(test, TypeError, + import("./export-hello.js", { with: { unsupportedAssertionKey: "unsupportedAssertionValue"} }), + "Dynamic import with an unsupported import attribute should fail"); +}, "Dynamic import with an unsupported import attribute should fail"); + +promise_test(test => { + return promise_rejects_js(test, TypeError, + import("./export-hello.js", { with: { type: "notARealType"} } ), + "Dynamic import with an unsupported type attribute should fail"); +}, "Dynamic import with an unsupported type attribute should fail"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/empty-attributes-clause.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/empty-attributes-clause.html new file mode 100644 index 0000000000..0a8868b2f4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/empty-attributes-clause.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<title>Handling of empty import attributes clause</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that no error occurs when an empty import attributes clause is provided."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(window.log, ["hello", "empty-attributes-clause"]); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./empty-attributes-clause.js" onerror="unreachable()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/empty-attributes-clause.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/empty-attributes-clause.js new file mode 100644 index 0000000000..98c4573179 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/empty-attributes-clause.js @@ -0,0 +1,2 @@ +import "./hello.js" with { }; +log.push("empty-attributes-clause"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/empty-type-attribute.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/empty-type-attribute.js new file mode 100644 index 0000000000..72272b5102 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/empty-type-attribute.js @@ -0,0 +1,2 @@ +import "./hello.js#2" with { type: "" }; +log.push("empty-type-assertion"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/export-hello.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/export-hello.js new file mode 100644 index 0000000000..34b58e6e12 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/export-hello.js @@ -0,0 +1 @@ +export default "hello"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/hello.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/hello.js new file mode 100644 index 0000000000..2f34844460 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/hello.js @@ -0,0 +1 @@ +log.push("hello");
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/invalid-import-errors-order.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/invalid-import-errors-order.html new file mode 100644 index 0000000000..8c438f626b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/invalid-import-errors-order.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<title>Handling of invalid module type import attributes</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + var log = []; + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that the errors order for invalid import declarations is" + + " specifier, then attribute key, and then type attribute value."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 3); + assert_equals(log[0].constructor, SyntaxError); + assert_equals(log[1].constructor, SyntaxError); + assert_equals(log[2].constructor, SyntaxError); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" onerror="unreachable()"> + // unknown attribute is reported before invalid specifier + import "INVALID" with { unknown: "foo" }; +</script> +<script type="module" onerror="unreachable()"> + // unknown attribute is reported before unknown type + import "./valid" with { unknown: "foo", type: "unknown" }; +</script> +<script type="module" onerror="unreachable()"> + // unknown attribute is reported before invalid specifier in subsequent import + import "./valid" with { unknown: "foo" }; + import "INVALID"; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/invalid-type-attribute-error.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/invalid-type-attribute-error.html new file mode 100644 index 0000000000..ac6d61a642 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/invalid-type-attribute-error.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Handling of invalid module type import attributes</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that invalid module type attribute leads to TypeError on window."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 4); + assert_equals(log[0].constructor, TypeError); + assert_equals(log[1].constructor, TypeError); + assert_equals(log[2].constructor, TypeError); + assert_equals(log[3].constructor, TypeError); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./invalid-type-attribute.js" onerror="unreachable()"></script> +<script type="module" src="./empty-type-attribute.js" onerror="unreachable()"></script> +<script type="module" src="./js-type-attribute.js" onerror="unreachable()"></script> +<script type="module" src="./javascript-type-attribute.js" onerror="unreachable()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/invalid-type-attribute.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/invalid-type-attribute.js new file mode 100644 index 0000000000..10e35b6b56 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/invalid-type-attribute.js @@ -0,0 +1,2 @@ +import "./hello.js#1" with { type: "notARealType" }; +log.push("invalid-type-attribute"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/javascript-type-attribute.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/javascript-type-attribute.js new file mode 100644 index 0000000000..568db18196 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/javascript-type-attribute.js @@ -0,0 +1,2 @@ +import "./hello.js#4" with { type: "javascript" }; +log.push("javascript-type-attribute"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/js-type-attribute.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/js-type-attribute.js new file mode 100644 index 0000000000..b7a454b4f2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/js-type-attribute.js @@ -0,0 +1,2 @@ +import "./hello.js#3" with { type: "js" }; +log.push("js-type-attribute"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/unsupported-attribute.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/unsupported-attribute.html new file mode 100644 index 0000000000..3656e465ce --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/unsupported-attribute.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<title>Handling of unsupported attribute</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that invalid module attribute leads to SyntaxError on window."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 1); + assert_equals(log[0].constructor, SyntaxError); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./unsupported-attribute.js" onerror="unreachable()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/unsupported-attribute.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/unsupported-attribute.js new file mode 100644 index 0000000000..2fc6829cfb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/import-attributes/unsupported-attribute.js @@ -0,0 +1,2 @@ +import "./hello.js" with { unsupportedAttributeKey: "unsupportedAttributeValue" }; +log.push("unsupported-attribute"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/is-module-goal.mjs b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/is-module-goal.mjs new file mode 100644 index 0000000000..b533fc2e90 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/is-module-goal.mjs @@ -0,0 +1 @@ +import "./serve-with-content-type.py?fn=is-module-goal.mjs&ct=text%2Fjavascript%3Bgoal=module";
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/is-script-goal.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/is-script-goal.js new file mode 100644 index 0000000000..069363dd40 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/is-script-goal.js @@ -0,0 +1,3 @@ +with ({}) { + ; +};
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/array.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/array.json new file mode 100644 index 0000000000..e77e32d338 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/array.json @@ -0,0 +1 @@ +["en", "try"] diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/bom-utf-16be.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/bom-utf-16be.json Binary files differnew file mode 100644 index 0000000000..d22a45a591 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/bom-utf-16be.json diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/bom-utf-16le.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/bom-utf-16le.json Binary files differnew file mode 100644 index 0000000000..4d1aa264a6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/bom-utf-16le.json diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/bom-utf-8.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/bom-utf-8.json new file mode 100644 index 0000000000..07ba933e86 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/bom-utf-8.json @@ -0,0 +1 @@ +{ "data": "hello" }
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/charset-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/charset-2.html new file mode 100644 index 0000000000..686178bfe1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/charset-2.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset="windows-1250"> +<title>JSON modules: UTF-8 decoding</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script type="module"> + import json from "../serve-with-content-type.py?fn=json-module-assertions/utf-8.json" assert { type: "json"}; + test(() => { + assert_equals(json.data, "śćążź"); + }, "JSON module should be loaded as utf-8 even though document's encoding is windows-1250"); +</script> +<script type="module"> + import json from "../serve-with-content-type.py?fn=json-module-assertions/windows-1250.json&ct=text/json%3Bcharset=windows-1250" assert { type: "json"}; + test(() => { + assert_not_equals(json.data, "śćążź", + 'Should be decoded as UTF-8'); + }, "JSON module should be loaded as utf-8 even if it is encoded in windows-1250 and served with a windows-1250 charset response header, and this document's encoding is windows-1250"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/charset-bom.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/charset-bom.any.js new file mode 100644 index 0000000000..d2dbe3e468 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/charset-bom.any.js @@ -0,0 +1,17 @@ +// META: global=window,dedicatedworker,sharedworker +// META: script=/common/utils.js + +promise_test(async () => { + const jsonModule = await import('./bom-utf-8.json', { assert: { type: 'json' } }); + assert_equals(jsonModule.default.data, 'hello'); +}, 'UTF-8 BOM should be stripped when decoding JSON module script'); + +promise_test(async test => { + await promise_rejects_js(test, SyntaxError, + import('./bom-utf-16be.json', { assert: { type: 'json' } }), 'Expected parse error from UTF-16BE BOM'); +}, 'UTF-16BE BOM should result in parse error in JSON module script'); + +promise_test(async test => { + await promise_rejects_js(test, SyntaxError, + import('./bom-utf-16le.json', { assert: { type: 'json' } }), 'Expected parse error from UTF-16LE BOM'); +}, 'UTF-16LE BOM should result in parse error in JSON module script'); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/charset.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/charset.html new file mode 100644 index 0000000000..7c74b9bf6c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/charset.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>JSON modules: UTF-8 decoding</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script type="module" onerror="unreachable()"> + import json from "../serve-with-content-type.py?fn=json-module-assertions/utf-8.json&ct=text/json%3Bcharset=utf-8" assert { type: "json"}; + test(() => { + assert_equals(json.data, "śćążź"); + }, "JSON module should be loaded as utf-8 when charset=utf8 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import json from "../serve-with-content-type.py?fn=json-module-assertions/utf-8.json&ct=text/json%3Bcharset=shift-jis" assert { type: "json"}; + test(() => { + assert_equals(json.data, "śćążź"); + }, "JSON module should be loaded as utf-8 when charset=shift-jis is specified"); +</script> +<script type="module" onerror="unreachable()"> + import json from "../serve-with-content-type.py?fn=json-module-assertions/utf-8.json&ct=text/json%3Bcharset=windows-1252" assert { type: "json"}; + test(() => { + assert_equals(json.data, "śćążź"); + }, "JSON module should be loaded as utf-8 when charset=windows-1252 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import json from "../serve-with-content-type.py?fn=json-module-assertions/utf-8.json&ct=text/json%3Bcharset=utf-7" assert { type: "json"};; + test(() => { + assert_equals(json.data, "śćążź"); + }, "JSON module should be loaded as utf-8 when charset=utf-7 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import json from "../serve-with-content-type.py?fn=json-module-assertions/windows-1250.json&ct=text/json%3Bcharset=windows-1250" assert { type: "json"}; + test(() => { + assert_not_equals(json.data, "śćążź", + 'Should be decoded as UTF-8'); + }, "JSON module should be loaded as utf-8 even if it is encoded in windows-1250 and served with a windows-1250 charset response header"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/cors-crossorigin-requests.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/cors-crossorigin-requests.html new file mode 100644 index 0000000000..757af2901c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/cors-crossorigin-requests.html @@ -0,0 +1,33 @@ +<!doctype html> +<html> +<head> + <title>json-module-assertions-crossorigin</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <h1>json-module-assertions-crossorigin</h1> + <iframe id="import-WithCORS" src="crossorigin-import-with-cors.sub.html"></iframe> + <iframe id="import-NoCORS" src="crossorigin-import-without-cors.sub.html"></iframe> + <iframe id="import-parseerror-WithCors" src="crossorigin-import-parse-error-with-cors.sub.html"></iframe> + <script> + + var tests = [ + { "obj": async_test("Imported JSON module, cross-origin with CORS"), "id": "import-WithCORS", "expected": "imported JSON: 42" }, + { "obj": async_test("Imported JSON module, cross-origin, missing CORS ACAO header"), "id": "import-NoCORS", "expected": "error" }, + { "obj": async_test("Imported JSON module with parse error, cross-origin, with CORS"), "id": "import-parseerror-WithCors", "expected": "0-0" }, + ]; + + window.addEventListener("load", function () { + tests.forEach(function (test) { + var target = document.getElementById(test.id); + test.obj.step(function () { + assert_equals(target.contentDocument._log, test.expected, "Unexpected _log value"); + }); + test.obj.done(); + }); + }); + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/credentials-iframe.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/credentials-iframe.sub.html new file mode 100644 index 0000000000..44e6402faa --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/credentials-iframe.sub.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<meta charset="utf-8"> + +<script type="module"> + import json from "./cross-origin.py?id=sameOriginNoneDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "json" }; + window.sameOriginNoneDescendant = json.requestHadCookies; +</script> +<script type="module" crossOrigin="anonymous"> + import json from "./cross-origin.py?id=sameOriginAnonymousDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "json" }; + window.sameOriginAnonymousDescendant = json.requestHadCookies; +</script> +<script type="module" crossOrigin="use-credentials"> + import json from "./cross-origin.py?id=sameOriginUseCredentialsDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "json" }; + window.sameOriginUseCredentialsDescendant = json.requestHadCookies; +</script> +<script type="module"> + import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module-assertions/cross-origin.py?id=crossOriginNoneDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "json" }; + window.crossOriginNoneDescendant = json.requestHadCookies; +</script> +<script type="module" crossOrigin="anonymous"> + import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module-assertions/cross-origin.py?id=crossOriginAnonymousDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "json" }; + window.crossOriginAnonymousDescendant = json.requestHadCookies; +</script> +<script type="module" crossOrigin="use-credentials"> +import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module-assertions/cross-origin.py?id=crossOriginUseCredentialsDescendant&origin=http://{{host}}:{{ports[http][0]}}" assert { type: "json" }; +window.crossOriginUseCredentialsDescendant = json.requestHadCookies; +</script> + +<script type="text/javascript"> +window.addEventListener('load', event => { + window.parent.postMessage({}, '*'); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/credentials.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/credentials.sub.html new file mode 100644 index 0000000000..d11d2f9589 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/credentials.sub.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +document.cookie = 'milk=1'; + +const setCookiePromise = fetch( + 'http://{{domains[www2]}}:{{ports[http][0]}}/cookies/resources/set-cookie.py?name=milk&path=/html/semantics/scripting-1/the-script-element/json-module-assertions/', + { + mode: 'no-cors', + credentials: 'include', + }); + +const windowLoadPromise = new Promise(resolve => { + window.addEventListener('load', () => { + resolve(); + }); +}); + +promise_test(t => { + const iframe = document.createElement('iframe'); + + return Promise.all([setCookiePromise, windowLoadPromise]).then(() => { + const messagePromise = new Promise(resolve => { + window.addEventListener('message', event => { + resolve(); + }); + }); + + iframe.src = 'credentials-iframe.sub.html'; + document.body.appendChild(iframe); + + return messagePromise; + }).then(() => { + const w = iframe.contentWindow; + + assert_equals(w.sameOriginNoneDescendant, true, + 'Descendant JSON modules should be loaded with the credentials when the crossOrigin attribute is not specified and the target is same-origin'); + assert_equals(w.sameOriginAnonymousDescendant, true, + 'Descendant JSON modules should be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is same-origin'); + assert_equals(w.sameOriginUseCredentialsDescendant, true, + 'Descendant JSON modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is same-origin'); + assert_equals(w.crossOriginNoneDescendant, false, + 'Descendant JSON modules should not be loaded with the credentials when the crossOrigin attribute is not specified and the target is cross-origin'); + assert_equals(w.crossOriginAnonymousDescendant, false, + 'Descendant JSON modules should not be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is cross-origin'); + assert_equals(w.crossOriginUseCredentialsDescendant, true, + 'Descendant JSON modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is cross-origin'); +}); +}, 'JSON Modules should be loaded with or without the credentials based on the same-origin-ness and the crossOrigin attribute'); +</script> +<body> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/cross-origin.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/cross-origin.py new file mode 100644 index 0000000000..cd56c3628a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/cross-origin.py @@ -0,0 +1,16 @@ +def main(request, response): + + headers = [ + (b"Content-Type", b"application/json"), + (b"Access-Control-Allow-Origin", request.GET.first(b"origin")), + (b"Access-Control-Allow-Credentials", b"true") + ] + + milk = request.cookies.first(b"milk", None) + + if milk is None: + return headers, u'{"requestHadCookies": false}' + elif milk.value == b"1": + return headers, u'{"requestHadCookies": true}' + + return headers, u'{"requestHadCookies": false}' diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/crossorigin-import-parse-error-with-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/crossorigin-import-parse-error-with-cors.sub.html new file mode 100644 index 0000000000..7d044f8579 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/crossorigin-import-parse-error-with-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>json-module-assertions-import-cross-domain-parse-error-WithCORS</title> + <script src="../module/crossorigin-common.js"></script> +</head> +<body> + <h1>json-module-assertions-import-cross-domain-parse-error-WithCORS</h1> + <script type="module" crossorigin> + import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module-assertions/parse-error.json?pipe=header(Access-Control-Allow-Origin,*)" assert { type: "json" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported JSON: ${json.answer}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/crossorigin-import-with-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/crossorigin-import-with-cors.sub.html new file mode 100644 index 0000000000..d71938dae4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/crossorigin-import-with-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>json-module-assertions-import-cross-domain-WithCORS</title> + <script src="../module/crossorigin-common.js"></script> +</head> +<body> + <h1>json-module-assertions-import-cross-domain-WithCORS</h1> + <script type="module" crossorigin> + import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module-assertions/data.json?pipe=header(Access-Control-Allow-Origin,*)" assert { type: "json" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported JSON: ${json.answer}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/crossorigin-import-without-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/crossorigin-import-without-cors.sub.html new file mode 100644 index 0000000000..9d07d6c727 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/crossorigin-import-without-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>json-module-assertions-import-cross-domain-NoCORS</title> + <script src="../module/crossorigin-common.js"></script> +</head> +<body> + <h1>json-module-assertions-import-cross-domain-NoCORS</h1> + <script type="module" onerror="document._log.push('error');"> + import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module-assertions/data.json" assert { type: "json" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported JSON: ${json.answer}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/data.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/data.json new file mode 100644 index 0000000000..14a0526ebb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/data.json @@ -0,0 +1,3 @@ +{ + "answer": 42 +}
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/false.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/false.json new file mode 100644 index 0000000000..c508d5366f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/false.json @@ -0,0 +1 @@ +false diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/integrity-matches.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/integrity-matches.js new file mode 100644 index 0000000000..969c90c290 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/integrity-matches.js @@ -0,0 +1,2 @@ +import json from "./data.json" assert { type: "json" }; +window.matchesLog.push(`integrity-matches,json:${json.answer}`); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/integrity-mismatches.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/integrity-mismatches.js new file mode 100644 index 0000000000..3c88a98dbc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/integrity-mismatches.js @@ -0,0 +1,2 @@ +import json "./data.json" assert { type: "json" }; +window.mismatchesLog.push(`integrity-mismatches,json:${json.answer}`); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/integrity.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/integrity.html new file mode 100644 index 0000000000..68a794b973 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/integrity.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title><script> integrity=""</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +window.matchesLog = []; +window.matchesEvents = []; + +window.mismatchesLog = []; +window.mismatchesEvents = []; +</script> +<script type="module" src="integrity-matches.js" integrity="sha384-VmQQfGzBiLKdyzw4FA4kL4ohu4tyujV68ddgW1aN/1v3cBZNNBn2gDFdVQxfL7+a" onload="window.matchesEvents.push('load');" onerror="window.matchesEvents.push('error')"></script> +<script type="module" src="integrity-mismatches.js" integrity="sha384-doesnotmatch" onload="window.mismatchesEvents.push('load');" onerror="window.mismatchesEvents.push('error')"></script> + +<script type="module"> +test(() => { + assert_array_equals(window.matchesLog, ["integrity-matches,json:42"], "The module and its dependency must have executed"); + assert_array_equals(window.matchesEvents, ["load"], "The load event must have fired"); +}, "The integrity attribute must be verified on the top-level of a module loading a JSON module and allow it to execute when it matches"); + +test(() => { + assert_array_equals(window.mismatchesLog, [], "The module and its dependency must not have executed"); + assert_array_equals(window.mismatchesEvents, ["error"], "The error event must have fired"); +}, "The integrity attribute must be verified on the top-level of a module loading a JSON module and not allow it to execute when there's a mismatch"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/invalid-content-type.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/invalid-content-type.any.js new file mode 100644 index 0000000000..cbccbd4842 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/invalid-content-type.any.js @@ -0,0 +1,17 @@ +// META: global=window,dedicatedworker,sharedworker + +const content_types = [ + "application/json+protobuf", + "application/json+blah", + "text/x-json", + "text/json+blah", + "application/blahjson", + "image/json", +]; +for (const content_type of content_types) { + promise_test(async test => { + await promise_rejects_js(test, TypeError, + import(`./module.json?pipe=header(Content-Type,${content_type})`, { assert: { type: "json"} }), + `Import of a JSON module with MIME type ${content_type} should fail`); + }, `Try importing JSON module with MIME type ${content_type}`); +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/json-module-service-worker-test.https.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/json-module-service-worker-test.https.html new file mode 100644 index 0000000000..cc47da1499 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/json-module-service-worker-test.https.html @@ -0,0 +1,29 @@ +<!doctype html> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> + promise_test(async (test) => { + const reg = await navigator.serviceWorker.register('./serviceworker.js', { type: 'module' }); + test.add_cleanup(() => reg.unregister()); + assert_not_equals(reg.installing, undefined); + }, "Javascript importing JSON Module should load within the context of a service worker"); + + promise_test(test => { + return promise_rejects_dom(test, "SecurityError", + navigator.serviceWorker.register('./module.json', { type: 'module' }), + "Attempting to load JSON as a service worker should fail"); + }, "Trying to register a service worker with a top-level JSON Module should fail"); + + promise_test(async (test) => { + const reg = await navigator.serviceWorker.register('./serviceworker-dynamic-import.js', { type: 'module' }); + test.add_cleanup(() => reg.unregister()); + assert_not_equals(reg.installing, undefined); + reg.installing.postMessage("PING"); + const msgEvent = await new Promise(resolve => { + navigator.serviceWorker.onmessage = resolve; + }); + assert_equals(msgEvent.data, "FAILED"); + }, "JSON Module dynamic import should not load within the context of a service worker"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/load-error-events.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/load-error-events.html new file mode 100644 index 0000000000..a9dfc1e691 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/load-error-events.html @@ -0,0 +1,67 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<head> +<title>load/error events for JSON modules</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/load-error-events-helpers.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +</head> +<script> + "use strict"; + + var test1_load = event_test('inline, 200, parser-inserted', false, false); + var test1_error = event_test('inline, 404, parser-inserted', false, true); + + var test2_load = event_test('src, 200, parser-inserted', true, false); + var test2_error = event_test('src, 404, parser-inserted', false, true); + + var test3_dynamic_load = event_test('src, 200, not parser-inserted', true, false); + var test3_dynamic_error = event_test('src, 404, not parser-inserted', false, true); + + var test4_dynamic_load = event_test('inline, 200, not parser-inserted', false, false); + var test4_dynamic_error = event_test('inline, 404, not parser-inserted', false, true); + + var script3_dynamic_load = document.createElement('script'); + script3_dynamic_load.setAttribute('type', 'module'); + script3_dynamic_load.onload = () => onLoad(test3_dynamic_load); + script3_dynamic_load.onerror = () => onError(test3_dynamic_load); + script3_dynamic_load.src = "./load-error-events.py?test=test3_dynamic_load"; + document.head.appendChild(script3_dynamic_load); + + var script3_dynamic_error = document.createElement('script'); + script3_dynamic_error.setAttribute('type', 'module'); + script3_dynamic_error.onload = () => onLoad(test3_dynamic_error); + script3_dynamic_error.onerror = () => onError(test3_dynamic_error); + script3_dynamic_error.src = "./load-error-events.py?test=test3_dynamic_error"; + document.head.appendChild(script3_dynamic_error); + + var script4_dynamic_load = document.createElement('script'); + script4_dynamic_load.setAttribute('type', 'module'); + script4_dynamic_load.onload = () => onLoad(test4_dynamic_load); + script4_dynamic_load.onerror = () => onError(test4_dynamic_load); + script4_dynamic_load.async = true; + script4_dynamic_load.appendChild(document.createTextNode(` + import "./module.json" assert { type: "json" }; + onExecute(test4_dynamic_load);` + )); + document.head.appendChild(script4_dynamic_load); + + var script4_dynamic_error = document.createElement('script'); + script4_dynamic_error.setAttribute('type', 'module'); + script4_dynamic_error.onload = () => onLoad(test4_dynamic_error); + script4_dynamic_error.onerror = () => onError(test4_dynamic_error); + script4_dynamic_error.async = true; + script4_dynamic_error.appendChild(document.createTextNode(`import "./not_found.json" assert { type: "json" };`)); + document.head.appendChild(script4_dynamic_error); +</script> +<script onload="onLoad(test1_load);" onerror="onError(test1_load);" type="module"> + import "./module.json" assert { type: "json"}; + onExecute(test1_load); +</script> +<script onload="onLoad(test1_error);" onerror="onError(test1_error);" type="module"> + import "./not_found.json" assert { type: "json"}; + onExecute(test1_error); +</script> +<script src="./load-error-events.py?test=test2_load" onload="onLoad(test2_load);" onerror="onError(test2_load);" type="module"></script> +<script src="./load-error-events.py?test=test2_error" onload="onLoad(test2_error);" onerror="onError(test2_error);" type="module"></script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/load-error-events.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/load-error-events.py new file mode 100644 index 0000000000..4018adcdf7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/load-error-events.py @@ -0,0 +1,14 @@ +import re + +def main(request, response): + headers = [(b"Content-Type", b"text/javascript")] + test = request.GET.first(b'test') + assert(re.match(b'^[a-zA-Z0-9_]+$', test)) + + status = 200 + if test.find(b'_load') >= 0: + content = b'import "./module.json" assert { type: "json"}; %s.executed = true;' % test + else: + content = b'import "./not_found.json" assert { type: "json"}; %s.test.step(function() { assert_unreached("404 script should not be executed"); });' % test + + return status, headers, content diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/module.html new file mode 100644 index 0000000000..a495d4ac18 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/module.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>JSON modules</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +const t = async_test(); +</script> +<script type="module" onerror="t.step(() => assert_unreached(event))"> +import v from "./module.json" assert { type: "json" }; +t.step(() => { + assert_equals(typeof v, "object"); + assert_array_equals(Object.keys(v), ["test"]); + assert_equals(v.test, true); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/module.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/module.json new file mode 100644 index 0000000000..f834b2a4e8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/module.json @@ -0,0 +1,3 @@ +{ + "test": true +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/non-object.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/non-object.any.js new file mode 100644 index 0000000000..37fbcae9fa --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/non-object.any.js @@ -0,0 +1,14 @@ +// META: global=window,dedicatedworker,sharedworker + +for (const value of [null, true, false, "string"]) { + promise_test(async t => { + const result = await import(`./${value}.json`, { assert: { type: "json" } }); + assert_equals(result.default, value); + }, `Non-object: ${value}`); +} + +promise_test(async t => { + const result = await import("./array.json", { assert: { type: "json" } }); + assert_array_equals(result.default, ["en", "try"]); +}, "Non-object: array"); + diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/null.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/null.json new file mode 100644 index 0000000000..19765bd501 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/null.json @@ -0,0 +1 @@ +null diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/parse-error.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/parse-error.html new file mode 100644 index 0000000000..9d0e3284fe --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/parse-error.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>JSON modules: parse error</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +setup({ + allow_uncaught_exception: true, +}); +async_test(t => { + window.addEventListener("error", t.step_func_done(e => { + assert_true(e instanceof ErrorEvent, "ErrorEvent"); + assert_equals(e.filename, new URL("parse-error.json", location).href); + assert_true(e.error instanceof SyntaxError, "SyntaxError"); + })); +}); +</script> +<script type="module"> +import v from "./parse-error.json" assert { type: "json" }; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/parse-error.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/parse-error.json new file mode 100644 index 0000000000..98232c64fc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/parse-error.json @@ -0,0 +1 @@ +{ diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/referrer-checker.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/referrer-checker.py new file mode 100644 index 0000000000..e9f0f1789b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/referrer-checker.py @@ -0,0 +1,6 @@ +def main(request, response): + referrer = request.headers.get(b"referer", b"") + response_headers = [(b"Content-Type", b"application/json"), + (b"Access-Control-Allow-Origin", b"*")] + return (200, response_headers, + b'{"referrer": "' + referrer + b'"}') diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/referrer-policies.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/referrer-policies.sub.html new file mode 100644 index 0000000000..655c962ab7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/referrer-policies.sub.html @@ -0,0 +1,84 @@ +<!DOCTYPE html> +<html> +<head> +<title>Referrers with JSON module requests</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> + // "name" parameter is necessary for bypassing the module map. + import referrerSame from "./referrer-checker.py?name=sameNoReferrerPolicy" assert { type: "json"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module-assertions/referrer-checker.py?name=remoteNoReferrerPolicy" assert { type: "json"}; + + const origin = (new URL(location.href)).origin + "/"; + const originUrl = location.href; + + test(t => { + assert_equals( + referrerSame.referrer, originUrl, + "Referrer URL should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the default referrer policy."); + + test(t => { + assert_equals( + referrerRemote.referrer, origin, + "Referrer origin should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the default referrer policy."); +</script> +<script type="module" referrerpolicy="origin"> + import referrerSame from "./referrer-checker.py?name=sameReferrerPolicyOrigin" assert { type: "json"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module-assertions/referrer-checker.py?name=remoteReferrerPolicyOrigin" assert { type: "json"}; + + const origin = (new URL(location.href)).origin + "/"; + + test(t => { + assert_equals( + referrerSame.referrer, origin, + "Referrer origin should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the origin policy."); + + test(t => { + assert_equals( + referrerRemote.referrer, origin, + "Referrer origin should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the origin policy."); + +</script> +<script type="module" referrerpolicy="no-referrer"> + import referrerSame from "./referrer-checker.py?name=sameReferrerPolicyNoReferrer" assert { type: "json"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module-assertions/referrer-checker.py?name=remoteReferrerPolicyNoReferrer" assert { type: "json"}; + + test(t => { + assert_equals( + referrerSame.referrer, "", + "No referrer should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the no-referrer policy."); + + test(t => { + assert_equals( + referrerRemote.referrer, "", + "No referrer should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the no-referrer policy."); + +</script> +<script type="module" referrerpolicy="unsafe-url"> + import referrerSame from "./referrer-checker.py?name=sameNoReferrerPolicyUnsafeUrl" assert { type: "json"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module-assertions/referrer-checker.py?name=remoteNoReferrerPolicyUnsafeUrl" assert { type: "json"}; + + const originUrl = location.href; + + test(t => { + assert_equals( + referrerSame.referrer, originUrl, + "Referrer URL should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the unsafe-url referrer policy."); + + test(t => { + assert_equals( + referrerRemote.referrer, originUrl, + "Referrer URL should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the unsafe-url referrer policy."); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/repeated-imports.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/repeated-imports.any.js new file mode 100644 index 0000000000..5cc3ee5b7c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/repeated-imports.any.js @@ -0,0 +1,65 @@ +// META: global=window,dedicatedworker,sharedworker +// META: script=/common/utils.js + +promise_test(async test => { + await promise_rejects_js(test, TypeError, + import("./module.json"), + "Dynamic import of a JSON module without a type assertion should fail"); + + // This time the import should succeed because we're using the correct + // import even though the previous attempt with the same specifier failed. + const result = await import("./module.json", { assert: { type: "json" } }); + assert_true(result.default.test); +}, "Importing a specifier that previously failed due to an incorrect type assertion can succeed if the correct assertion is later given"); + +promise_test(async test => { + // Append a URL fragment to the specifier so that this is independent + // from the previous test. + const result = await import("./module.json#2", { assert: { type: "json" } }); + assert_true(result.default.test); + + await promise_rejects_js(test, TypeError, + import("./module.json#2"), + "Dynamic import should fail with the type assertion missing even if the same specifier previously succeeded"); +}, "Importing a specifier that previously succeeded with the correct type assertion should fail if the incorrect assertion is later given"); + +promise_test(async test => { + const uuid_token = token(); + // serve-json-then-js.py gives us JSON the first time + const result_json = await import(`../serve-json-then-js.py?key=${uuid_token}`, { assert: { type: "json" } }); + assert_equals(result_json.default.hello, "world"); + + // Import using the same specifier again; this time we get JS, which + // should succeed since we're not asserting a non-JS type this time. + const result_js = await import(`../serve-json-then-js.py?key=${uuid_token}`); + assert_equals(result_js.default, "hello"); +}, "Two modules of different type with the same specifier can load if the server changes its responses"); + +promise_test(async test => { + const uuid_token = token(); + // serve-json-then-js.py gives us JSON the first time + await promise_rejects_js(test, TypeError, + import(`../serve-json-then-js.py?key=${uuid_token}`), + "Dynamic import of JS with a JSON type assertion should fail"); + + // Import using the same specifier/module type pair again; this time we get JS, + // but the import should still fail because the module map entry for this + // specifier/module type pair already contains a failure. + await promise_rejects_js(test, TypeError, + import(`../serve-json-then-js.py?key=${uuid_token}`), + "import should always fail if the same specifier/type assertion pair failed previously"); +}, "An import should always fail if the same specifier/type assertion pair failed previously"); + +promise_test(async test => { + const uuid_token = token(); + // serve-json-then-js.py gives us JSON the first time + const result_json = await import(`../serve-json-then-js.py?key=${uuid_token}`, { assert: { type: "json" } }); + assert_equals(result_json.default.hello, "world"); + + // If this were to do another fetch, the import would fail because + // serve-json-then-js.py would give us JS this time. But, the module map + // entry for this specifier/module type pair already exists, so we + // successfully reuse the entry instead of fetching again. + const result_json_2 = await import(`../serve-json-then-js.py?key=${uuid_token}`, { assert: { type: "json" } }); + assert_equals(result_json_2.default.hello, "world"); +}, "If an import previously succeeded for a given specifier/type assertion pair, future uses of that pair should yield the same result"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/script-element-json-src.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/script-element-json-src.html new file mode 100644 index 0000000000..c6d7c9a76e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/script-element-json-src.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<title><script> with JSON src</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test that <script> doesn't load when the src is JSON."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, ["error"]); + })); +</script> +<script type="module" src="./module.json" onload="t.unreached_func('JSON src should fail to load')" onerror="log.push('error')"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/serviceworker-dynamic-import.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/serviceworker-dynamic-import.js new file mode 100644 index 0000000000..9466c6fbe4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/serviceworker-dynamic-import.js @@ -0,0 +1,5 @@ +onmessage = e => { + e.waitUntil(import("./module.json", { assert: { type: "json" } }) + .then(module => e.source.postMessage("LOADED")) + .catch(error => e.source.postMessage("FAILED"))); + };
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/serviceworker.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/serviceworker.js new file mode 100644 index 0000000000..3f0a4d1664 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/serviceworker.js @@ -0,0 +1 @@ +import './module.json' assert { type: "json" };
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/string.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/string.json new file mode 100644 index 0000000000..ace2d72d9d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/string.json @@ -0,0 +1 @@ +"string" diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/true.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/true.json new file mode 100644 index 0000000000..27ba77ddaf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/true.json @@ -0,0 +1 @@ +true diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/utf-8.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/utf-8.json new file mode 100644 index 0000000000..088d982358 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/utf-8.json @@ -0,0 +1,4 @@ +{ + "data": "śćążź", + "comment": "The data above are five Polish letters, similar to scazz. It can be read correctly only with utf-8 encoding." +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/valid-content-type.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/valid-content-type.html new file mode 100644 index 0000000000..162f2d6afc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/valid-content-type.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>JSON modules: Content-Type</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +function check(t, v) { + t.step(() => { + assert_equals(typeof v, "object"); + assert_array_equals(Object.keys(v), ["test"]); + assert_equals(v.test, true); + t.done(); + }); +} +const t1 = async_test("text/json"); +const t2 = async_test("application/json"); +const t3 = async_test("text/html+json"); +const t4 = async_test("image/svg+json"); +const t5 = async_test("text/json;boundary=something"); +const t6 = async_test("text/json;foo=bar"); +</script> +<script type="module" onerror="t1.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module-assertions/module.json&ct=text/json" assert { type: "json"}; +check(t1, v); +</script> +<script type="module" onerror="t2.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module-assertions/module.json&ct=application/json" assert { type: "json"}; +check(t2, v); +</script> +<script type="module" onerror="t3.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module-assertions/module.json&ct=text/html%2Bjson" assert { type: "json"}; +check(t3, v); +</script> +<script type="module" onerror="t4.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module-assertions/module.json&ct=image/svg%2Bjson" assert { type: "json"}; +check(t4, v); +</script> +<script type="module" onerror="t5.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module-assertions/module.json&ct=text/json;boundary=something" assert { type: "json"}; +check(t5, v); +</script> +<script type="module" onerror="t6.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module-assertions/module.json&ct=text/json;foo=bar" assert { type: "json"}; +check(t6, v); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/windows-1250.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/windows-1250.json new file mode 100644 index 0000000000..490e752ce9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module-assertions/windows-1250.json @@ -0,0 +1,4 @@ +{ + "data": "�湿�", + "comment": "The data above are five Polish letters, similar to scazz. It can be read correctly only with windows1250 encoding." +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/array.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/array.json new file mode 100644 index 0000000000..e77e32d338 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/array.json @@ -0,0 +1 @@ +["en", "try"] diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/bom-utf-16be.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/bom-utf-16be.json Binary files differnew file mode 100644 index 0000000000..d22a45a591 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/bom-utf-16be.json diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/bom-utf-16le.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/bom-utf-16le.json Binary files differnew file mode 100644 index 0000000000..4d1aa264a6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/bom-utf-16le.json diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/bom-utf-8.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/bom-utf-8.json new file mode 100644 index 0000000000..07ba933e86 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/bom-utf-8.json @@ -0,0 +1 @@ +{ "data": "hello" }
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/charset-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/charset-2.html new file mode 100644 index 0000000000..dfadaba4d1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/charset-2.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset="windows-1250"> +<title>JSON modules: UTF-8 decoding</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script type="module"> + import json from "../serve-with-content-type.py?fn=json-module/utf-8.json" with { type: "json"}; + test(() => { + assert_equals(json.data, "śćążź"); + }, "JSON module should be loaded as utf-8 even though document's encoding is windows-1250"); +</script> +<script type="module"> + import json from "../serve-with-content-type.py?fn=json-module/windows-1250.json&ct=text/json%3Bcharset=windows-1250" with { type: "json"}; + test(() => { + assert_not_equals(json.data, "śćążź", + 'Should be decoded as UTF-8'); + }, "JSON module should be loaded as utf-8 even if it is encoded in windows-1250 and served with a windows-1250 charset response header, and this document's encoding is windows-1250"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/charset-bom.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/charset-bom.any.js new file mode 100644 index 0000000000..483936a4f7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/charset-bom.any.js @@ -0,0 +1,17 @@ +// META: global=window,dedicatedworker,sharedworker +// META: script=/common/utils.js + +promise_test(async () => { + const jsonModule = await import('./bom-utf-8.json', { with: { type: 'json' } }); + assert_equals(jsonModule.default.data, 'hello'); +}, 'UTF-8 BOM should be stripped when decoding JSON module script'); + +promise_test(async test => { + await promise_rejects_js(test, SyntaxError, + import('./bom-utf-16be.json', { with: { type: 'json' } }), 'Expected parse error from UTF-16BE BOM'); +}, 'UTF-16BE BOM should result in parse error in JSON module script'); + +promise_test(async test => { + await promise_rejects_js(test, SyntaxError, + import('./bom-utf-16le.json', { with: { type: 'json' } }), 'Expected parse error from UTF-16LE BOM'); +}, 'UTF-16LE BOM should result in parse error in JSON module script'); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/charset.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/charset.html new file mode 100644 index 0000000000..ce72f0ef1b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/charset.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>JSON modules: UTF-8 decoding</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script type="module" onerror="unreachable()"> + import json from "../serve-with-content-type.py?fn=json-module/utf-8.json&ct=text/json%3Bcharset=utf-8" with { type: "json"}; + test(() => { + assert_equals(json.data, "śćążź"); + }, "JSON module should be loaded as utf-8 when charset=utf8 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import json from "../serve-with-content-type.py?fn=json-module/utf-8.json&ct=text/json%3Bcharset=shift-jis" with { type: "json"}; + test(() => { + assert_equals(json.data, "śćążź"); + }, "JSON module should be loaded as utf-8 when charset=shift-jis is specified"); +</script> +<script type="module" onerror="unreachable()"> + import json from "../serve-with-content-type.py?fn=json-module/utf-8.json&ct=text/json%3Bcharset=windows-1252" with { type: "json"}; + test(() => { + assert_equals(json.data, "śćążź"); + }, "JSON module should be loaded as utf-8 when charset=windows-1252 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import json from "../serve-with-content-type.py?fn=json-module/utf-8.json&ct=text/json%3Bcharset=utf-7" with { type: "json"};; + test(() => { + assert_equals(json.data, "śćążź"); + }, "JSON module should be loaded as utf-8 when charset=utf-7 is specified"); +</script> +<script type="module" onerror="unreachable()"> + import json from "../serve-with-content-type.py?fn=json-module/windows-1250.json&ct=text/json%3Bcharset=windows-1250" with { type: "json"}; + test(() => { + assert_not_equals(json.data, "śćążź", + 'Should be decoded as UTF-8'); + }, "JSON module should be loaded as utf-8 even if it is encoded in windows-1250 and served with a windows-1250 charset response header"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/cors-crossorigin-requests.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/cors-crossorigin-requests.html new file mode 100644 index 0000000000..99ff2f67e8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/cors-crossorigin-requests.html @@ -0,0 +1,33 @@ +<!doctype html> +<html> +<head> + <title>json-module-crossorigin</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <h1>json-module-crossorigin</h1> + <iframe id="import-WithCORS" src="crossorigin-import-with-cors.sub.html"></iframe> + <iframe id="import-NoCORS" src="crossorigin-import-without-cors.sub.html"></iframe> + <iframe id="import-parseerror-WithCors" src="crossorigin-import-parse-error-with-cors.sub.html"></iframe> + <script> + + var tests = [ + { "obj": async_test("Imported JSON module, cross-origin with CORS"), "id": "import-WithCORS", "expected": "imported JSON: 42" }, + { "obj": async_test("Imported JSON module, cross-origin, missing CORS ACAO header"), "id": "import-NoCORS", "expected": "error" }, + { "obj": async_test("Imported JSON module with parse error, cross-origin, with CORS"), "id": "import-parseerror-WithCors", "expected": "0-0" }, + ]; + + window.addEventListener("load", function () { + tests.forEach(function (test) { + var target = document.getElementById(test.id); + test.obj.step(function () { + assert_equals(target.contentDocument._log, test.expected, "Unexpected _log value"); + }); + test.obj.done(); + }); + }); + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/credentials-iframe.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/credentials-iframe.sub.html new file mode 100644 index 0000000000..b89edf8d31 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/credentials-iframe.sub.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<meta charset="utf-8"> + +<script type="module"> + import json from "./cross-origin.py?id=sameOriginNoneDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "json" }; + window.sameOriginNoneDescendant = json.requestHadCookies; +</script> +<script type="module" crossOrigin="anonymous"> + import json from "./cross-origin.py?id=sameOriginAnonymousDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "json" }; + window.sameOriginAnonymousDescendant = json.requestHadCookies; +</script> +<script type="module" crossOrigin="use-credentials"> + import json from "./cross-origin.py?id=sameOriginUseCredentialsDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "json" }; + window.sameOriginUseCredentialsDescendant = json.requestHadCookies; +</script> +<script type="module"> + import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module/cross-origin.py?id=crossOriginNoneDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "json" }; + window.crossOriginNoneDescendant = json.requestHadCookies; +</script> +<script type="module" crossOrigin="anonymous"> + import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module/cross-origin.py?id=crossOriginAnonymousDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "json" }; + window.crossOriginAnonymousDescendant = json.requestHadCookies; +</script> +<script type="module" crossOrigin="use-credentials"> +import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module/cross-origin.py?id=crossOriginUseCredentialsDescendant&origin=http://{{host}}:{{ports[http][0]}}" with { type: "json" }; +window.crossOriginUseCredentialsDescendant = json.requestHadCookies; +</script> + +<script type="text/javascript"> +window.addEventListener('load', event => { + window.parent.postMessage({}, '*'); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/credentials.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/credentials.sub.html new file mode 100644 index 0000000000..a6df506e21 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/credentials.sub.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +document.cookie = 'milk=1'; + +const setCookiePromise = fetch( + 'http://{{domains[www2]}}:{{ports[http][0]}}/cookies/resources/set-cookie.py?name=milk&path=/html/semantics/scripting-1/the-script-element/json-module/', + { + mode: 'no-cors', + credentials: 'include', + }); + +const windowLoadPromise = new Promise(resolve => { + window.addEventListener('load', () => { + resolve(); + }); +}); + +promise_test(t => { + const iframe = document.createElement('iframe'); + + return Promise.all([setCookiePromise, windowLoadPromise]).then(() => { + const messagePromise = new Promise(resolve => { + window.addEventListener('message', event => { + resolve(); + }); + }); + + iframe.src = 'credentials-iframe.sub.html'; + document.body.appendChild(iframe); + + return messagePromise; + }).then(() => { + const w = iframe.contentWindow; + + assert_equals(w.sameOriginNoneDescendant, true, + 'Descendant JSON modules should be loaded with the credentials when the crossOrigin attribute is not specified and the target is same-origin'); + assert_equals(w.sameOriginAnonymousDescendant, true, + 'Descendant JSON modules should be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is same-origin'); + assert_equals(w.sameOriginUseCredentialsDescendant, true, + 'Descendant JSON modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is same-origin'); + assert_equals(w.crossOriginNoneDescendant, false, + 'Descendant JSON modules should not be loaded with the credentials when the crossOrigin attribute is not specified and the target is cross-origin'); + assert_equals(w.crossOriginAnonymousDescendant, false, + 'Descendant JSON modules should not be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is cross-origin'); + assert_equals(w.crossOriginUseCredentialsDescendant, true, + 'Descendant JSON modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is cross-origin'); +}); +}, 'JSON Modules should be loaded with or without the credentials based on the same-origin-ness and the crossOrigin attribute'); +</script> +<body> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/cross-origin.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/cross-origin.py new file mode 100644 index 0000000000..cd56c3628a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/cross-origin.py @@ -0,0 +1,16 @@ +def main(request, response): + + headers = [ + (b"Content-Type", b"application/json"), + (b"Access-Control-Allow-Origin", request.GET.first(b"origin")), + (b"Access-Control-Allow-Credentials", b"true") + ] + + milk = request.cookies.first(b"milk", None) + + if milk is None: + return headers, u'{"requestHadCookies": false}' + elif milk.value == b"1": + return headers, u'{"requestHadCookies": true}' + + return headers, u'{"requestHadCookies": false}' diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/crossorigin-import-parse-error-with-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/crossorigin-import-parse-error-with-cors.sub.html new file mode 100644 index 0000000000..9972c53d1b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/crossorigin-import-parse-error-with-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>json-module-import-cross-domain-parse-error-WithCORS</title> + <script src="../module/crossorigin-common.js"></script> +</head> +<body> + <h1>json-module-import-cross-domain-parse-error-WithCORS</h1> + <script type="module" crossorigin> + import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module/parse-error.json?pipe=header(Access-Control-Allow-Origin,*)" with { type: "json" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported JSON: ${json.answer}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/crossorigin-import-with-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/crossorigin-import-with-cors.sub.html new file mode 100644 index 0000000000..95fd156df2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/crossorigin-import-with-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>json-module-import-cross-domain-WithCORS</title> + <script src="../module/crossorigin-common.js"></script> +</head> +<body> + <h1>json-module-import-cross-domain-WithCORS</h1> + <script type="module" crossorigin> + import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module/data.json?pipe=header(Access-Control-Allow-Origin,*)" with { type: "json" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported JSON: ${json.answer}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/crossorigin-import-without-cors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/crossorigin-import-without-cors.sub.html new file mode 100644 index 0000000000..b9318c8b20 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/crossorigin-import-without-cors.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>json-module-import-cross-domain-NoCORS</title> + <script src="../module/crossorigin-common.js"></script> +</head> +<body> + <h1>json-module-import-cross-domain-NoCORS</h1> + <script type="module" onerror="document._log.push('error');"> + import json from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module/data.json" with { type: "json" }; + // Push an event to the log indicating that the script was executed. + document._log.push(`imported JSON: ${json.answer}`); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/data.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/data.json new file mode 100644 index 0000000000..14a0526ebb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/data.json @@ -0,0 +1,3 @@ +{ + "answer": 42 +}
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/false.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/false.json new file mode 100644 index 0000000000..c508d5366f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/false.json @@ -0,0 +1 @@ +false diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity-matches.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity-matches.js new file mode 100644 index 0000000000..20459c17e3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity-matches.js @@ -0,0 +1,2 @@ +import json from "./data.json" with { type: "json" }; +window.matchesLog.push(`integrity-matches,json:${json.answer}`); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity-mismatches.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity-mismatches.js new file mode 100644 index 0000000000..0406dbcca5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity-mismatches.js @@ -0,0 +1,2 @@ +import json "./data.json" with { type: "json" }; +window.mismatchesLog.push(`integrity-mismatches,json:${json.answer}`); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity.html new file mode 100644 index 0000000000..68a794b973 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/integrity.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title><script> integrity=""</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +window.matchesLog = []; +window.matchesEvents = []; + +window.mismatchesLog = []; +window.mismatchesEvents = []; +</script> +<script type="module" src="integrity-matches.js" integrity="sha384-VmQQfGzBiLKdyzw4FA4kL4ohu4tyujV68ddgW1aN/1v3cBZNNBn2gDFdVQxfL7+a" onload="window.matchesEvents.push('load');" onerror="window.matchesEvents.push('error')"></script> +<script type="module" src="integrity-mismatches.js" integrity="sha384-doesnotmatch" onload="window.mismatchesEvents.push('load');" onerror="window.mismatchesEvents.push('error')"></script> + +<script type="module"> +test(() => { + assert_array_equals(window.matchesLog, ["integrity-matches,json:42"], "The module and its dependency must have executed"); + assert_array_equals(window.matchesEvents, ["load"], "The load event must have fired"); +}, "The integrity attribute must be verified on the top-level of a module loading a JSON module and allow it to execute when it matches"); + +test(() => { + assert_array_equals(window.mismatchesLog, [], "The module and its dependency must not have executed"); + assert_array_equals(window.mismatchesEvents, ["error"], "The error event must have fired"); +}, "The integrity attribute must be verified on the top-level of a module loading a JSON module and not allow it to execute when there's a mismatch"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/invalid-content-type.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/invalid-content-type.any.js new file mode 100644 index 0000000000..4226c3dc03 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/invalid-content-type.any.js @@ -0,0 +1,17 @@ +// META: global=window,dedicatedworker,sharedworker + +const content_types = [ + "application/json+protobuf", + "application/json+blah", + "text/x-json", + "text/json+blah", + "application/blahjson", + "image/json", +]; +for (const content_type of content_types) { + promise_test(async test => { + await promise_rejects_js(test, TypeError, + import(`./module.json?pipe=header(Content-Type,${content_type})`, { with: { type: "json"} }), + `Import of a JSON module with MIME type ${content_type} should fail`); + }, `Try importing JSON module with MIME type ${content_type}`); +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/json-module-service-worker-test.https.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/json-module-service-worker-test.https.html new file mode 100644 index 0000000000..cc47da1499 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/json-module-service-worker-test.https.html @@ -0,0 +1,29 @@ +<!doctype html> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> + promise_test(async (test) => { + const reg = await navigator.serviceWorker.register('./serviceworker.js', { type: 'module' }); + test.add_cleanup(() => reg.unregister()); + assert_not_equals(reg.installing, undefined); + }, "Javascript importing JSON Module should load within the context of a service worker"); + + promise_test(test => { + return promise_rejects_dom(test, "SecurityError", + navigator.serviceWorker.register('./module.json', { type: 'module' }), + "Attempting to load JSON as a service worker should fail"); + }, "Trying to register a service worker with a top-level JSON Module should fail"); + + promise_test(async (test) => { + const reg = await navigator.serviceWorker.register('./serviceworker-dynamic-import.js', { type: 'module' }); + test.add_cleanup(() => reg.unregister()); + assert_not_equals(reg.installing, undefined); + reg.installing.postMessage("PING"); + const msgEvent = await new Promise(resolve => { + navigator.serviceWorker.onmessage = resolve; + }); + assert_equals(msgEvent.data, "FAILED"); + }, "JSON Module dynamic import should not load within the context of a service worker"); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/load-error-events.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/load-error-events.html new file mode 100644 index 0000000000..54c1892540 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/load-error-events.html @@ -0,0 +1,67 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<head> +<title>load/error events for JSON modules</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/load-error-events-helpers.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +</head> +<script> + "use strict"; + + var test1_load = event_test('inline, 200, parser-inserted', false, false); + var test1_error = event_test('inline, 404, parser-inserted', false, true); + + var test2_load = event_test('src, 200, parser-inserted', true, false); + var test2_error = event_test('src, 404, parser-inserted', false, true); + + var test3_dynamic_load = event_test('src, 200, not parser-inserted', true, false); + var test3_dynamic_error = event_test('src, 404, not parser-inserted', false, true); + + var test4_dynamic_load = event_test('inline, 200, not parser-inserted', false, false); + var test4_dynamic_error = event_test('inline, 404, not parser-inserted', false, true); + + var script3_dynamic_load = document.createElement('script'); + script3_dynamic_load.setAttribute('type', 'module'); + script3_dynamic_load.onload = () => onLoad(test3_dynamic_load); + script3_dynamic_load.onerror = () => onError(test3_dynamic_load); + script3_dynamic_load.src = "./load-error-events.py?test=test3_dynamic_load"; + document.head.appendChild(script3_dynamic_load); + + var script3_dynamic_error = document.createElement('script'); + script3_dynamic_error.setAttribute('type', 'module'); + script3_dynamic_error.onload = () => onLoad(test3_dynamic_error); + script3_dynamic_error.onerror = () => onError(test3_dynamic_error); + script3_dynamic_error.src = "./load-error-events.py?test=test3_dynamic_error"; + document.head.appendChild(script3_dynamic_error); + + var script4_dynamic_load = document.createElement('script'); + script4_dynamic_load.setAttribute('type', 'module'); + script4_dynamic_load.onload = () => onLoad(test4_dynamic_load); + script4_dynamic_load.onerror = () => onError(test4_dynamic_load); + script4_dynamic_load.async = true; + script4_dynamic_load.appendChild(document.createTextNode(` + import "./module.json" with { type: "json" }; + onExecute(test4_dynamic_load);` + )); + document.head.appendChild(script4_dynamic_load); + + var script4_dynamic_error = document.createElement('script'); + script4_dynamic_error.setAttribute('type', 'module'); + script4_dynamic_error.onload = () => onLoad(test4_dynamic_error); + script4_dynamic_error.onerror = () => onError(test4_dynamic_error); + script4_dynamic_error.async = true; + script4_dynamic_error.appendChild(document.createTextNode(`import "./not_found.json" with { type: "json" };`)); + document.head.appendChild(script4_dynamic_error); +</script> +<script onload="onLoad(test1_load);" onerror="onError(test1_load);" type="module"> + import "./module.json" with { type: "json"}; + onExecute(test1_load); +</script> +<script onload="onLoad(test1_error);" onerror="onError(test1_error);" type="module"> + import "./not_found.json" with { type: "json"}; + onExecute(test1_error); +</script> +<script src="./load-error-events.py?test=test2_load" onload="onLoad(test2_load);" onerror="onError(test2_load);" type="module"></script> +<script src="./load-error-events.py?test=test2_error" onload="onLoad(test2_error);" onerror="onError(test2_error);" type="module"></script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/load-error-events.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/load-error-events.py new file mode 100644 index 0000000000..244552a693 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/load-error-events.py @@ -0,0 +1,14 @@ +import re + +def main(request, response): + headers = [(b"Content-Type", b"text/javascript")] + test = request.GET.first(b'test') + assert(re.match(b'^[a-zA-Z0-9_]+$', test)) + + status = 200 + if test.find(b'_load') >= 0: + content = b'import "./module.json" with { type: "json"}; %s.executed = true;' % test + else: + content = b'import "./not_found.json" with { type: "json"}; %s.test.step(function() { assert_unreached("404 script should not be executed"); });' % test + + return status, headers, content diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/module.html new file mode 100644 index 0000000000..05fc264f36 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/module.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>JSON modules</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +const t = async_test(); +</script> +<script type="module" onerror="t.step(() => assert_unreached(event))"> +import v from "./module.json" with { type: "json" }; +t.step(() => { + assert_equals(typeof v, "object"); + assert_array_equals(Object.keys(v), ["test"]); + assert_equals(v.test, true); + t.done(); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/module.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/module.json new file mode 100644 index 0000000000..f834b2a4e8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/module.json @@ -0,0 +1,3 @@ +{ + "test": true +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/non-object.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/non-object.any.js new file mode 100644 index 0000000000..ae78ddf072 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/non-object.any.js @@ -0,0 +1,14 @@ +// META: global=window,dedicatedworker,sharedworker + +for (const value of [null, true, false, "string"]) { + promise_test(async t => { + const result = await import(`./${value}.json`, { with: { type: "json" } }); + assert_equals(result.default, value); + }, `Non-object: ${value}`); +} + +promise_test(async t => { + const result = await import("./array.json", { with: { type: "json" } }); + assert_array_equals(result.default, ["en", "try"]); +}, "Non-object: array"); + diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/null.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/null.json new file mode 100644 index 0000000000..19765bd501 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/null.json @@ -0,0 +1 @@ +null diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/parse-error.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/parse-error.html new file mode 100644 index 0000000000..88fb23a00d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/parse-error.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>JSON modules: parse error</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +setup({ + allow_uncaught_exception: true, +}); +async_test(t => { + window.addEventListener("error", t.step_func_done(e => { + assert_true(e instanceof ErrorEvent, "ErrorEvent"); + assert_equals(e.filename, new URL("parse-error.json", location).href); + assert_true(e.error instanceof SyntaxError, "SyntaxError"); + })); +}); +</script> +<script type="module"> +import v from "./parse-error.json" with { type: "json" }; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/parse-error.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/parse-error.json new file mode 100644 index 0000000000..98232c64fc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/parse-error.json @@ -0,0 +1 @@ +{ diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/referrer-checker.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/referrer-checker.py new file mode 100644 index 0000000000..e9f0f1789b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/referrer-checker.py @@ -0,0 +1,6 @@ +def main(request, response): + referrer = request.headers.get(b"referer", b"") + response_headers = [(b"Content-Type", b"application/json"), + (b"Access-Control-Allow-Origin", b"*")] + return (200, response_headers, + b'{"referrer": "' + referrer + b'"}') diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/referrer-policies.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/referrer-policies.sub.html new file mode 100644 index 0000000000..1509c853e2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/referrer-policies.sub.html @@ -0,0 +1,84 @@ +<!DOCTYPE html> +<html> +<head> +<title>Referrers with JSON module requests</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> + // "name" parameter is necessary for bypassing the module map. + import referrerSame from "./referrer-checker.py?name=sameNoReferrerPolicy" with { type: "json"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module/referrer-checker.py?name=remoteNoReferrerPolicy" with { type: "json"}; + + const origin = (new URL(location.href)).origin + "/"; + const originUrl = location.href; + + test(t => { + assert_equals( + referrerSame.referrer, originUrl, + "Referrer URL should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the default referrer policy."); + + test(t => { + assert_equals( + referrerRemote.referrer, origin, + "Referrer origin should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the default referrer policy."); +</script> +<script type="module" referrerpolicy="origin"> + import referrerSame from "./referrer-checker.py?name=sameReferrerPolicyOrigin" with { type: "json"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module/referrer-checker.py?name=remoteReferrerPolicyOrigin" with { type: "json"}; + + const origin = (new URL(location.href)).origin + "/"; + + test(t => { + assert_equals( + referrerSame.referrer, origin, + "Referrer origin should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the origin policy."); + + test(t => { + assert_equals( + referrerRemote.referrer, origin, + "Referrer origin should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the origin policy."); + +</script> +<script type="module" referrerpolicy="no-referrer"> + import referrerSame from "./referrer-checker.py?name=sameReferrerPolicyNoReferrer" with { type: "json"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module/referrer-checker.py?name=remoteReferrerPolicyNoReferrer" with { type: "json"}; + + test(t => { + assert_equals( + referrerSame.referrer, "", + "No referrer should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the no-referrer policy."); + + test(t => { + assert_equals( + referrerRemote.referrer, "", + "No referrer should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the no-referrer policy."); + +</script> +<script type="module" referrerpolicy="unsafe-url"> + import referrerSame from "./referrer-checker.py?name=sameNoReferrerPolicyUnsafeUrl" with { type: "json"}; + import referrerRemote from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/json-module/referrer-checker.py?name=remoteNoReferrerPolicyUnsafeUrl" with { type: "json"}; + + const originUrl = location.href; + + test(t => { + assert_equals( + referrerSame.referrer, originUrl, + "Referrer URL should be sent for the same-origin top-level script."); + }, "Importing a same-origin top-level script with the unsafe-url referrer policy."); + + test(t => { + assert_equals( + referrerRemote.referrer, originUrl, + "Referrer URL should be sent for the remote-origin top-level script."); + }, "Importing a remote-origin top-level script with the unsafe-url referrer policy."); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/repeated-imports.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/repeated-imports.any.js new file mode 100644 index 0000000000..722251b84d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/repeated-imports.any.js @@ -0,0 +1,65 @@ +// META: global=window,dedicatedworker,sharedworker +// META: script=/common/utils.js + +promise_test(async test => { + await promise_rejects_js(test, TypeError, + import("./module.json"), + "Dynamic import of a JSON module without a type attribute should fail"); + + // This time the import should succeed because we're using the correct + // import even though the previous attempt with the same specifier failed. + const result = await import("./module.json", { with: { type: "json" } }); + assert_true(result.default.test); +}, "Importing a specifier that previously failed due to an incorrect type attribute can succeed if the correct attribute is later given"); + +promise_test(async test => { + // Append a URL fragment to the specifier so that this is independent + // from the previous test. + const result = await import("./module.json#2", { with: { type: "json" } }); + assert_true(result.default.test); + + await promise_rejects_js(test, TypeError, + import("./module.json#2"), + "Dynamic import should fail with the type attribute missing even if the same specifier previously succeeded"); +}, "Importing a specifier that previously succeeded with the correct type attribute should fail if the incorrect attribute is later given"); + +promise_test(async test => { + const uuid_token = token(); + // serve-json-then-js.py gives us JSON the first time + const result_json = await import(`../serve-json-then-js.py?key=${uuid_token}`, { with: { type: "json" } }); + assert_equals(result_json.default.hello, "world"); + + // Import using the same specifier again; this time we get JS, which + // should succeed since we're not asserting a non-JS type this time. + const result_js = await import(`../serve-json-then-js.py?key=${uuid_token}`); + assert_equals(result_js.default, "hello"); +}, "Two modules of different type with the same specifier can load if the server changes its responses"); + +promise_test(async test => { + const uuid_token = token(); + // serve-json-then-js.py gives us JSON the first time + await promise_rejects_js(test, TypeError, + import(`../serve-json-then-js.py?key=${uuid_token}`), + "Dynamic import of JS with a JSON type attribute should fail"); + + // Import using the same specifier/module type pair again; this time we get JS, + // but the import should still fail because the module map entry for this + // specifier/module type pair already contains a failure. + await promise_rejects_js(test, TypeError, + import(`../serve-json-then-js.py?key=${uuid_token}`), + "import should always fail if the same specifier/type attribute pair failed previously"); +}, "An import should always fail if the same specifier/type attribute pair failed previously"); + +promise_test(async test => { + const uuid_token = token(); + // serve-json-then-js.py gives us JSON the first time + const result_json = await import(`../serve-json-then-js.py?key=${uuid_token}`, { with: { type: "json" } }); + assert_equals(result_json.default.hello, "world"); + + // If this were to do another fetch, the import would fail because + // serve-json-then-js.py would give us JS this time. But, the module map + // entry for this specifier/module type pair already exists, so we + // successfully reuse the entry instead of fetching again. + const result_json_2 = await import(`../serve-json-then-js.py?key=${uuid_token}`, { with: { type: "json" } }); + assert_equals(result_json_2.default.hello, "world"); +}, "If an import previously succeeded for a given specifier/type attribute pair, future uses of that pair should yield the same result"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/script-element-json-src.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/script-element-json-src.html new file mode 100644 index 0000000000..c6d7c9a76e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/script-element-json-src.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<title><script> with JSON src</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test that <script> doesn't load when the src is JSON."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, ["error"]); + })); +</script> +<script type="module" src="./module.json" onload="t.unreached_func('JSON src should fail to load')" onerror="log.push('error')"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/serviceworker-dynamic-import.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/serviceworker-dynamic-import.js new file mode 100644 index 0000000000..cd39c789cb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/serviceworker-dynamic-import.js @@ -0,0 +1,5 @@ +onmessage = e => { + e.waitUntil(import("./module.json", { with: { type: "json" } }) + .then(module => e.source.postMessage("LOADED")) + .catch(error => e.source.postMessage("FAILED"))); + };
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/serviceworker.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/serviceworker.js new file mode 100644 index 0000000000..65210fe3e7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/serviceworker.js @@ -0,0 +1 @@ +import './module.json' with { type: "json" };
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/string.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/string.json new file mode 100644 index 0000000000..ace2d72d9d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/string.json @@ -0,0 +1 @@ +"string" diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/true.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/true.json new file mode 100644 index 0000000000..27ba77ddaf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/true.json @@ -0,0 +1 @@ +true diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/utf-8.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/utf-8.json new file mode 100644 index 0000000000..088d982358 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/utf-8.json @@ -0,0 +1,4 @@ +{ + "data": "śćążź", + "comment": "The data above are five Polish letters, similar to scazz. It can be read correctly only with utf-8 encoding." +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/valid-content-type.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/valid-content-type.html new file mode 100644 index 0000000000..3232b84d27 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/valid-content-type.html @@ -0,0 +1,46 @@ +<!DOCTYPE html> +<meta charset=utf-8> +<title>JSON modules: Content-Type</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +function check(t, v) { + t.step(() => { + assert_equals(typeof v, "object"); + assert_array_equals(Object.keys(v), ["test"]); + assert_equals(v.test, true); + t.done(); + }); +} +const t1 = async_test("text/json"); +const t2 = async_test("application/json"); +const t3 = async_test("text/html+json"); +const t4 = async_test("image/svg+json"); +const t5 = async_test("text/json;boundary=something"); +const t6 = async_test("text/json;foo=bar"); +</script> +<script type="module" onerror="t1.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module/module.json&ct=text/json" with { type: "json"}; +check(t1, v); +</script> +<script type="module" onerror="t2.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module/module.json&ct=application/json" with { type: "json"}; +check(t2, v); +</script> +<script type="module" onerror="t3.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module/module.json&ct=text/html%2Bjson" with { type: "json"}; +check(t3, v); +</script> +<script type="module" onerror="t4.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module/module.json&ct=image/svg%2Bjson" with { type: "json"}; +check(t4, v); +</script> +<script type="module" onerror="t5.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module/module.json&ct=text/json;boundary=something" with { type: "json"}; +check(t5, v); +</script> +<script type="module" onerror="t6.step(() => assert_unreached(event))"> +import v from "../serve-with-content-type.py?fn=json-module/module.json&ct=text/json;foo=bar" with { type: "json"}; +check(t6, v); +</script>
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/windows-1250.json b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/windows-1250.json new file mode 100644 index 0000000000..490e752ce9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/json-module/windows-1250.json @@ -0,0 +1,4 @@ +{ + "data": "�湿�", + "comment": "The data above are five Polish letters, similar to scazz. It can be read correctly only with windows1250 encoding." +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-1.html new file mode 100644 index 0000000000..45571550e1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-1.html @@ -0,0 +1,68 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<head> +<title>load/error events for classic scripts</title> +<!-- For module scripts see module/load-error-events*.html --> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/load-error-events-helpers.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +</head> +<script> +"use strict"; +var test1_load = event_test('src, 200, parser-inserted, defer, no async', true, false); +var test2_load = event_test('src, 200, parser-inserted, no defer, no async', true, false); +var test4_load = event_test('src, 200, parser-inserted, no defer, async', true, false); + +var test3_dynamic_load = event_test('src, 200, not parser-inserted, no defer, no async, no non-blocking', true, false); +var test4_dynamic_load = event_test('src, 200, not parser-inserted, no defer, async', true, false); + +var test1_error = event_test('src, 404, parser-inserted, defer, no async', false, true); +var test2_error = event_test('src, 404, parser-inserted, no defer, no async', false, true); +var test4_error = event_test('src, 404, parser-inserted, no defer, async', false, true); + +var test3_dynamic_error = event_test('src, 404, not parser-inserted, no defer, no async, no non-blocking', false, true); +var test4_dynamic_error = event_test('src, 404, not parser-inserted, no defer, async', false, true); + +var test6_load = event_test('no src, parser-inserted, no style sheets blocking scripts', false, false); + +var script3_dynamic_load = document.createElement('script'); +script3_dynamic_load.onload = () => onLoad(test3_dynamic_load); +script3_dynamic_load.onerror = () => onError(test3_dynamic_load); +script3_dynamic_load.async = false; +script3_dynamic_load.src = "resources/load-error-events.py?test=test3_dynamic_load"; +document.head.appendChild(script3_dynamic_load); + +var script3_dynamic_error = document.createElement('script'); +script3_dynamic_error.onload = () => onLoad(test3_dynamic_error); +script3_dynamic_error.onerror = () => onError(test3_dynamic_error); +script3_dynamic_error.async = false; +script3_dynamic_error.src = "resources/load-error-events.py?test=test3_dynamic_error"; +document.head.appendChild(script3_dynamic_error); + +var script4_dynamic_load = document.createElement('script'); +script4_dynamic_load.onload = () => onLoad(test4_dynamic_load); +script4_dynamic_load.onerror = () => onError(test4_dynamic_load); +script4_dynamic_load.async = true; +script4_dynamic_load.src = "resources/load-error-events.py?test=test4_dynamic_load"; +document.head.appendChild(script4_dynamic_load); + +var script4_dynamic_error = document.createElement('script'); +script4_dynamic_error.onload = () => onLoad(test4_dynamic_error); +script4_dynamic_error.onerror = () => onError(test4_dynamic_error); +script4_dynamic_error.async = true; +script4_dynamic_error.src = "resources/load-error-events.py?test=test4_dynamic_error"; +document.head.appendChild(script4_dynamic_error); +</script> + +<script src="resources/load-error-events.py?test=test1_load" onload="onLoad(test1_load);" onerror="onError(test1_load);" defer></script> +<script src="resources/load-error-events.py?test=test2_load" onload="onLoad(test2_load);" onerror="onError(test2_load);"></script> +<script src="resources/load-error-events.py?test=test4_load" onload="onLoad(test4_load);" onerror="onError(test4_load);" async></script> +<script src="resources/load-error-events.py?test=test1_error" onload="onLoad(test1_error);" onerror="onError(test1_error);" defer></script> +<script src="resources/load-error-events.py?test=test2_error" onload="onLoad(test2_error);" onerror="onError(test2_error);"></script> +<script src="resources/load-error-events.py?test=test4_error" onload="onLoad(test4_error);" onerror="onError(test4_error);" async></script> + +<script onload="onLoad(test6_load);" onerror="onError(test6_load);"> +"use strict"; +onExecute(test6_load); +</script> 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 new file mode 100644 index 0000000000..0748b45909 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-2.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<head> +<title>load/error events for classic scripts with a style sheet that is blocking scripts</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/load-error-events-helpers.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script> +"use strict"; +var test5_load = event_test('no src, parser-inserted, has style sheets blocking scripts, script nesting level == 1', false, false); +</script> + +<link rel="stylesheet" href="/common/slow.py"></link> +<!-- This is testing the case where an inline classic script is inserted +by parser while there is an loading stylesheet. Therefore, it is critical to +place a <link rel="stylesheet"> just above the <script> to be tested. --> +<script onload="onLoad(test5_load);" onerror="onError(test5_load);"> +"use strict"; +onExecute(test5_load); +</script> +</head> 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 new file mode 100644 index 0000000000..83a752ce2c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/load-error-events-3.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<head> +<title>load/error events for classic scripts with a style sheet that is blocking scripts and script nesting level > 1</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/load-error-events-helpers.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +</head> +<script> +"use strict"; +var test6_load = event_test('no src, parser-inserted, has style sheets blocking scripts, script nesting level == 2', + false, false); + +document.write( + `<link rel="stylesheet" href="/common/slow.py"></link> + <script onload="onLoad(test6_load);" + onerror="onError(test6_load);"> + "use strict"; + onExecute(test6_load); + </scr` + `ipt>`); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/log.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/log.py new file mode 100644 index 0000000000..2a6cc33029 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/log.py @@ -0,0 +1,13 @@ +import time + +def main(request, response): + response.headers.append(b"Content-Type", b"text/javascript") + try: + script_id = int(request.GET.first(b"id")) + delay = int(request.GET.first(b"sec")) + except: + response.set_error(400, u"Invalid parameter") + + time.sleep(int(delay)) + + return u"log('%s')" % script_id diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-window-onerror-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-window-onerror-module.html new file mode 100644 index 0000000000..728ce32c38 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-window-onerror-module.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<head> + <meta charset="utf-8"> + <title>Microtask checkpoint after window.onerror events (module)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="resources/checkpoint-after-error-event.js" type="module"></script> + <script type="module">self.postMessage("foo");</script> +</head> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-window-onerror.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-window-onerror.html new file mode 100644 index 0000000000..72a197ca6a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-window-onerror.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<head> + <meta charset="utf-8"> + <title>Microtask checkpoint after window.onerror events (classic)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="resources/checkpoint-after-error-event.js"></script> + <script>self.postMessage("foo");</script> +</head> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-workerglobalscope-onerror-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-workerglobalscope-onerror-module.html new file mode 100644 index 0000000000..ff2b5d4943 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-workerglobalscope-onerror-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<head> + <meta charset="utf-8"> + <title>Microtask checkpoint after window.onerror events (module)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + const worker = new Worker( + "resources/checkpoint-after-error-event-worker-module.js", + {type: "module"}); + fetch_tests_from_worker(worker); + worker.postMessage("foo"); + </script> +</head> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-workerglobalscope-onerror.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-workerglobalscope-onerror.html new file mode 100644 index 0000000000..1932c7183b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-after-workerglobalscope-onerror.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<head> + <meta charset="utf-8"> + <title>Microtask checkpoint after window.onerror events (module)</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + const worker = new Worker( + "resources/checkpoint-after-error-event-worker.js"); + fetch_tests_from_worker(worker); + worker.postMessage("foo"); + </script> +</head> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-importScripts.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-importScripts.any.js new file mode 100644 index 0000000000..8791a099b6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-importScripts.any.js @@ -0,0 +1,40 @@ +// META: global=dedicatedworker,sharedworker + +// The `then` handlers for `Promise.resolve()` are evaluated in the first +// microtasks checkpoint after `Promise.resolve()`. + +// ---------------------------------------------------------------- +// Check when microtasks checkpoint is performed around importScripts(). + +// The expectation is: the `then` handlers are evaluated after the script +// calling importScripts() is finished, not immediately after importScripts(). +// Although #clean-up-after-running-script is executed as a part of +// #run-a-classic-script for importScripts()ed scripts, but at that time +// microtasks checkpoint is NOT performed because JavaScript execution context +// stack is not empty. + +self.log = []; + +// Microtasks should be executed before +// #run-a-classic-script/#run-a-module-script is completed, and thus before +// script evaluation scheduled by setTimeout(). +async_test(t => { + self.addEventListener('error', + t.unreached_func('error event should not be fired')); + + t.step_timeout(() => { + assert_array_equals(log, [ + 'importScripts()ed script', + 'catch', + 'promise' + ]); + t.done(); + }, + 0); +}, "Promise resolved during importScripts()"); + +try { + importScripts('resources/resolve-then-throw.js'); +} catch (e) { + self.log.push('catch'); +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-importScripts.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-importScripts.any.js new file mode 100644 index 0000000000..bacfc9fd04 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-importScripts.any.js @@ -0,0 +1,11 @@ +// META: global=dedicatedworker,sharedworker +// META: script=./resources/evaluation-order-setup.js + +// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script +// called from https://html.spec.whatwg.org/C/#import-scripts-into-worker-global-scope +setupTest("importScripts() queueing a microtask then throwing an exception", [ + "body", + "microtask", +]); + +importScripts('./resources/evaluation-order-1-nothrow.js'); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-static-import.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-static-import.any.js new file mode 100644 index 0000000000..006eab7a7e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-nothrow-static-import.any.js @@ -0,0 +1,5 @@ +// META: global=dedicatedworker-module,sharedworker-module +// META: script=./resources/evaluation-order-setup.js + +import './resources/evaluation-order-1-nothrow-setup.js'; +import './resources/evaluation-order-1-nothrow.js'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-importScripts.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-importScripts.any.js new file mode 100644 index 0000000000..0b42ea1e50 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-importScripts.any.js @@ -0,0 +1,22 @@ +// META: global=dedicatedworker,sharedworker +// META: script=./resources/evaluation-order-setup.js + +// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script +// called from https://html.spec.whatwg.org/C/#import-scripts-into-worker-global-scope +setupTest("importScripts() queueing a microtask then throwing an exception", [ + // Step 6 of #run-a-classic-script. + "body", + + // Step 7.1.1 ("Clean up after running script") is no-op because JavaScript + // execution context stack is still non-empty immediately after + // importScripts() as the outer script is still executing. + + // Step 7.1.2 (Rethrowing an exception) causes worker onerror. + "global-error", + + // Microtask checkpoint is performed later, perhaps + // "Clean up after running script" after the outer script is finished. + "microtask", +]); + +importScripts('./resources/evaluation-order-1-throw.js'); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-static-import.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-static-import.any.js new file mode 100644 index 0000000000..f6cc427c71 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1-throw-static-import.any.js @@ -0,0 +1,5 @@ +// META: global=dedicatedworker-module,sharedworker-module +// META: script=./resources/evaluation-order-setup.js + +import './resources/evaluation-order-1-throw-setup.js'; +import './resources/evaluation-order-1-throw.js'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1.html new file mode 100644 index 0000000000..4800ef81bc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-1.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/evaluation-order-setup.js"></script> + +<script> +// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script +setupTest("Classic script queueing a microtask then throwing an exception", [ + "body", // Step 6. + "global-error", // "Report the exception" at Step 7.3. + "microtask", // "Clean up after running script" at Step 7.2. + ]); +</script> +<script src="resources/evaluation-order-1-throw.js" + onerror="unreachable()" onload="testDone()"></script> + +<script> +// Spec: https://html.spec.whatwg.org/C/#run-a-classic-script +setupTest("Classic script queueing a microtask", [ + "body", // Step 6. + "microtask", // "Clean up after running script" at Step 7.2. + ]); +</script> +<script src="resources/evaluation-order-1-nothrow.js" + onerror="unreachable()" onload="testDone()"></script> + + +<script type="module" src="resources/evaluation-order-1-throw-setup.js"></script> +<script type="module" src="resources/evaluation-order-1-throw.js" + onerror="unreachable()" onload="testDone()"></script> + +<script type="module" src="resources/evaluation-order-1-nothrow-setup.js"></script> +<script type="module" src="resources/evaluation-order-1-nothrow.js" + onerror="unreachable()" onload="testDone()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.any.js new file mode 100644 index 0000000000..bbc6474823 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.any.js @@ -0,0 +1,5 @@ +// META: global=dedicatedworker-module,sharedworker-module +// META: script=./resources/evaluation-order-setup.js + +import './resources/evaluation-order-2-setup.js'; +import './resources/evaluation-order-2.1.mjs'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.html new file mode 100644 index 0000000000..e55c2ecbed --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-2.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/evaluation-order-setup.js"></script> + +<script type="module" src="resources/evaluation-order-2-setup.js"></script> +<script type="module" src="resources/evaluation-order-2.1.mjs" + onerror="unreachable()" onload="testDone()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.any.js new file mode 100644 index 0000000000..19e94714e5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.any.js @@ -0,0 +1,5 @@ +// META: global=dedicatedworker-module,sharedworker-module +// META: script=./resources/evaluation-order-setup.js + +import './resources/evaluation-order-3-setup.js'; +import './resources/evaluation-order-3.1.mjs'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.html new file mode 100644 index 0000000000..ef351acd28 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-3.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/evaluation-order-setup.js"></script> + +<script type="module" src="resources/evaluation-order-3-setup.js"></script> +<script type="module" src="resources/evaluation-order-3.1.mjs" + onerror="unreachable()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-4.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-4.html new file mode 100644 index 0000000000..f27678439d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/evaluation-order-4.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/evaluation-order-setup.js"></script> + +<script> +// Spec: https://html.spec.whatwg.org/C/#run-a-module-script +setupTest("Module script queueing a microtask then top-level await", [ + "step-4.1-1", "step-4.1-2", + "microtask-4.1", + "script-load", + "step-4.2-1", "step-4.2-2", + "microtask-4.2", +]); +window.onerror = testDone; +</script> +<script type="module" src="resources/evaluation-order-4.1.mjs" + onerror="unreachable()" onload="log.push('script-load')"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/checkpoint-after-error-event-worker-module.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/checkpoint-after-error-event-worker-module.js new file mode 100644 index 0000000000..b9ae7142d5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/checkpoint-after-error-event-worker-module.js @@ -0,0 +1,2 @@ +import "/resources/testharness.js"; +import "./checkpoint-after-error-event.js"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/checkpoint-after-error-event-worker.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/checkpoint-after-error-event-worker.js new file mode 100644 index 0000000000..4694db1e44 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/checkpoint-after-error-event-worker.js @@ -0,0 +1,2 @@ +importScripts("/resources/testharness.js"); +importScripts("checkpoint-after-error-event.js"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/checkpoint-after-error-event.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/checkpoint-after-error-event.js new file mode 100644 index 0000000000..1a2b9404a7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/checkpoint-after-error-event.js @@ -0,0 +1,89 @@ +// The `then` handlers for `Promise.resolve()` are evaluated in the first +// microtasks checkpoint after `Promise.resolve()`. + +self.setup({allow_uncaught_exception: true}); + +// ---------------------------------------------------------------- +// Check when microtasks checkpoint is performed +// - Around `self`'s error event fired via +// https://html.spec.whatwg.org/C/#report-the-error during +// - https://html.spec.whatwg.org/C/#run-a-classic-script or +// - https://html.spec.whatwg.org/C/#run-a-module-script. + +// The expectation is: the `then` handlers are evaluated after all error event +// handlers are evaluated, not after each error event handler. + +// Just after each event handler is invoked, +// https://webidl.spec.whatwg.org/#call-a-user-objects-operation +// calls #clean-up-after-running-script, but this doesn't execute new +// microtasks immediately, because: +// - Before https://github.com/whatwg/html/pull/4352: +// #report-the-error is called before #clean-up-after-running-script by +// #run-a-classic-script/#run-a-module-script, so microtask checkpoint +// is not performed because JavaScript execution context stack is not empty. +// - After https://github.com/whatwg/html/pull/4352: +// #report-the-error is called during #perform-a-microtask-checkpoint (because +// it is called on rejection of promises), so #perform-a-microtask-checkpoint +// is executed but early exited. +self.log = []; + +self.addEventListener('error', () => { + log.push('handler 1'); + Promise.resolve().then(() => log.push('handler 1 promise')); +}); +self.addEventListener('error', () => { + log.push('handler 2'); + Promise.resolve().then(() => log.push('handler 2 promise')); +}); + +// Microtasks should be executed before +// #run-a-classic-script/#run-a-module-script is completed, and thus before +// script evaluation scheduled by setTimeout(). +async_test(t => { + t.step_timeout(() => { + assert_array_equals(log, [ + 'handler 1', + 'handler 2', + 'handler 1 promise', + 'handler 2 promise' + ]); + t.done(); + }, + 0); +}, "Promise resolved during #report-the-error"); + +// ---------------------------------------------------------------- +// Check when microtasks checkpoint is performed +// around event events other than the `self` error event cases above. +// In this case, microtasks are executed just after each event handler is +// invoked via #clean-up-after-running-script called from +// https://webidl.spec.whatwg.org/#call-a-user-objects-operation, +// because the event handlers are executed outside the +// #prepare-to-run-script/#clean-up-after-running-script scopes in +// #run-a-classic-script/#run-a-module-script. +self.log2 = []; +self.t2 = async_test( + "Promise resolved during event handlers other than error"); + +self.addEventListener('message', () => { + log2.push('handler 1'); + Promise.resolve().then(() => log2.push('handler 1 promise')); +}); +self.addEventListener('message', () => { + log2.push('handler 2'); + Promise.resolve().then(t2.step_func_done(() => { + log2.push('handler 2 promise'); + assert_array_equals(log2, [ + 'handler 1', + 'handler 1 promise', + 'handler 2', + 'handler 2 promise' + ]); + })); +}); + +// ---------------------------------------------------------------- + +done(); + +throw new Error('script 1'); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow-setup.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow-setup.js new file mode 100644 index 0000000000..1b42e99593 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow-setup.js @@ -0,0 +1,5 @@ +// Spec: https://html.spec.whatwg.org/C/#run-a-module-script +setupTest("Module script queueing a microtask", [ + "body", // Step 6. + "microtask", // "Clean up after running script" at Step 8. +]); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow.js new file mode 100644 index 0000000000..e19d9b1b13 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-nothrow.js @@ -0,0 +1,2 @@ +queueMicrotask(() => globalThis.log.push("microtask")); +globalThis.log.push("body"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw-setup.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw-setup.js new file mode 100644 index 0000000000..651a494e53 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw-setup.js @@ -0,0 +1,10 @@ +// Spec: https://html.spec.whatwg.org/C/#run-a-module-script +setupTest("Module script queueing a microtask then throwing an exception", [ + "body", // Step 6. + "microtask", // "Clean up after running script" at Step 8. + "global-error", // "Clean up after running script" at Step 8, because + // `evaluationPromise` is synchronously rejected and the rejection is + // processed in the microtask checkpoint here (See also Step 7). + // As `evaluationPromise` is rejected after the microtask queued during + // evaluation, "global-error" occurs after "microtask". +]); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw.js new file mode 100644 index 0000000000..2451df1c15 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-1-throw.js @@ -0,0 +1,4 @@ +queueMicrotask(() => globalThis.log.push("microtask")); +globalThis.log.push("body"); + +throw new Error("error"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2-setup.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2-setup.js new file mode 100644 index 0000000000..46f7354538 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2-setup.js @@ -0,0 +1,10 @@ +// Spec: https://html.spec.whatwg.org/C/#run-a-module-script +setupTest("Module script queueing a microtask then throwing an exception", [ + "step-2.2-1", "step-2.2-2", // Step 6. + "microtask-2.2", // "Clean up after running script" at Step 8. + "global-error", // "Clean up after running script" at Step 8, + // because `evaluationPromise` is synchronously rejected and the rejection + // is processed in the microtask checkpoint here (See also Step 7). + // As `evaluationPromise` is rejected after the microtask queued during + // evaluation, "global-error" occurs after "microtask". +]); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2.1.mjs b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2.1.mjs new file mode 100644 index 0000000000..d6c2afa2f7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2.1.mjs @@ -0,0 +1,8 @@ +globalThis.log.push("step-2.1-1"); +queueMicrotask(() => globalThis.log.push("microtask-2.1")); +globalThis.log.push("step-2.1-2"); + +// import is evaluated first. +import "./evaluation-order-2.2.mjs"; + +globalThis.log.push("step-2.1-3"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2.2.mjs b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2.2.mjs new file mode 100644 index 0000000000..5c67c4f9a2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-2.2.mjs @@ -0,0 +1,7 @@ +globalThis.log.push("step-2.2-1"); +queueMicrotask(() => globalThis.log.push("microtask-2.2")); +globalThis.log.push("step-2.2-2"); + +globalThis.test_load.step_timeout(() => globalThis.testDone(), 0); + +throw new Error("error"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3-setup.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3-setup.js new file mode 100644 index 0000000000..edc046910e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3-setup.js @@ -0,0 +1,7 @@ +setupTest("Module script queueing a microtask then throwing an exception", [ + "step-3.1-1", "step-3.1-2", "step-3.1-3", + "microtask-3.1", + "step-3.2-1", "step-3.2-2", + "microtask-3.2", + "import-catch", "error", +]); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3.1.mjs b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3.1.mjs new file mode 100644 index 0000000000..ef320632af --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3.1.mjs @@ -0,0 +1,11 @@ +globalThis.log.push("step-3.1-1"); +queueMicrotask(() => globalThis.log.push("microtask-3.1")); +globalThis.log.push("step-3.1-2"); + +import("./evaluation-order-3.2.mjs").catch( + exception => { + globalThis.log.push("import-catch", exception.message); + globalThis.testDone(); + }); + +globalThis.log.push("step-3.1-3"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3.2.mjs b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3.2.mjs new file mode 100644 index 0000000000..8ccb581206 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-3.2.mjs @@ -0,0 +1,5 @@ +globalThis.log.push("step-3.2-1"); +queueMicrotask(() => globalThis.log.push("microtask-3.2")); +globalThis.log.push("step-3.2-2"); + +throw new Error("error"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-4.1.mjs b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-4.1.mjs new file mode 100644 index 0000000000..f3347c1d28 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-4.1.mjs @@ -0,0 +1,8 @@ +log.push("step-4.1-1"); +queueMicrotask(() => log.push("microtask-4.1")); +log.push("step-4.1-2"); + +await import("./evaluation-order-4.2.mjs"); + +// Not happening as we throw in the above module. +log.push("step-4.1-3"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-4.2.mjs b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-4.2.mjs new file mode 100644 index 0000000000..96a5cca3a6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-4.2.mjs @@ -0,0 +1,5 @@ +log.push("step-4.2-1"); +queueMicrotask(() => log.push("microtask-4.2")); +log.push("step-4.2-2"); + +throw new Error("error"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-setup.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-setup.js new file mode 100644 index 0000000000..d2e28935c4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/evaluation-order-setup.js @@ -0,0 +1,30 @@ +globalThis.setup({allow_uncaught_exception: true}); + +// Must be called after previous tests are completed. +globalThis.setupTest = (description, expectedLog) => { + globalThis.log = []; + globalThis.onerror = message => { + globalThis.log.push("global-error"); + return true; + }; + globalThis.onunhandledrejection = + () => globalThis.log.push('unhandled-promise-rejection'); + + globalThis.unreachable = () => globalThis.log.push("unreachable"); + + globalThis.test_load = async_test(description); + globalThis.testDone = globalThis.test_load.step_func_done(() => { + assert_array_equals(globalThis.log, expectedLog); + }); + + if (!('Window' in globalThis && globalThis instanceof Window)) { + // In workers, there are no <script> load event, so scheduling `testDone()` + // here, assuming the target script is loaded and evaluated soon. + globalThis.test_load.step_timeout(() => globalThis.testDone(), 1000); + + // In workers, call `done()` here because the auto-generated `done()` calls + // by `any.js` etc. are at the end of main script and thus are not + // evaluated when the target script throws an exception. + done(); + } +}; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/resolve-then-throw.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/resolve-then-throw.js new file mode 100644 index 0000000000..a841eb780a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/microtasks/resources/resolve-then-throw.js @@ -0,0 +1,3 @@ +self.log.push('importScripts()ed script'); +Promise.resolve().then(() => self.log.push('promise')); +throw new Error('foo'); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/bad-module-specifier.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/bad-module-specifier.js new file mode 100644 index 0000000000..a53a3bebe7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/bad-module-specifier.js @@ -0,0 +1,3 @@ +import "string-without-dot-slash-prefix"; +import "./this.js"; +log.push("bad-module-specifier"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/charset-01.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/charset-01.html new file mode 100644 index 0000000000..7cd4916309 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/charset-01.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Root module scripts should always use UTF-8</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="module" src="../serve-with-content-type.py?fn=external-script-utf8.js&ct=text/javascript&dummy=1"></script> +<script type="module"> +test(function() { + assert_equals(window.getSomeString(), "śćążź", + 'Should be decoded as UTF-8'); +}, 'UTF-8 module script'); +</script> + +<script type="module" src="../serve-with-content-type.py?fn=external-script-utf8.js&ct=text/javascript&dummy=2" charset="windows-1250"></script> +<script type="module"> +test(function() { + assert_equals(window.getSomeString(), "śćążź", + 'Should be decoded as UTF-8'); +}, 'UTF-8 module script with wrong charset in attribute'); +</script> + +<script type="module" src="../serve-with-content-type.py?fn=external-script-utf8.js&ct=text/javascript%3Bcharset=windows-1250&dummy=3"></script> +<script type="module"> +test(function() { + assert_equals(window.getSomeString(), "śćążź", + 'Should be decoded as UTF-8'); +}, 'UTF-8 module script with wrong charset in Content-Type'); +</script> + +<script type="module" src="../serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript&dummy=1"></script> +<script type="module"> +test(function() { + assert_not_equals(window.getSomeString(), "śćążź", + 'Should be decoded as UTF-8'); +}, 'Non-UTF-8 module script'); +</script> + +<script type="module" src="../serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript&dummy=2" charset="windows-1250"></script> +<script type="module"> +test(function() { + assert_not_equals(window.getSomeString(), "śćążź", + 'Should be decoded as UTF-8'); +}, 'Non-UTF-8 module script with charset in attribute'); +</script> + +<script type="module" src="../serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript%3Bcharset=windows-1250"></script> +<script type="module"> +test(function() { + assert_not_equals(window.getSomeString(), "śćążź", + 'Should be decoded as UTF-8'); +}, 'Non-UTF-8 module script with charset in Content-Type'); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/charset-02.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/charset-02.html new file mode 100644 index 0000000000..c7c4517ad3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/charset-02.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<title>Module scripts should ignore BOMs and always use UTF-8</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +setup({allow_uncaught_exception: true}); +</script> +<script type="module" src="../serve-with-content-type.py?fn=resources/bom-utf-8.js&ct=text/javascript"></script> +<script type="module" src="../serve-with-content-type.py?fn=resources/bom-utf-16be.js&ct=text/javascript"></script> +<script type="module" src="../serve-with-content-type.py?fn=resources/bom-utf-16le.js&ct=text/javascript"></script> +<script type="module"> +test(function() { + assert_equals(window.executed_utf8_bom, '\u4e09\u6751\u304b\u306a\u5b50', + 'Should be decoded as UTF-8'); +}, 'UTF-8 module script with UTF-8 BOM'); + +test(function() { + assert_equals(window.executed_utf16be_bom, undefined, + 'Should result in compile error because of UTF-16BE BOM'); +}, 'UTF-16 module script with UTF-16BE BOM'); + +test(function() { + assert_equals(window.executed_utf16le_bom, undefined, + 'Should result in compile error because of UTF-16LE BOM'); +}, 'UTF-16 module script with UTF-16LE BOM'); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/charset-03.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/charset-03.html new file mode 100644 index 0000000000..666cb2e68b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/charset-03.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Imported module scripts should always use UTF-8</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script type="module" src="resources/import-utf8.js"></script> +<script type="module"> +test(function() { + assert_equals(window.getSomeString(), "śćążź", + 'Should be decoded as UTF-8'); +}, 'UTF-8 imported module script'); +</script> + +<script type="module" src="resources/import-utf8-with-charset-header.js"></script> +<script type="module"> +test(function() { + assert_equals(window.getSomeString(), "śćążź", + 'Should be decoded as UTF-8'); +}, 'UTF-8 imported module script with wrong charset in Content-Type'); +</script> + +<script type="module" src="resources/import-non-utf8.js"></script> +<script type="module"> +test(function() { + assert_not_equals(window.getSomeString(), "śćążź", + 'Should be decoded as UTF-8'); +}, 'Non-UTF-8 imported module script'); +</script> + +<script type="module" src="resources/import-non-utf8-with-charset-header.js"></script> +<script type="module"> +test(function() { + assert_not_equals(window.getSomeString(), "śćążź", + 'Should be decoded as UTF-8'); +}, 'Non-UTF-8 imported module script with charset in Content-Type'); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html new file mode 100644 index 0000000000..50933da2c1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<title>Choice of parse errors</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + window.addEventListener("onunhandledrejection", unreachable); + + const test_load = async_test( + "Parse errors in different files should be reported " + + "depending on different roots"); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 4); + + // Two different parse errors from different module scripts + // should be reported for each <script> element. + assert_equals(log[0].constructor, SyntaxError); + assert_equals(log[1], 1); + + assert_equals(log[2].constructor, SyntaxError); + assert_equals(log[3], 2); + + assert_not_equals(log[0], log[2], + 'two different parse errors should be reported'); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./choice-of-error-1a.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./choice-of-error-1b.js" + onerror="unreachable()" onload="log.push(2)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1a.js new file mode 100644 index 0000000000..f479e5e1fa --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1a.js @@ -0,0 +1,2 @@ +import './choice-of-error-1b.js'; +import './syntaxerror.js?1c'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1b.js new file mode 100644 index 0000000000..257f4a4678 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-1b.js @@ -0,0 +1,2 @@ +import './choice-of-error-1a.js'; +import './syntaxerror.js?1d'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html new file mode 100644 index 0000000000..51adb09d11 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<title>Choice of instantiation errors</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + window.addEventListener("onunhandledrejection", unreachable); + + const test_load = async_test( + "Instantiation errors in different files should be reported " + + "depending on different roots"); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 4); + + // Two different instantiation errors from different module scripts + // should be reported for each <script> element. + assert_equals(log[0].constructor, SyntaxError); + assert_equals(log[1], 1); + + assert_equals(log[2].constructor, SyntaxError); + assert_equals(log[3], 2); + + assert_not_equals(log[0], log[2], + 'two different instantiation errors should be reported'); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./choice-of-error-2a.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./choice-of-error-2b.js" + onerror="unreachable()" onload="log.push(2)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2a.js new file mode 100644 index 0000000000..2dc7aac11a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2a.js @@ -0,0 +1,2 @@ +import './choice-of-error-2b.js'; +import './instantiation-error-1.js?2c'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2b.js new file mode 100644 index 0000000000..2adb9eea59 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-2b.js @@ -0,0 +1,2 @@ +import './choice-of-error-2a.js'; +import './instantiation-error-1.js?2d'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html new file mode 100644 index 0000000000..bc52119bfe --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<title>Choice of evaluation errors</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + window.addEventListener("onunhandledrejection", unreachable); + + const test_load = async_test( + "Evaluation errors are cached in intermediate module scripts"); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 5); + + // Evaluation errors, unlike parse/instantiation errors, are remembered + // and cached in module scripts between the root and the script that + // caused an evaluation error, and thus the same evaluation error + // is reported for both <script> elements. + assert_equals(log[0], "throw2"); + assert_true(log[1].bar); + assert_equals(log[2], 1); + + assert_true(log[3].bar); + assert_equals(log[4], 2); + + assert_equals(log[1], log[3], 'evaluation errors must be the same'); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./choice-of-error-3a.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./choice-of-error-3b.js" + onerror="unreachable()" onload="log.push(2)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3a.js new file mode 100644 index 0000000000..71154674a3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3a.js @@ -0,0 +1,2 @@ +import './choice-of-error-3b.js'; +import './throw.js?3c'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3b.js new file mode 100644 index 0000000000..2131a35eff --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/choice-of-error-3b.js @@ -0,0 +1,2 @@ +import './choice-of-error-3a.js'; +import './throw2.js?3d'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/compilation-error-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/compilation-error-1.html new file mode 100644 index 0000000000..ff580d4899 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/compilation-error-1.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Handling of compilation errors, 1</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that syntax errors lead to SyntaxError events on window, " + + "and that exceptions are remembered."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 5); + assert_equals(log[0].constructor, SyntaxError); + assert_true(log.every(exn => exn === log[0])); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./syntaxerror.js" onerror="unreachable()"></script> +<script type="module" src="./syntaxerror.js" onerror="unreachable()"></script> +<script type="module" src="./syntaxerror-nested.js" onerror="unreachable()"></script> +<script type="module" src="./syntaxerror.js" onerror="unreachable()"></script> +<script type="module" src="./syntaxerror-nested.js" onerror="unreachable()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/compilation-error-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/compilation-error-2.html new file mode 100644 index 0000000000..131a6e439f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/compilation-error-2.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Handling of compilation errors, 2</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that syntax errors lead to SyntaxError events on window, " + + "and that exceptions are remembered."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 5); + assert_equals(log[0].constructor, SyntaxError); + assert_true(log.every(exn => exn === log[0])); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./syntaxerror-nested.js" onerror="unreachable()"></script> +<script type="module" src="./syntaxerror-nested.js" onerror="unreachable()"></script> +<script type="module" src="./syntaxerror.js" onerror="unreachable()"></script> +<script type="module" src="./syntaxerror-nested.js" onerror="unreachable()"></script> +<script type="module" src="./syntaxerror.js" onerror="unreachable()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/credentials.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/credentials.sub.html new file mode 100644 index 0000000000..983961ae44 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/credentials.sub.html @@ -0,0 +1,68 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +document.cookie = 'same=1'; + +const setCookiePromise = fetch( + 'http://{{domains[www2]}}:{{ports[http][0]}}/cookies/resources/set-cookie.py?name=cross&path=/html/semantics/scripting-1/the-script-element/module/', + { + mode: 'no-cors', + credentials: 'include', + }); + +const windowLoadPromise = new Promise(resolve => { + window.addEventListener('load', () => { + resolve(); + }); +}); + +promise_test(t => { + const iframe = document.createElement('iframe'); + + return Promise.all([setCookiePromise, windowLoadPromise]).then(() => { + const messagePromise = new Promise(resolve => { + window.addEventListener('message', event => { + resolve(); + }); + }); + + iframe.src = 'resources/credentials-iframe.sub.html'; + document.body.appendChild(iframe); + + return messagePromise; + }).then(() => { + const w = iframe.contentWindow; + + assert_equals(w.sameOriginNone, 'found', + 'Modules should be loaded with the credentials when the crossOrigin attribute is not specified and the target is same-origin'); + assert_equals(w.sameOriginAnonymous, 'found', + 'Modules should be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is same-origin'); + assert_equals(w.sameOriginUseCredentials, 'found', + 'Modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is same-origin'); + assert_equals(w.crossOriginNone, 'not found', + 'Modules should not be loaded with the credentials when the crossOrigin attribute is not specified and the target is cross-origin'); + assert_equals(w.crossOriginAnonymous, 'not found', + 'Modules should not be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is cross-origin'); + assert_equals(w.crossOriginUseCredentials, 'found', + 'Modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is cross-origin'); + + assert_equals(w.sameOriginNoneDescendant, 'found', + 'Descendant modules should be loaded with the credentials when the crossOrigin attribute is not specified and the target is same-origin'); + assert_equals(w.sameOriginAnonymousDescendant, 'found', + 'Descendant modules should be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is same-origin'); + assert_equals(w.sameOriginUseCredentialsDescendant, 'found', + 'Descendant modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is same-origin'); + assert_equals(w.crossOriginNoneDescendant, 'not found', + 'Descendant modules should not be loaded with the credentials when the crossOrigin attribute is not specified and the target is cross-origin'); + assert_equals(w.crossOriginAnonymousDescendant, 'not found', + 'Descendant modules should not be loaded with the credentials when the crossOrigin attribute is specified with "anonymous" as its value and the target is cross-origin'); + assert_equals(w.crossOriginUseCredentialsDescendant, 'found', + 'Descendant modules should be loaded with the credentials when the crossOrigin attribute is specified with "use-credentials" as its value and the target is cross-origin'); +}); +}, 'Modules should be loaded with or without the credentials based on the same-origin-ness and the crossOrigin attribute'); +</script> +<body> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-common.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-common.js new file mode 100644 index 0000000000..59bf0fd42f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-common.js @@ -0,0 +1,8 @@ +document._log = []; +window.addEventListener("error", function (ev) { + var errorSerialized = ev.lineno + "-" + ev.colno; + document._log.push(errorSerialized); +}); +window.addEventListener("load", function () { + document._log = document._log.join(","); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-different.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-different.sub.html new file mode 100644 index 0000000000..8eb3292e89 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-different.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>html-script-module-crossOrigin-import-NoCORS</title> + <script src="crossorigin-common.js"></script> +</head> +<body> + <h1>html-script-module-crossOrigin-import-NoCORS</h1> + <script type="module" onerror="document._log.push('error');"> + + import { foo } from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js"; + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-missingheader.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-missingheader.sub.html new file mode 100644 index 0000000000..cccb30f718 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-missingheader.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>html-script-module-crossOrigin-root-BlockedMissingHeader</title> + <script src="crossorigin-common.js"></script> +</head> +<body> + <h1>html-script-module-crossOrigin-root-BlockedMissingHeader</h1> + <script type="module" onerror="document._log.push('error');" crossorigin> + + import { foo } from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js"; + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-same.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-same.sub.html new file mode 100644 index 0000000000..84f4de1d7e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-same.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>html-script-module-crossOrigin-root-WithCORS</title> + <script src="crossorigin-common.js"></script> +</head> +<body> + <h1>html-script-module-crossOrigin-root-WithCORS</h1> + <script type="module" crossorigin> + + import { foo } from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js?pipe=header(Access-Control-Allow-Origin,*)"; + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-wrongheader.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-wrongheader.sub.html new file mode 100644 index 0000000000..5743a9e304 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-import-wrongheader.sub.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<html> +<head> + <title>html-script-module-crossOrigin-root-BlockedWrongHeader</title> + <script src="crossorigin-common.js"></script> +</head> +<body> + <h1>html-script-module-crossOrigin-root-BlockedWrongHeader</h1> + <script type="module" onerror="document._log.push('error');" crossorigin> + + import { foo } from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js?pipe=header(Access-Control-Allow-Origin,http://{{domains[www2]}}:{{ports[http][0]}})"; + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-different.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-different.sub.html new file mode 100644 index 0000000000..54d4354c53 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-different.sub.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> + <title>html-script-module-crossOrigin-root-NoCORS</title> + <script src="crossorigin-common.js"></script> +</head> +<body> + <h1>html-script-module-crossOrigin-root-NoCORS</h1> + <script type="module" src="http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js" onerror="document._log.push('error');"></script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-missingheader.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-missingheader.sub.html new file mode 100644 index 0000000000..03943002ba --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-missingheader.sub.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> + <title>html-script-module-crossOrigin-root-BlockedMissingHeader</title> + <script src="crossorigin-common.js"></script> +</head> +<body> + <h1>html-script-module-crossOrigin-root-BlockedMissingHeader</h1> + <script type="module" src="http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js" onerror="document._log.push('error');" crossorigin></script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-same.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-same.sub.html new file mode 100644 index 0000000000..3ec839e9a9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-same.sub.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> + <title>html-script-module-crossOrigin-root-WithCORS</title> + <script src="crossorigin-common.js"></script> +</head> +<body> + <h1>html-script-module-crossOrigin-root-WithCORS</h1> + <script type="module" src="http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js?pipe=header(Access-Control-Allow-Origin,*)" crossorigin></script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-wrongheader.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-wrongheader.sub.html new file mode 100644 index 0000000000..c45736a896 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-root-wrongheader.sub.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> + <title>html-script-module-crossOrigin-root-BlockedWrongHeader</title> + <script src="crossorigin-common.js"></script> +</head> +<body> + <h1>html-script-module-crossOrigin-root-BlockedWrongHeader</h1> + <script type="module" src="http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js?pipe=header(Access-Control-Allow-Origin,http://{{domains[www2]}}:{{ports[http][0]}})" onerror="document._log.push('error');" crossorigin></script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js new file mode 100644 index 0000000000..29d04ec619 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js @@ -0,0 +1,8 @@ +export var foo = {}; + +// Push an event to the log indicating that the script was executed. +document._log.push("running"); + +// Deliberately trigger an error to test what details of the error +// the (possibly) cross-origin parent can listen to. +nonExistentMethod(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin.html new file mode 100644 index 0000000000..5c8d6667b0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/crossorigin.html @@ -0,0 +1,43 @@ +<!doctype html> +<html> +<head> + <title>html-script-module-crossOrigin</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <h1>html-script-module-crossOrigin</h1> + <iframe id="root-WithCORS" src="crossorigin-root-same.sub.html"></iframe> + <iframe id="root-NoCORS" src="crossorigin-root-different.sub.html"></iframe> + <iframe id="root-BlockedMissingHeader" src="crossorigin-root-missingheader.sub.html"></iframe> + <iframe id="root-BlockedWrongHeader" src="crossorigin-root-wrongheader.sub.html"></iframe> + <iframe id="import-WithCORS" src="crossorigin-import-same.sub.html"></iframe> + <iframe id="import-NoCORS" src="crossorigin-import-different.sub.html"></iframe> + <iframe id="import-BlockedMissingHeader" src="crossorigin-import-missingheader.sub.html"></iframe> + <iframe id="import-BlockedWrongHeader" src="crossorigin-import-wrongheader.sub.html"></iframe> + <script> + + var tests = [ + { "obj": async_test("Root module, Error in CORS-same-origin script"), "id": "root-WithCORS", "expected": "running,8-1" }, + { "obj": async_test("Root module, Blocked script download, missing CORS ACAO header"), "id": "root-NoCORS", "expected": "error" }, + { "obj": async_test("Root module, Blocked script download, crossorigin attribute with missing CORS ACAO header"), "id": "root-BlockedMissingHeader", "expected": "error" }, + { "obj": async_test("Root module, Blocked script download, mismatched CORS ACAO header"), "id": "root-BlockedWrongHeader", "expected": "error" }, + { "obj": async_test("Imported module, Error in CORS-same-origin script"), "id": "import-WithCORS", "expected": "running,8-1" }, + { "obj": async_test("Imported module, Blocked script download, missing CORS ACAO header"), "id": "import-NoCORS", "expected": "error" }, + { "obj": async_test("Imported module, Blocked script download, crossorigin attribute with missing CORS ACAO header"), "id": "import-BlockedMissingHeader", "expected": "error" }, + { "obj": async_test("Imported module, Blocked script download, mismatched CORS ACAO header"), "id": "import-BlockedWrongHeader", "expected": "error" }, + ]; + + window.addEventListener("load", function () { + tests.forEach(function (test) { + var target = document.getElementById(test.id); + test.obj.step(function () { + assert_equals(target.contentDocument._log, test.expected, "Unexpected _log value"); + }); + test.obj.done(); + }); + }); + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/currentScript-null.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/currentScript-null.html new file mode 100644 index 0000000000..146a9db60d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/currentScript-null.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="module" src="set-currentScript-on-window.js"></script> +<script type="module"> +import { currentScriptOnImportedModule } from "./currentscript.js"; + +test(() => { + assert_equals(document.currentScript, null, "document.currentScript on inline scripts should be null"); + assert_equals(currentScriptOnImportedModule, null, "document.currentScript on imported scripts should be null"); + assert_equals(window.currentScriptRecorded, null, "document.currentScript on external module scripts should be null"); +}, "currentScript on script type=module should be all null"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/currentscript.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/currentscript.js new file mode 100644 index 0000000000..547359ff96 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/currentscript.js @@ -0,0 +1 @@ +export let currentScriptOnImportedModule = window.document.currentScript; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/custom-element-exception.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/custom-element-exception.html new file mode 100644 index 0000000000..bd77a8f1bb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/custom-element-exception.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<title>Handling of exceptions in custom element constructors</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that exceptions from the constructor of a custom element " + + "inside a module are propagated as expected.\n"); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(1, log.length); + const exception = log[0]; + assert_true(exception instanceof Error); + assert_equals(exception.message, "custom element error"); + })); +</script> +<script type="module"> + class XThrower extends HTMLElement { + constructor() { + super(); + throw new Error("custom element error"); + } + } + customElements.define("x-thrower", XThrower); + document.createElement("x-thrower"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-tdz-access-a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-tdz-access-a.js new file mode 100644 index 0000000000..1f91f93eb1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-tdz-access-a.js @@ -0,0 +1,3 @@ +log.push("cycle-tdz-access-a"); +import { Y } from "./cycle-tdz-access.js"; +export var X = Y; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-tdz-access.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-tdz-access.js new file mode 100644 index 0000000000..9df68b3b27 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-tdz-access.js @@ -0,0 +1,3 @@ +log.push("cycle-tdz-access"); +import { X } from "./cycle-tdz-access-a.js"; +export let Y = X; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-unresolvable-a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-unresolvable-a.js new file mode 100644 index 0000000000..12994f23d0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-unresolvable-a.js @@ -0,0 +1,2 @@ +export {x} from "./cycle-unresolvable.js"; +log.push("cycle-unresolvable-a"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-unresolvable.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-unresolvable.js new file mode 100644 index 0000000000..61c6d8dcb0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/cycle-unresolvable.js @@ -0,0 +1,2 @@ +export {x} from "./cycle-unresolvable-a.js"; +log.push("cycle-unresolvable"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/duplicated-imports-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/duplicated-imports-1.html new file mode 100644 index 0000000000..57002a3e07 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/duplicated-imports-1.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<title>Importing a module multiple times with the same specifier</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +window.log = []; +</script> +<script type="module"> +import { foo } from './export-something.js'; +import { set_foo } from './export-something.js'; +import default1 from './export-default.js'; +import default2 from './export-default.js'; + +test(() => { + assert_array_equals(log, ['export-something', 'export-default']); + assert_equals(foo, 42); + set_foo(43); + assert_equals(foo, 43); + assert_equals(default1, "fox"); + assert_equals(default2, "fox"); +}, 'Duplicated imports with the same specifier'); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/duplicated-imports-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/duplicated-imports-2.html new file mode 100644 index 0000000000..6a01495c33 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/duplicated-imports-2.html @@ -0,0 +1,23 @@ +<!DOCTYPE html> +<title>Importing a module multiple times with the different specifier</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +window.log = []; +</script> +<script type="module"> +import { foo } from './export-something.js'; +import { set_foo } from '../module/export-something.js'; +import default1 from './export-default.js'; +import default2 from '../module/export-default.js'; + +test(() => { + assert_array_equals(log, ['export-something', 'export-default']); + assert_equals(foo, 42); + set_foo(43); + assert_equals(foo, 43); + assert_equals(default1, "fox"); + assert_equals(default2, "fox"); +}, 'Duplicated imports with the different specifier'); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/base-url-worker-importScripts.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/base-url-worker-importScripts.html new file mode 100644 index 0000000000..817cf6d5dd --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/base-url-worker-importScripts.html @@ -0,0 +1,7 @@ +<!DOCTYPE html> +<title>Base URLs used in resolving specifiers in dynamic imports from importScripts()</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +fetch_tests_from_worker(new Worker("./worker-importScripts.sub.js")); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/base-url-worker.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/base-url-worker.sub.html new file mode 100644 index 0000000000..a12204281c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/base-url-worker.sub.html @@ -0,0 +1,8 @@ +<!DOCTYPE html> +<title>Base URLs used in resolving specifiers in dynamic imports from workers</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +fetch_tests_from_worker(new Worker( + "../beta/redirect.py?location=http://{{host}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/base-url.sub.js")); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/base-url.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/base-url.sub.html new file mode 100644 index 0000000000..f7d4927a10 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/base-url.sub.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Base URLs used in resolving specifiers in dynamic imports</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +self.testName = "same origin classic <script>"; +self.baseUrlSanitized = false; +</script> +<script src="../beta/redirect.py?location=http://{{host}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/base-url.sub.js"></script> + +<script> +self.testName = "cross origin classic <script> without crossorigin attribute"; +self.baseUrlSanitized = true; +</script> +<script src="../beta/redirect.py?location=http://{{hosts[alt][]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/base-url.sub.js"></script> + +<script> +self.testName = "cross origin classic <script> with crossorigin attribute"; +self.baseUrlSanitized = false; +</script> +<script src="../beta/redirect.py?location=http://{{hosts[alt][]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/base-url.sub.js%3Fpipe=header(Access-Control-Allow-Origin,*)" crossorigin></script> + +<script> +self.testName = "cross origin module <script>"; +self.baseUrlSanitized = false; +</script> +<script src="../beta/redirect.py?location=http://{{hosts[alt][]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/base-url.sub.js%3Fpipe=header(Access-Control-Allow-Origin,*)" type="module"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/code-cache.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/code-cache.js new file mode 100644 index 0000000000..8a8530c9b6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/code-cache.js @@ -0,0 +1,9 @@ +promise_test(() => { + return (new Function('w', 'return import(w)'))("./import.js?Function") + .then(module => assert_equals(module.A.from, 'alpha/import.js')); +}, 'alpha - Function'); + +promise_test(() => { + return eval('import("./import.js?eval")') + .then(module => assert_equals(module.A.from, 'alpha/import.js')); +}, 'alpha - eval'); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/import.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/import.js new file mode 100644 index 0000000000..b2ac52df2a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/import.js @@ -0,0 +1 @@ +export const A = { "from": "alpha/import.js" }; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/worker-importScripts.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/worker-importScripts.sub.js new file mode 100644 index 0000000000..904d32f9bf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/alpha/worker-importScripts.sub.js @@ -0,0 +1,15 @@ +"use strict"; + +importScripts("/resources/testharness.js"); + +// CORS-same-origin +self.testName = "same-origin importScripts()"; +self.baseUrlSanitized = false; +importScripts("../beta/redirect.py?location=http://{{host}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/base-url.sub.js"); + +// CORS-cross-origin +self.testName = "cross-origin importScripts()"; +self.baseUrlSanitized = true; +importScripts("../beta/redirect.py?location=http://{{hosts[alt][]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/base-url.sub.js"); + +done(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/beta/code-cache.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/beta/code-cache.js new file mode 100644 index 0000000000..1c2a2b636a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/beta/code-cache.js @@ -0,0 +1,9 @@ +promise_test(() => { + return (new Function('w', 'return import(w)'))("./import.js?Function") + .then(module => assert_equals(module.A.from, 'beta/import.js')); +}, 'beta - Function'); + +promise_test(() => { + return eval('import("./import.js?eval")') + .then(module => assert_equals(module.A.from, 'beta/import.js')); +}, 'beta - eval'); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/beta/import.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/beta/import.js new file mode 100644 index 0000000000..7de1c68182 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/beta/import.js @@ -0,0 +1 @@ +export const A = { "from": "beta/import.js" }; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/beta/redirect.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/beta/redirect.py new file mode 100644 index 0000000000..f2fd1ebd51 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/beta/redirect.py @@ -0,0 +1,19 @@ +def main(request, response): + """Simple handler that causes redirection. + + The request should typically have two query parameters: + status - The status to use for the redirection. Defaults to 302. + location - The resource to redirect to. + """ + status = 302 + if b"status" in request.GET: + try: + status = int(request.GET.first(b"status")) + except ValueError: + pass + + response.status = status + + location = request.GET.first(b"location") + + response.headers.set(b"Location", location) diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url-workers.window.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url-workers.window.js new file mode 100644 index 0000000000..70cb20fa57 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url-workers.window.js @@ -0,0 +1,60 @@ +function objectUrlFromModule(module) { + const blob = new Blob([module], { type: "text/javascript" }); + return URL.createObjectURL(blob); +} + +const moduleText = `export const foo = "bar";`; + +async_test((t) => { + const moduleBlobUrl = objectUrlFromModule(moduleText); + t.add_cleanup(() => URL.revokeObjectURL(moduleBlobUrl)); + + const worker = new Worker("./resources/blob-url-worker.js"); + worker.postMessage(moduleBlobUrl); + + worker.addEventListener( + "message", + t.step_func_done((evt) => { + assert_true(evt.data.importSucceeded); + assert_equals(evt.data.module.foo, "bar"); + }) + ); +}, "A blob URL created in a window agent can be imported from a worker"); + +async_test((t) => { + const moduleBlobUrl = objectUrlFromModule(moduleText); + URL.revokeObjectURL(moduleBlobUrl); + + const worker = new Worker("./resources/blob-url-worker.js"); + worker.postMessage(moduleBlobUrl); + + worker.addEventListener( + "message", + t.step_func_done((evt) => { + assert_false(evt.data.importSucceeded); + assert_equals(evt.data.errorName, "TypeError"); + }) + ); +}, "A blob URL revoked in a window agent will not resolve in a worker"); + +promise_test(async (t) => { + const moduleBlobUrl = objectUrlFromModule(moduleText); + + await import(moduleBlobUrl); + + URL.revokeObjectURL(moduleBlobUrl); + + const worker = new Worker("./resources/blob-url-worker.js"); + worker.postMessage(moduleBlobUrl); + + await new Promise((resolve) => { + worker.addEventListener( + "message", + t.step_func((evt) => { + assert_false(evt.data.importSucceeded); + assert_equals(evt.data.errorName, "TypeError"); + resolve(); + }) + ); + }); +}, "A revoked blob URL will not resolve in a worker even if it's in the window's module graph"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.js new file mode 100644 index 0000000000..0719a18bf1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.js @@ -0,0 +1,66 @@ +// META: global=window,dedicatedworker,sharedworker,dedicatedworker-module,sharedworker-module + +function objectUrlFromModule(module) { + const blob = new Blob([module], { type: "text/javascript" }); + return URL.createObjectURL(blob); +} + +const moduleText = `export const foo = "bar";`; + +promise_test(async (t) => { + const moduleBlobUrl = objectUrlFromModule(moduleText); + t.add_cleanup(() => URL.revokeObjectURL(moduleBlobUrl)); + + const module = await import(moduleBlobUrl); + assert_equals(module.foo, "bar"); +}, "Blob URLs are supported in dynamic imports"); + +promise_test(async (t) => { + const moduleBlobUrl = objectUrlFromModule(moduleText); + t.add_cleanup(() => URL.revokeObjectURL(moduleBlobUrl)); + + const module1 = await import(moduleBlobUrl); + const module2 = await import(moduleBlobUrl); + assert_equals(module1, module2); +}, "Identical blob URLs resolve to the same module"); + +promise_test(async (t) => { + const moduleBlob = new Blob([moduleText], { type: "text/javascript" }); + const moduleBlobUrl1 = URL.createObjectURL(moduleBlob); + const moduleBlobUrl2 = URL.createObjectURL(moduleBlob); + t.add_cleanup(() => { + URL.revokeObjectURL(moduleBlobUrl1); + URL.revokeObjectURL(moduleBlobUrl2); + }); + + const module1 = await import(moduleBlobUrl1); + const module2 = await import(moduleBlobUrl2); + assert_not_equals(module1, module2); +}, "Different blob URLs pointing to the same blob resolve to different modules"); + +promise_test(async (t) => { + const moduleBlobUrl = objectUrlFromModule(moduleText); + URL.revokeObjectURL(moduleBlobUrl); + + await promise_rejects_js(t, TypeError, import(moduleBlobUrl)); +}, "A revoked blob URL will not resolve"); + +promise_test(async () => { + const moduleBlobUrl = objectUrlFromModule(moduleText); + const module1 = await import(moduleBlobUrl); + + URL.revokeObjectURL(moduleBlobUrl); + + const module2 = await import(moduleBlobUrl); + assert_equals(module1, module2); +}, "A revoked blob URL will resolve if it's already in the module graph"); + +promise_test(async () => { + const moduleBlobUrl = objectUrlFromModule(moduleText); + + const importPromise = import(moduleBlobUrl); + URL.revokeObjectURL(moduleBlobUrl); + + const module = await importPromise; + assert_equals(module.foo, "bar"); +}, "Revoking a blob URL immediately after calling import will not fail"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/code-cache-base-url.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/code-cache-base-url.html new file mode 100644 index 0000000000..688a6193a5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/code-cache-base-url.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<!-- +Regression test for https://crbug.com/990810: +Functions with the same source code shouldn't be cached if their referencing +scripts and host defined options are different. + +Each Function in the following three scripts should have different base URLs +respectively, but in https://crbug.com/990810 the Function in +`gamma/code-cache.js` reuses the Function in `beta/code-cache.js`, resulting in +wrong base URL. +--> + +<script src="alpha/code-cache.js"></script> +<script src="beta/code-cache.js"></script> +<script src="gamma/code-cache.js"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/code-cache-nonce.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/code-cache-nonce.html new file mode 100644 index 0000000000..bd920f8107 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/code-cache-nonce.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<script> +// Regression test for https://crbug.com/979351: +// This test loads a same script file (`resources/code-cache-nonce.js`) +// with three different nonces (i.e. different host defined options). +// Dynamic imports from the script therefore should have different nonces, +// but when code caching ignores the difference in nonces, the first nonce +// ('abc') is reused incorrectly for subsequent dynamic imports, causing +// CSP violation (and thus dynamic import rejection). + +function runTest(nonce, description) { + // Perform a dynamic import with nonce=`nonce` + // from a page (`iframe`) with a matching CSP script-src 'nonce-`nonce`'. + // This should be successful. + promise_test(t => { + return new Promise((resolve, reject) => { + const iframe = document.createElement('iframe'); + iframe.src = 'resources/code-cache-nonce-iframe.sub.html?nonce=' + nonce; + iframe.onload = () => { + // `globalThis.promise` is set by `resources/code-cache-nonce.js`. + // `t.step_timeout()` is workaround for https://crbug.com/1247801. + globalThis.promise.then( + v => t.step_timeout(() => resolve(v), 0), + v => t.step_timeout(() => reject(v), 0) + ); + }; + document.body.appendChild(iframe); + t.add_cleanup(() => iframe.remove()); + }); + }, description); +} + +// As `promise_test` are serialized, each iframe is created after previous +// iframes and scripts are completely loaded. +runTest('abc', 'First dynamic import should use nonce=abc'); +runTest('def', 'Second dynamic import should use nonce=def'); +runTest('ghi', 'Third dynamic import should use nonce=ghi'); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/delay-load-event.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/delay-load-event.html new file mode 100644 index 0000000000..5ec6433e65 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/delay-load-event.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<title>Dynamic imports don't delay the load event</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +// Dynamic imports don't #delay-the-load-event. +// Therefore, Window load event would be fired +// just after the dynamic import() below starts. +window.loaded = []; +window.addEventListener('load', () => loaded.push('Window load event')); +promise_test(t => { + loaded.push('import start'); + // This 'loading' log is added to detect the previous Chromium behavior + // where the Window load event is delayed until just before script + // element's load event. + t.step_timeout(() => loaded.push('loading'), 1000); + return import("../resources/slow-module.js?pipe=trickle(d2)") + .then(() => { + assert_array_equals( + loaded, + ['import start', 'Window load event', 'loading', 'slow'], + "Window load event shouldn't be delayed by dynamic imports"); + }); +}, "Dynamic imports don't delay the load event."); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-credentials-setTimeout.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-credentials-setTimeout.sub.html new file mode 100644 index 0000000000..189aa819fa --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-credentials-setTimeout.sub.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/dynamic-import-credentials-helper.sub.js"></script> + +<script type="text/javascript"> +runTestsFromIframe('../resources/dynamic-import-credentials-setTimeout-iframe.sub.html'); +</script> +<body> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-credentials.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-credentials.sub.html new file mode 100644 index 0000000000..910644531c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-credentials.sub.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/dynamic-import-credentials-helper.sub.js"></script> + +<script type="text/javascript"> +runTestsFromIframe('../resources/dynamic-import-credentials-iframe.sub.html'); +</script> +<body> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-fetch-error.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-fetch-error.sub.html new file mode 100644 index 0000000000..12738c7b97 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-fetch-error.sub.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<title>import(): error cases occuring during fetching</title> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> +<script type="module"> +const cases = [ + ["wrong MIME type", "../errorhandling-wrongMimetype.js?pipe=header(Content-Type,text/plain)"], + ["wrong MIME type of a dependency", "../errorhandling-wrongMimetype-import.js"], + ["404", "../resources/404-but-js.asis"], + ["404 of a dependency", "../resources/imports-404-but-js.js"], + ["500", "../resources/500-but-js.asis"], + ["500 of a dependency", "../resources/imports-500-but-js.js"], + ["cross-origin module (without CORS)", "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/imports-a.js"], + ["cross-origin module dependency (without CORS)", "../resources/imports-b-cross-origin.sub.js"] +]; + +for (const [label, specifier] of cases) { + promise_test(t => { + return promise_rejects_js(t, TypeError, import(specifier)); + }, "import() must reject when there is a " + label); + + promise_test(async t => { + // The use of ?x is used to separate tests so they don't interfere with each other. + // (However, it shouldn't matter anyway, in a spec-compliant implementation.) + const suffix = (specifier.includes("?") ? "&" : "?") + "x"; + const promise1 = import(specifier + suffix); + const promise2 = import(specifier + suffix); + + await promise_rejects_js(t, TypeError, promise1, "It must reject the first time"); + await promise_rejects_js(t, TypeError, promise2, "It must reject the second time"); + + const error1 = await promise1.catch(e => e); + const error2 = await promise2.catch(e => e); + + assert_not_equals(error1, error2, "The error objects must be different"); + }, "import() must reject with a different error object for each import when there is a " + label); +} + +promise_test(async t => { + const id = token(); + const url = `./resources/status-changing-script.py?id=${id}`; + + // Serve HTTP 404 for the first import(). + await fetch(url + '&newStatus=404'); + const promise1 = import(url); + await promise_rejects_js(t, TypeError, promise1, + "First import() must be rejected due to 404"); + + // Serve HTTP 200 after the first import() completes. + await fetch(url + '&newStatus=200'); + const r = await fetch(url, { cache: 'no-cache' }); + assert_equals(r.status, 200); + + const promise2 = import(url); + await promise_rejects_js(t, TypeError, promise2, + "Second import() must be rejected, because the result of " + + "the first import() is cached in the module map"); +}, "import() fetch errors must be cached"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-script-error.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-script-error.html new file mode 100644 index 0000000000..e9b10e3bab --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports-script-error.html @@ -0,0 +1,53 @@ +<!DOCTYPE html> +<title>import(): error cases caused by the imported module script</title> +<link rel="author" title="Kouhei Ueno" href="mailto:kouhei@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script type="module"> +const cases = [ + ["parse error", "../syntaxerror.js", SyntaxError], + ["bad module specifier", "does-not-start-with-dot.js", TypeError, { differentErrorObjects: true }], + ["bad module specifier in a dependency", "../bad-module-specifier.js", TypeError], + ["instantiation error", "../instantiation-error-1.js", SyntaxError, { differentErrorObjects: true }], + ["evaluation error", "../throw-error.js", Error] +]; + +for (const [label, specifier, error, { differentErrorObjects } = {}] of cases) { + promise_test(t => { + return promise_rejects_js(t, error, import(specifier)); + }, "import() must reject when there is a " + label); + + const errorObjectsLabel = differentErrorObjects ? "different error objects" : "the same error object"; + promise_test(async t => { + // The use of ?x is used to separate tests so they don't interfere with each other. + // (However, it shouldn't matter anyway, in a spec-compliant implementation.) + const promise1 = import(specifier + "?x"); + const promise2 = import(specifier + "?x"); + + await promise_rejects_js(t, error, promise1, "It must reject the first time"); + await promise_rejects_js(t, error, promise2, "It must reject the second time"); + + const error1 = await promise1.catch(e => e); + const error2 = await promise2.catch(e => e); + + if (differentErrorObjects) { + assert_not_equals(error1, error2, "The error objects must be different"); + } else { + assert_equals(error1, error2, "The error objects must be equal"); + } + }, `import() must reject with ${errorObjectsLabel} for each import when there is a ${label}`); +} + +promise_test(t => { + delete window.before_throwing_error; + delete window.after_throwing_error; + + return promise_rejects_js(t, Error, import("../throw-error.js?y")).then(() => { + assert_true(window.before_throwing_error, + "the module script should run to a point where it throws exception"); + assert_equals(window.after_throwing_error, undefined, + "the module script should not run after it throws exception"); + }); +}, "import()ing a module with an evaluation error must stop evaluation"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports.html new file mode 100644 index 0000000000..9807e21b0d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/dynamic-imports.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<title>Basic dynamic imports</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="module"> +promise_test(t => { + return import("./../imports-a.js").then(module => { + assert_true(window.evaluated_imports_a); + assert_equals(module.A["from"], "imports-a.js"); + }); +}, "Dynamic imports should resolve module."); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/base-url.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/base-url.sub.js new file mode 100644 index 0000000000..ec7784983d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/base-url.sub.js @@ -0,0 +1,58 @@ +"use strict"; + +// This script triggers import(), and thus the base URL of this script +// (either loaded by `<script>` or `importScripts()`) is used as the base URL +// of resolving relative URL-like specifiers in `import()`. + +// The following fields should be set by the callers of this script +// (unless loaded as the worker top-level script): +// - self.testName (string) +// - self.baseUrlSanitized (boolean) + +// When this script is loaded as the worker top-level script: +if ('DedicatedWorkerGlobalScope' in self && + self instanceof DedicatedWorkerGlobalScope && + !self.testName) { + importScripts("/resources/testharness.js"); + self.testName = 'worker top-level script'; + // Worker top-level scripts are always same-origin. + self.baseUrlSanitized = false; +} + +{ + // This could change by the time the test is executed, so we save it now. + // As this script is loaded multiple times, savedBaseUrlSanitized is scoped. + const savedBaseUrlSanitized = self.baseUrlSanitized; + + promise_test(() => { + const promise = import("./import.js?pipe=header(Access-Control-Allow-Origin,*)&label=relative-" + self.testName); + if (savedBaseUrlSanitized) { + // The base URL is "about:blank" and thus import() here should fail. + return promise.then(module => { + // This code should be unreached, but assert_equals() is used here + // to log `module.A["from"]` in case of unexpected resolution. + assert_equals(module.A["from"], "(unreached)", + "Relative URL-like specifier resolution should fail"); + assert_unreached(); + }, + () => {}); + } else { + // The base URL is the response URL of this script, i.e. + // `.../gamma/base-url.sub.js`. + return promise.then(module => { + assert_equals(module.A["from"], "gamma/import.js"); + }); + } + }, + "Relative URL-like from " + self.testName); +} + +promise_test(() => { + return import("http://{{hosts[alt][]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/import.js?pipe=header(Access-Control-Allow-Origin,*)&label=absolute-" + self.testName) + .then(module => { + assert_equals(module.A["from"], "gamma/import.js"); + }) + }, + "Absolute URL-like from " + self.testName); + +done(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/code-cache.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/code-cache.js new file mode 100644 index 0000000000..b470bc8ae5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/code-cache.js @@ -0,0 +1,9 @@ +promise_test(() => { + return (new Function('w', 'return import(w)'))("./import.js?Function") + .then(module => assert_equals(module.A.from, 'gamma/import.js')); +}, 'gamma - Function'); + +promise_test(() => { + return eval('import("./import.js?eval")') + .then(module => assert_equals(module.A.from, 'gamma/import.js')); +}, 'gamma - eval'); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/import.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/import.js new file mode 100644 index 0000000000..435c1369be --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/gamma/import.js @@ -0,0 +1 @@ +export const A = { "from": "gamma/import.js" }; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/inline-event-handler.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/inline-event-handler.html new file mode 100644 index 0000000000..13cc8b6624 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/inline-event-handler.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id='div' onmousedown='import("./../imports-a.js").then(window.continueTest);'></div> +<script> +const div = document.getElementById('div'); + +promise_test(t => { + const promise = new Promise(resolve => window.continueTest = resolve); + + const event = new MouseEvent('mousedown', {'button': 1}); + div.dispatchEvent(event); + + return promise.then(() => { + assert_true(window.evaluated_imports_a); + div.parentNode.removeChild(div); + }); +}, "dynamic import should work when triggered from inline event handlers"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/basic.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/basic.any.js new file mode 100644 index 0000000000..82cb3b215d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/basic.any.js @@ -0,0 +1,32 @@ +// META: global=window,dedicatedworker,sharedworker +// META: script=ticker.js + +promise_test(async t => { + const getCount = ticker(1000); + + const importP = import("<invalid>"); + await promise_rejects_js(t, TypeError, importP, 'import() should reject'); + + assert_less_than(getCount(), 1000); +}, "import() should not drain the microtask queue if it fails during specifier resolution"); + +promise_test(async t => { + // Use Date.now() to ensure that the module is not in the module map + const specifier = "./empty-module.js?" + Date.now(); + + await import(specifier); + + const getCount = ticker(1000); + await import(specifier); + assert_less_than(getCount(), 1000); +}, "import() should not drain the microtask queue when loading an already loaded module"); + +promise_test(async t => { + // Use Date.now() to ensure that the module is not in the module map + const specifier = "./empty-module.js?" + Date.now(); + + const getCount = ticker(1e7); + await import(specifier); + assert_equals(getCount(), 1e7); +}, "import() should drain the microtask queue when fetching a new module"); + diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/css-import-in-worker.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/css-import-in-worker.any.js new file mode 100644 index 0000000000..bd6f5d092f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/css-import-in-worker.any.js @@ -0,0 +1,14 @@ +// META: global=dedicatedworker,sharedworker +// META: script=ticker.js + +promise_test(async t => { + // Use Date.now() to ensure that the module is not in the module map + const specifier = "./empty-module.css?" + Date.now(); + + const getCount = ticker(1000); + + const importP = import(specifier, { assert: { type: "css" } }); + await promise_rejects_js(t, TypeError, importP, 'import() should reject'); + + assert_less_than(getCount(), 1000); +}, "import() should not drain the microtask queue if it fails because of the 'type: css' assertion in a worker"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/empty-module.css b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/empty-module.css new file mode 100644 index 0000000000..108e7649bd --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/empty-module.css @@ -0,0 +1,4 @@ +/* +This file is empty, because all it matters is if the +dynamic import that loads it fails or succedes. +*/ diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/empty-module.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/empty-module.js new file mode 100644 index 0000000000..108e7649bd --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/empty-module.js @@ -0,0 +1,4 @@ +/* +This file is empty, because all it matters is if the +dynamic import that loads it fails or succedes. +*/ diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/serviceworker.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/serviceworker.any.js new file mode 100644 index 0000000000..4c75cab1b6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/serviceworker.any.js @@ -0,0 +1,14 @@ +// META: global=serviceworker +// META: script=ticker.js + +promise_test(async t => { + // Use Date.now() to ensure that the module is not in the module map + const specifier = "./empty-module.js?" + Date.now(); + + const getCount = ticker(1000); + + const importP = import(specifier); + await promise_rejects_js(t, TypeError, importP, 'import() should reject'); + + assert_less_than(getCount(), 1000); +}, "import() should not drain the microtask queue if it fails because it's used in a ServiceWorker"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/ticker.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/ticker.js new file mode 100644 index 0000000000..42619b6e70 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/ticker.js @@ -0,0 +1,13 @@ +globalThis.ticker = function ticker(max) { + let i = 0; + let stop = false; + Promise.resolve().then(function loop() { + if (stop || i >= max) return; + i++; + Promise.resolve().then(loop); + }); + return () => { + stop = true; + return i; + }; +}; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/with-import-assertions.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/with-import-assertions.any.js new file mode 100644 index 0000000000..f67ba9a1ae --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/with-import-assertions.any.js @@ -0,0 +1,15 @@ +// META: global=window,dedicatedworker,sharedworker +// META: script=ticker.js + +promise_test(async t => { + // Use Date.now() to ensure that the module is not in the module map + const specifier = "./empty-module.js?" + Date.now(); + + const getCount = ticker(1000); + + const importP = import(specifier, { assert: { type: "<invalid>" } }); + await promise_rejects_js(t, TypeError, importP, 'import() should reject'); + + assert_less_than(getCount(), 1000); +}, "import() should not drain the microtask queue if it fails while validating the 'type' assertion"); + diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/worklet-ref.https.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/worklet-ref.https.html new file mode 100644 index 0000000000..6c598aee39 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/worklet-ref.https.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<canvas id ="output" width="100" height="100" style="background: blue;"></canvas> +<script> +"use strict"; +const canvas = document.getElementById('output'); +const ctx = canvas.getContext('2d'); + +ctx.fillStyle = 'green'; +ctx.fillRect(0, 0, 100, 100); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/worklet.https.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/worklet.https.html new file mode 100644 index 0000000000..5cd59f86dc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/worklet.https.html @@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<link rel="help" href="https://html.spec.whatwg.org/#hostimportmoduledynamically(referencingscriptormodule,-specifier,-promisecapability)"> +<link rel="match" href="worklet-ref.https.html"> +<style> +#output { + width: 100px; + height: 100px; + background-image: paint(rects); + background-color: blue; +} +</style> +<script src="/common/reftest-wait.js"></script> +<script src="/common/worklet-reftest.js"></script> +<body> +<div id="output"></div> + +<script id="code" type="text/worklet"> +registerPaint('rects', class { + async paint(ctx, geom) { + ctx.fillStyle = 'red'; + + const getCount = ticker(1000); + + try { + // Use Date.now() to ensure that the module is not in the module map + await import("./empty-module.js?" + Date.now()); + } catch (e) { + if (getCount() < 1000) { + ctx.fillStyle = 'green'; + } + } + ctx.fillRect(0, 0, geom.width, geom.height); + } +}); +</script> + +<script> +"use strict"; +CSS.paintWorklet.addModule("./ticker.js").then(() => + importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent) +); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/no-active-script-classic-manual.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/no-active-script-classic-manual.html new file mode 100644 index 0000000000..b01f595c03 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/no-active-script-classic-manual.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Dynamic import when there is no active script</title> +<link rel="help" href="https://github.com/whatwg/html/pull/4181"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<p>Click these buttons in sequence:</p> + +<button id="button1">Click me 1</button> + +<button id="button2">Click me 2</button> + +<p>The result will be pass/fail per the testharness.js results</p> + +<!-- We set the attributes from a separate script to specifically make + sure that it's not that script's base URL that gets used, but instead this page's. --> +<script src="scripts/no-active-script.js"></script> + +<script> +"use strict"; +setup({ explicit_timeout: true }); + +promise_test(t => { + t.add_cleanup(() => { + delete window.evaluated_imports_a; + }); + + const promise = new Promise((resolve, reject) => { + window.continueTest1 = resolve; + window.errorTest1 = reject; + }); + + return promise.then(module => { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); +}, "onclick that directly imports should successfully import, using page's base URL"); + +promise_test(t => { + t.add_cleanup(() => { + delete window.evaluated_imports_a; + }); + + const promise = new Promise((resolve, reject) => { + window.continueTest2 = resolve; + window.errorTest2 = reject; + }); + + return promise.then(module => { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); +}, "onclick that indirectly imports after a task should successfully import, using page's base URL"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/no-active-script-module-manual.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/no-active-script-module-manual.html new file mode 100644 index 0000000000..359b71d821 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/no-active-script-module-manual.html @@ -0,0 +1,55 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Dynamic import when there is no active script</title> +<link rel="help" href="https://github.com/whatwg/html/pull/4181"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<p>Click these buttons in sequence:</p> + +<button id="button1">Click me 1</button> + +<button id="button2">Click me 2</button> + +<p>The result will be pass/fail per the testharness.js results</p> + +<!-- We set the attributes from a separate script to specifically make + sure that it's not that script's base URL that gets used, but instead this page's. --> +<script src="scripts/no-active-script.js" type="module"></script> + +<script type="module"> +"use strict"; +setup({ explicit_timeout: true }); + +promise_test(t => { + t.add_cleanup(() => { + delete window.evaluated_imports_a; + }); + + const promise = new Promise((resolve, reject) => { + window.continueTest1 = resolve; + window.errorTest1 = reject; + }); + + return promise.then(module => { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); +}, "onclick that directly imports should successfully import, using page's base URL"); + +promise_test(t => { + t.add_cleanup(() => { + delete window.evaluated_imports_a; + }); + + const promise = new Promise((resolve, reject) => { + window.continueTest2 = resolve; + window.errorTest2 = reject; + }); + + return promise.then(module => { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); +}, "onclick that indirectly imports after a task should successfully import, using page's base URL"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-classic.html new file mode 100644 index 0000000000..0958cfbeba --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-classic.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<meta http-equiv="content-security-policy" content="script-src 'nonce-correct'"> +<script nonce="correct" src="/resources/testharness.js"></script> +<script nonce="correct" src="/resources/testharnessreport.js"></script> +<script nonce="correct" src="./propagate-nonce-external.js"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-module.html new file mode 100644 index 0000000000..47c422e59c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external-module.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<meta http-equiv="content-security-policy" content="script-src 'nonce-correct'"> +<script nonce="correct" src="/resources/testharness.js"></script> +<script nonce="correct" src="/resources/testharnessreport.js"></script> +<script type="module" nonce="correct" src="./propagate-nonce-external.js"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external.js new file mode 100644 index 0000000000..3b97d2f40e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-external.js @@ -0,0 +1,7 @@ +// This file is loaded both as a module and as a classic script. +promise_test(t => { + return import("../imports-a.js").then(module => { + assert_true(window.evaluated_imports_a); + assert_equals(module.A["from"], "imports-a.js"); + }); +}, "Dynamically imported module should eval when imported from script w/ a valid nonce."); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-classic.html new file mode 100644 index 0000000000..754110cb5e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-classic.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<meta http-equiv="content-security-policy" content="script-src 'nonce-correct'"> +<script nonce="correct" src="/resources/testharness.js"></script> +<script nonce="correct" src="/resources/testharnessreport.js"></script> +<script nonce="correct"> +promise_test(t => { + return import("./../imports-a.js").then(module => { + assert_true(window.evaluated_imports_a); + assert_equals(module.A["from"], "imports-a.js"); + }); +}, "Dynamically imported module should eval when imported from script w/ a valid nonce."); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-module.html new file mode 100644 index 0000000000..f3322773a4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/propagate-nonce-inline-module.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<meta http-equiv="content-security-policy" content="script-src 'nonce-correct'"> +<script nonce="correct" src="/resources/testharness.js"></script> +<script nonce="correct" src="/resources/testharnessreport.js"></script> +<script type="module" nonce="correct"> +promise_test(t => { + return import("./../imports-a.js").then(module => { + assert_true(window.evaluated_imports_a); + assert_equals(module.A["from"], "imports-a.js"); + }); +}, "Dynamically imported module should eval when imported from script w/ a valid nonce."); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/blob-url-worker.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/blob-url-worker.js new file mode 100644 index 0000000000..07071e05ce --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/blob-url-worker.js @@ -0,0 +1,11 @@ +self.addEventListener("message", (evt) => { + const importModule = import(evt.data); + importModule.then( + (module) => { + self.postMessage({ importSucceeded: true, module: { ...module } }); + }, + (error) => { + self.postMessage({ importSucceeded: false, errorName: error.name }); + } + ); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/code-cache-nonce-iframe.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/code-cache-nonce-iframe.sub.html new file mode 100644 index 0000000000..56f915aac1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/code-cache-nonce-iframe.sub.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<meta http-equiv="content-security-policy" + content="script-src 'unsafe-eval' 'nonce-{{GET[nonce]}}'"> +<script src="code-cache-nonce.js" nonce="{{GET[nonce]}}"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/code-cache-nonce.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/code-cache-nonce.js new file mode 100644 index 0000000000..e9983fb6cd --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/code-cache-nonce.js @@ -0,0 +1,4 @@ +// Note that the function source text is intentionally different from e.g. +// ../alpha/code-cache.js to avoid caching Functions between different sets +// of tests. +parent.promise = (new Function('x', 'return import(x)'))('../../imports-a.js'); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/empty-iframe.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/empty-iframe.html new file mode 100644 index 0000000000..ad5ab30eda --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/empty-iframe.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + </head> + <body> + <div id="dummy"></div> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/status-changing-script.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/status-changing-script.py new file mode 100644 index 0000000000..a44d3dd3eb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/status-changing-script.py @@ -0,0 +1,18 @@ +def main(request, response): + headers = [(b"Content-Type", b"text/javascript"), + (b"Cache-Control", b"private, no-store")] + + id = request.GET.first(b"id") + + with request.server.stash.lock: + status = request.server.stash.take(id) + if status is None: + status = 200 + + new_status = request.GET.first(b"newStatus", None) + if new_status is not None: + status = int(new_status) + + request.server.stash.put(id, status) + + return status, headers, b"" diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/v8-code-cache-iframe.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/v8-code-cache-iframe.sub.html new file mode 100644 index 0000000000..c3a870b3f1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/v8-code-cache-iframe.sub.html @@ -0,0 +1,9 @@ +<!DOCTYPE html> +<meta http-equiv="content-security-policy" + content="script-src 'nonce-{{GET[nonce]}}'"> +<!-- +base element to make the base URLs of the Document and the script different +--> +<base href="../"> +<script src="resources/v8-code-cache.js?pipe=header(Cache-Control,max-age=1000)" + nonce="{{GET[nonce]}}" type="{{GET[type]}}"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/v8-code-cache.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/v8-code-cache.js new file mode 100644 index 0000000000..1d3e88a51d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/resources/v8-code-cache.js @@ -0,0 +1,74 @@ +parent.promise = import('../../imports-a.js'); + +// Padding for triggering V8 Code Cache on Chromium. +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ +// ============================================================================ diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/Function.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/Function.js new file mode 100644 index 0000000000..447e5060b1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/Function.js @@ -0,0 +1,2 @@ +// import()s in a dynamically created function are resolved relative to the script. +Function(`import('../../imports-a.js?label=' + window.label).then(window.continueTest, window.errorTest)`)(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/eval.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/eval.js new file mode 100644 index 0000000000..100602733a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/eval.js @@ -0,0 +1,2 @@ +// import()s in eval are resolved relative to the script. +eval(`import('../../imports-a.js?label=' + window.label).then(window.continueTest, window.errorTest)`); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/inline-event-handlers-UA-code.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/inline-event-handlers-UA-code.js new file mode 100644 index 0000000000..3202ce47b9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/inline-event-handlers-UA-code.js @@ -0,0 +1,3 @@ +// import()s in an event handler are resolved relative to the document base. +window.dummyDiv.setAttribute("onclick", `import('./imports-a.js?label=' + window.label).then(window.continueTest, window.errorTest)`); +window.dummyDiv.click(); // different from **on**click() diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/no-active-script.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/no-active-script.js new file mode 100644 index 0000000000..85d8ac29ec --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/no-active-script.js @@ -0,0 +1,5 @@ +"use strict"; + +document.querySelector("#button1").setAttribute("onclick", "import('../imports-a.js?label=button1').then(window.continueTest1, window.errorTest1)"); + +document.querySelector("#button2").setAttribute("onclick", "Promise.resolve(`import('../imports-a.js?label=button2')`).then(eval).then(window.continueTest2, window.errorTest2);"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/reflected-inline-event-handlers.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/reflected-inline-event-handlers.js new file mode 100644 index 0000000000..923eb7d8b6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/reflected-inline-event-handlers.js @@ -0,0 +1,3 @@ +// import()s in an event handler are resolved relative to the document base. +window.dummyDiv.setAttribute("onclick", `import('./imports-a.js?label=' + window.label).then(window.continueTest, window.errorTest)`); +window.dummyDiv.onclick(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/setTimeout.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/setTimeout.js new file mode 100644 index 0000000000..342b342e8e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/scripts/setTimeout.js @@ -0,0 +1,2 @@ +// import()s in a timeout handler are resolved relative to the script. +setTimeout(`import('../../imports-a.js?label=' + window.label).then(window.continueTest, window.errorTest)`, 0); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html new file mode 100644 index 0000000000..855705e585 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-classic.html @@ -0,0 +1,63 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>import() inside compiled strings uses the script base URL inside a classic script that is loaded from a file</title> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id="dummy"></div> + +<base href="scripts/foo/"> +<script> +// Tweak the base URL of the document here to distinguish: +// - document URL +// - document base URL = ../ +// - External scripts' base URL = ./scripts/eval.js etc. +// - This inline script's base URL = ./scripts/foo/ +document.querySelector("base").remove(); +const base = document.createElement("base"); +base.setAttribute("href", "../"); +document.body.appendChild(base); + +function load(scriptSrc) { + const el = document.createElement("script"); + el.src = scriptSrc; + document.body.appendChild(el); +} + +function createTestPromise() { + return new Promise((resolve, reject) => { + window.dummyDiv.removeAttribute("onclick"); + delete window.evaluated_imports_a; + delete window.label; + + window.continueTest = resolve; + window.errorTest = reject; + }); +} + +window.dummyDiv = document.querySelector("#dummy"); + +const evaluators = [ + "setTimeout", + "eval", + "Function", + "reflected-inline-event-handlers", + "inline-event-handlers-UA-code" +]; + +for (const label of evaluators) { + promise_test(() => { + const promise = createTestPromise(); + + window.label = label; + load(`dynamic-import/scripts/${label}.js`); + + return promise.then(module => { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); + }, label + " should successfully import"); +}; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html new file mode 100644 index 0000000000..d90af9c96a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-external-module.html @@ -0,0 +1,64 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>import() inside compiled strings uses the script base URL inside a module script that is loaded from a file</title> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id="dummy"></div> + +<base href="scripts/foo/"> +<script type="module"> +// Tweak the base URL of the document here to distinguish: +// - document URL +// - document base URL = ../ +// - External scripts' base URL = ./scripts/eval.js etc. +// - This inline script's base URL = ./scripts/foo/ +document.querySelector("base").remove(); +const base = document.createElement("base"); +base.setAttribute("href", "../"); +document.body.appendChild(base); + +function load(scriptSrc) { + const el = document.createElement("script"); + el.type = "module"; + el.src = scriptSrc; + document.body.appendChild(el); +} + +function createTestPromise() { + return new Promise((resolve, reject) => { + window.dummyDiv.removeAttribute("onclick"); + delete window.evaluated_imports_a; + delete window.label; + + window.continueTest = resolve; + window.errorTest = reject; + }); +} + +window.dummyDiv = document.querySelector("#dummy"); + +const evaluators = [ + "setTimeout", + "eval", + "Function", + "reflected-inline-event-handlers", + "inline-event-handlers-UA-code" +]; + +for (const label of evaluators) { + promise_test(() => { + const promise = createTestPromise(); + + window.label = label; + load(`dynamic-import/scripts/${label}.js`); + + return promise.then(module => { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); + }, label + " should successfully import"); +}; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html new file mode 100644 index 0000000000..2fe1f75535 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-classic.html @@ -0,0 +1,73 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>import() inside compiled strings uses the script base URL (= document base URL) inside an inline classic script</title> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<div id="dummy"></div> + +<base href="scripts/foo/"> +<script> +// Tweak the base URL of the document here to distinguish: +// - document URL +// - document base URL = ../ +// - This inline script's base URL = ./scripts/foo/ +document.querySelector("base").remove(); +const base = document.createElement("base"); +base.setAttribute("href", "../"); +document.body.appendChild(base); + +function createTestPromise() { + return new Promise((resolve, reject) => { + window.continueTest = resolve; + window.errorTest = reject; + }); +} + +const dummyDiv = document.querySelector("#dummy"); + +function doTest(label, evaluator, path) { + promise_test(t => { + t.add_cleanup(() => { + dummyDiv.removeAttribute("onclick"); + delete window.evaluated_imports_a; + }); + + const promise = createTestPromise(); + + evaluator(`import('${path}/imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`); + + return promise.then(module => { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); + }, label + " should successfully import"); +} + +// Inline script's base URL should be used. +doTest("setTimeout", setTimeout, "../../.."); +doTest("eval", eval, "../../.."); +doTest("the Function constructor", + (x) => { + Function(x)(); + }, + "../../.."); + +// Document's base URL should be used, as there are no active scripts. +doTest("reflected inline event handlers", + (x) => { + dummyDiv.setAttribute("onclick", x); + dummyDiv.onclick(); + }, + "."); + +doTest("inline event handlers triggered via UA code", + (x) => { + dummyDiv.setAttribute("onclick", x); + dummyDiv.click(); // different from .**on**click() + }, + "."); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html new file mode 100644 index 0000000000..1691550ecb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-base-url-inline-module.html @@ -0,0 +1,73 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>import() inside compiled strings uses the script base URL (= document base URL) inside an inline module script</title> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<div id="dummy"></div> + +<base href="scripts/foo/"> +<script type="module"> +// Tweak the base URL of the document here to distinguish: +// - document URL +// - document base URL = ../ +// - This inline script's base URL = ./scripts/foo/ +document.querySelector("base").remove(); +const base = document.createElement("base"); +base.setAttribute("href", "../"); +document.body.appendChild(base); + +function createTestPromise() { + return new Promise((resolve, reject) => { + window.continueTest = resolve; + window.errorTest = reject; + }); +} + +const dummyDiv = document.querySelector("#dummy"); + +function doTest(label, evaluator, path) { + promise_test(t => { + t.add_cleanup(() => { + dummyDiv.removeAttribute("onclick"); + delete window.evaluated_imports_a; + }); + + const promise = createTestPromise(); + + evaluator(`import('${path}/imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`); + + return promise.then(module => { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); + }, label + " should successfully import"); +} + +// Inline script's base URL should be used. +doTest("setTimeout", setTimeout, "../../.."); +doTest("eval", eval, "../../.."); +doTest("the Function constructor", + (x) => { + Function(x)(); + }, + "../../.."); + +// Document's base URL should be used, as there are no active scripts. +doTest("reflected inline event handlers", + (x) => { + dummyDiv.setAttribute("onclick", x); + dummyDiv.onclick(); + }, + "."); + +doTest("inline event handlers triggered via UA code", + (x) => { + dummyDiv.setAttribute("onclick", x); + dummyDiv.click(); // different from .**on**click() + }, + "."); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-classic.html new file mode 100644 index 0000000000..34ea00abc8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-classic.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>import() inside compiled strings inside a classic script</title> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id="dummy"></div> + +<script> +function createTestPromise() { + return new Promise((resolve, reject) => { + window.continueTest = resolve; + window.errorTest = reject; + }); +} + +const dummyDiv = document.querySelector("#dummy"); + +const evaluators = { + eval, + setTimeout, + "the Function constructor"(x) { + Function(x)(); + }, + "reflected inline event handlers"(x) { + dummyDiv.setAttribute("onclick", x); + dummyDiv.onclick(); + }, + "inline event handlers triggered via UA code"(x) { + dummyDiv.setAttribute("onclick", x); + dummyDiv.click(); // different from .**on**click() + } +}; + +for (const [label, evaluator] of Object.entries(evaluators)) { + promise_test(t => { + t.add_cleanup(() => { + dummyDiv.removeAttribute("onclick"); + delete window.evaluated_imports_a; + }); + + const promise = createTestPromise(); + + evaluator(`import('../imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`); + + return promise.then(module => { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); + }, label + " should successfully import"); +}; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-module.html new file mode 100644 index 0000000000..b85d446d8d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-module.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>import() inside compiled strings inside a module script</title> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id="dummy"></div> + +<script type="module"> +function createTestPromise() { + return new Promise((resolve, reject) => { + window.continueTest = resolve; + window.errorTest = reject; + }); +} + +const dummyDiv = document.querySelector("#dummy"); + +const evaluators = { + eval, + setTimeout, + "the Function constructor"(x) { + Function(x)(); + }, + "reflected inline event handlers"(x) { + dummyDiv.setAttribute("onclick", x); + dummyDiv.onclick(); + }, + "inline event handlers triggered via UA code"(x) { + dummyDiv.setAttribute("onclick", x); + dummyDiv.click(); // different from .**on**click() + } +}; + +for (const [label, evaluator] of Object.entries(evaluators)) { + promise_test(t => { + t.add_cleanup(() => { + dummyDiv.removeAttribute("onclick"); + delete window.evaluated_imports_a; + }); + + const promise = createTestPromise(); + + evaluator(`import('../imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`); + + return promise.then(module => { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); + }, label + " should successfully import"); +}; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html new file mode 100644 index 0000000000..b582eba8b0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-classic.html @@ -0,0 +1,104 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>import() inside compiled strings uses the appropriate nonce inside a classic script</title> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<meta http-equiv="content-security-policy" content="script-src 'nonce-correct' 'unsafe-eval' 'unsafe-hashes' 'sha256-cAMzxBL19bKt4KwKGbxy/ZOFIIjH5AmRjlVbsD5pvNw=' 'sha256-3VjoJYNK/9HJMS8rrZHlqSZgUssDY+GPyc7AU8lNM3k='"> + +<script nonce="correct" src="/resources/testharness.js"></script> +<script nonce="correct" src="/resources/testharnessreport.js"></script> + +<div id="dummy"></div> + +<script nonce="correct"> +"use strict"; +const dummyDiv = document.querySelector("#dummy"); + +function createTestPromise(t) { + t.add_cleanup(() => { + delete window.evaluated_imports_a; + delete window.unreached; + delete window.continueTest; + delete window.errorTest; + }); + + return new Promise((resolve, reject) => { + window.unreached = t.unreached_func("Must not reach this"); + window.continueTest = resolve; + window.errorTest = reject; + }); +} + +function assertSuccessful(module) { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); +} + +promise_test(t => { + const promise = createTestPromise(t); + + setTimeout(`import('../imports-a.js?label=setTimeout').then(window.continueTest, window.errorTest)`, 0); + + return promise.then(assertSuccessful); +}, "setTimeout must inherit the nonce from the triggering script, thus execute"); + +promise_test(t => { + const promise = createTestPromise(t); + + eval(`import('../imports-a.js?label=direct eval').then(window.continueTest, window.errorTest)`); + + return promise.then(assertSuccessful); +}, "direct eval must inherit the nonce from the triggering script, thus execute"); + +promise_test(t => { + const promise = createTestPromise(t); + + const evalAlias = eval; + evalAlias(`import('../imports-a.js?label=indirect eval').then(window.continueTest, window.errorTest)`); + + return promise.then(assertSuccessful); +}, "indirect eval must inherit the nonce from the triggering script, thus execute"); + +promise_test(t => { + const promise = createTestPromise(t); + + Function(`import('../imports-a.js?label=the Function constructor').then(window.continueTest, window.errorTest)`)(); + + return promise.then(assertSuccessful); +}, "the Function constructor must inherit the nonce from the triggering script, thus execute"); + +promise_test(t => { + t.add_cleanup(() => { + dummyDiv.removeAttribute("onclick"); + }); + + const promise = createTestPromise(t); + + // This only works because of the 'unsafe-hashes' and the hash in the CSP policy + dummyDiv.setAttribute( + "onclick", + `import('../imports-a.js?label=reflected inline event handlers').then(window.continueTest, window.errorTest)` + ); + dummyDiv.onclick(); + + return promise_rejects_js(t, TypeError, promise); +}, "reflected inline event handlers must not inherit the nonce from the triggering script, thus fail"); + +promise_test(t => { + t.add_cleanup(() => { + dummyDiv.removeAttribute("onclick"); + }); + + const promise = createTestPromise(t); + + // This only works because of the 'unsafe-hashes' and the hash in the CSP policy + dummyDiv.setAttribute( + "onclick", + `import('../imports-a.js?label=inline event handlers triggered via UA code').then(window.continueTest, window.errorTest)` + ); + assert_equals(typeof dummyDiv.onclick, "function", "the browser must be able to parse a string containing the import() syntax into a function"); + dummyDiv.click(); // different from **on**click() + + return promise_rejects_js(t, TypeError, promise); +}, "inline event handlers triggered via UA code must not inherit the nonce from the triggering script, thus fail"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html new file mode 100644 index 0000000000..4fa1cc5877 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-nonce-module.html @@ -0,0 +1,103 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>import() inside compiled strings uses the appropriate nonce inside a module script</title> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<meta http-equiv="content-security-policy" content="script-src 'nonce-correct' 'unsafe-eval' 'unsafe-hashes' 'sha256-cAMzxBL19bKt4KwKGbxy/ZOFIIjH5AmRjlVbsD5pvNw=' 'sha256-3VjoJYNK/9HJMS8rrZHlqSZgUssDY+GPyc7AU8lNM3k='"> + +<script nonce="correct" src="/resources/testharness.js"></script> +<script nonce="correct" src="/resources/testharnessreport.js"></script> + +<div id="dummy"></div> + +<script type="module" nonce="correct"> +const dummyDiv = document.querySelector("#dummy"); + +function createTestPromise(t) { + t.add_cleanup(() => { + delete window.evaluated_imports_a; + delete window.unreached; + delete window.continueTest; + delete window.errorTest; + }); + + return new Promise((resolve, reject) => { + window.unreached = t.unreached_func("Must not reach this"); + window.continueTest = resolve; + window.errorTest = reject; + }); +} + +function assertSuccessful(module) { + assert_true(window.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); +} + +promise_test(t => { + const promise = createTestPromise(t); + + setTimeout(`import('../imports-a.js?label=setTimeout').then(window.continueTest, window.errorTest)`, 0); + + return promise.then(assertSuccessful); +}, "setTimeout must inherit the nonce from the triggering script, thus execute"); + +promise_test(t => { + const promise = createTestPromise(t); + + eval(`import('../imports-a.js?label=direct eval').then(window.continueTest, window.errorTest)`); + + return promise.then(assertSuccessful); +}, "direct eval must inherit the nonce from the triggering script, thus execute"); + +promise_test(t => { + const promise = createTestPromise(t); + + const evalAlias = eval; + evalAlias(`import('../imports-a.js?label=indirect eval').then(window.continueTest, window.errorTest)`); + + return promise.then(assertSuccessful); +}, "indirect eval must inherit the nonce from the triggering script, thus execute"); + +promise_test(t => { + const promise = createTestPromise(t); + + Function(`import('../imports-a.js?label=the Function constructor').then(window.continueTest, window.errorTest)`)(); + + return promise.then(assertSuccessful); +}, "the Function constructor must inherit the nonce from the triggering script, thus execute"); + +promise_test(t => { + t.add_cleanup(() => { + dummyDiv.removeAttribute("onclick"); + }); + + const promise = createTestPromise(t); + + // This only works because of the 'unsafe-hashes' and the hash in the CSP policy + dummyDiv.setAttribute( + "onclick", + `import('../imports-a.js?label=reflected inline event handlers').then(window.continueTest, window.errorTest)` + ); + dummyDiv.onclick(); + + return promise_rejects_js(t, TypeError, promise); +}, "reflected inline event handlers must not inherit the nonce from the triggering script, thus fail"); + +promise_test(t => { + t.add_cleanup(() => { + dummyDiv.removeAttribute("onclick"); + }); + + const promise = createTestPromise(t); + + // This only works because of the 'unsafe-hashes' and the hash in the CSP policy + dummyDiv.setAttribute( + "onclick", + `import('../imports-a.js?label=inline event handlers triggered via UA code').then(window.continueTest, window.errorTest)` + ); + assert_equals(typeof dummyDiv.onclick, 'function', "the browser must be able to parse a string containing the import() syntax into a function"); + dummyDiv.click(); // different from **on**click() + + return promise_rejects_js(t, TypeError, promise); +}, "inline event handlers triggered via UA code must not inherit the nonce from the triggering script, thus fail"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-of-promise-result.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-of-promise-result.html new file mode 100644 index 0000000000..5514049c78 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-of-promise-result.html @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>import() inside compiled strings inside a classic script</title> +<link rel="help" href="https://github.com/whatwg/html/pull/3163"> +<link rel="help" href="https://github.com/tc39/ecma262/issues/871#issuecomment-292493142"> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<base href="scripts/foo/"> +<script> +"use strict"; + +// This test is based on the current specification, but all browser +// implementations aren't conformant. See +// https://bugs.chromium.org/p/chromium/issues/detail?id=1245063 +// https://github.com/heycam/webidl/pull/902 + +// Tweak the base URL of the document here to distinguish: +// - document URL +// - document base URL = ../ +// - This inline script's base URL = ./scripts/foo/ +document.querySelector("base").remove(); +const base = document.createElement("base"); +base.setAttribute("href", "../"); +document.body.appendChild(base); + +self.ran = false; + +// The active script for the dynamic import is this inline script +// (see https://html.spec.whatwg.org/C/#hostmakejobcallback). +promise_test(t => { + t.add_cleanup(() => { + self.ran = false; + }) + + return Promise.resolve(`import("../../../imports-a.js?1").then(() => { self.ran = true; })`) + .then(eval) + .then(() => { + assert_true(self.ran); + }); +}, "Evaled the script via eval, successful import"); + +promise_test(t => { + t.add_cleanup(() => { + self.ran = false; + }) + + return Promise.resolve(`import("bad-specifier?1").catch(() => { self.ran = true; })`) + .then(eval) + .then(() => { + assert_true(self.ran); + }); +}, "Evaled the script via eval, failed import"); + +promise_test(t => { + t.add_cleanup(() => { + self.ran = false; + }) + + return Promise.resolve(`return import("../../../imports-a.js?2").then(() => { self.ran = true; })`) + .then(Function) + .then(Function.prototype.call.bind(Function.prototype.call)) + .then(() => { + assert_true(self.ran); + }); +}, "Evaled the script via Function, successful import"); + +promise_test(t => { + t.add_cleanup(() => { + self.ran = false; + }) + + return Promise.resolve(`return import("bad-specifier?2").catch(() => { self.ran = true; })`) + .then(Function) + .then(Function.prototype.call.bind(Function.prototype.call)) + .then(() => { + assert_true(self.ran); + }); +}, "Evaled the script via Function, failed import"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document.html new file mode 100644 index 0000000000..3b1d98f6b1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-other-document.html @@ -0,0 +1,79 @@ +<!doctype html> +<meta charset=utf-8> +<title>Check import() works when active script is in another document</title> +<link rel="author" title="Jon Coppeard" href="mailto:jcoppeard@mozilla.com"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> + +<iframe id="frame" src="resources/empty-iframe.html"></iframe> + +<script> + +function startTest() { + const otherWindow = document.getElementById("frame").contentWindow; + const otherDiv = otherWindow.document.getElementById("dummy"); + + function createTestPromise() { + return new Promise((resolve, reject) => { + otherWindow.continueTest = resolve; + otherWindow.errorTest = reject; + }); + } + + const evaluators = { + eval: otherWindow.eval, + setTimeout: otherWindow.setTimeout, + "the Function constructor"(x) { + otherWindow.Function(x)(); + }, + }; + + for (const [label, evaluator] of Object.entries(evaluators)) { + promise_test(t => { + t.add_cleanup(() => { + otherDiv.removeAttribute("onclick"); + delete otherWindow.evaluated_imports_a; + }); + + const promise = createTestPromise(); + + evaluator(`import('../imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`); + + return promise.then(module => { + assert_true(otherWindow.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); + }, label + " should successfully import"); + }; + + const eventHandlerEvaluators = { + "reflected inline event handlers"(x) { + otherDiv.setAttribute("onclick", x); + otherDiv.onclick(); + }, + "inline event handlers triggered by JS"(x) { + otherDiv.setAttribute("onclick", x); + otherDiv.click(); // different from .**on**click() + } + }; + + for (const [label, evaluator] of Object.entries(eventHandlerEvaluators)) { + promise_test(t => { + t.add_cleanup(() => { + otherDiv.removeAttribute("onclick"); + delete otherWindow.evaluated_imports_a; + }); + + const promise = createTestPromise(); + + evaluator(`import('../../imports-a.js?label=${label}').then(window.continueTest, window.errorTest);`); + + return promise.then(module => { + assert_true(otherWindow.evaluated_imports_a, "The module must have been evaluated"); + assert_equals(module.A.from, "imports-a.js", "The module namespace object must be correct"); + }); + }, label + " should successfully import"); + }; +} +</script> +<body onLoad="startTest()"></body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache.html new file mode 100644 index 0000000000..77de19e74b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<script> +// Regression test for https://crbug.com/1244145: +// This test loads a same script file (`resources/v8-code-cache.js`) +// multiple times to trigger V8 Code Cache. +// Host defined options (including base URLs and nonces) are lost when the +// script is compiled using the cached metadata, and thus causing +// dynamic import failures due to wrong base URLs and wrong nonces. + +function runTest(type, nonce, description) { + promise_test(t => { + return new Promise((resolve, reject) => { + const iframe = document.createElement('iframe'); + iframe.src = 'resources/v8-code-cache-iframe.sub.html?nonce=' + nonce + '&type=' + type; + iframe.onload = () => { + // `window.promise` is set by `resources/v8-code-cache.js`. + window.promise.then(resolve, reject); + }; + document.body.appendChild(iframe); + t.add_cleanup(() => iframe.remove()); + }); + }, type + ': ' + description); +} + +// As `promise_test` are serialized, each iframe is created after previous +// iframes and scripts are completely loaded. +for (const type of ['text/javascript', 'module']) { + // Cache the script in V8 Code Cache by running multiple times. + runTest(type, 'abc', 'Run #1'); + runTest(type, 'abc', 'Run #2'); + runTest(type, 'abc', 'Run #3'); + runTest(type, 'abc', 'Run #4'); + // Changing the nonce seems to disable compilation cache, trigger compilation + // using V8 Code Cache and thus expose the bug. + runTest(type, 'def', 'Run #5'); +} +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-and-slow-dependency.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-and-slow-dependency.html new file mode 100644 index 0000000000..f336276f3f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-and-slow-dependency.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<title>Module importing syntax error script and slow script should not crash UA</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="module"> +setup({allow_uncaught_exception: true}); +window.log = []; +window.loaded = false; +</script> +<script type="module"> +import "./syntaxerror.js"; +import "./resources/delayed-modulescript.py"; + +window.loaded = true; +</script> +<script type="module"> +test(() => { + assert_false(loaded); + }, "module graph with a syntax error should not evaulate but should not crash UA."); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html new file mode 100644 index 0000000000..2480a60d6d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title>Handling of different types of errors</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + window.addEventListener("onunhandledrejection", unreachable); + + const test_load = async_test( + "network error has higher priority than parse error"); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 3); + + // A parse error is reported for the first top-level + // <script> element for syntaxerror.js. + assert_equals(log[0].constructor, SyntaxError); + assert_equals(log[1], 1); + + // onerror is called (with no errors reported) due to a network error + // for the second top-level <script>. + assert_equals(log[2], 2); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./syntaxerror.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./error-type-1.js" + onerror="log.push(2)" onload="unreachable()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.js new file mode 100644 index 0000000000..4882d3f2a5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-1.js @@ -0,0 +1,2 @@ +import './syntaxerror.js'; +import './404.js'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html new file mode 100644 index 0000000000..673bf28ca2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<title>Handling of different types of errors</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + window.addEventListener("onunhandledrejection", unreachable); + + const test_load = async_test( + "parse error has higher priority than instantiation error"); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 4); + + // An instantiation error is reported for the first top-level + // <script> element for instantiation-error-1.js. + assert_equals(log[0].constructor, SyntaxError); + assert_equals(log[1], 1); + + // A parse error is reported for the second top-level <script>. + assert_equals(log[2].constructor, SyntaxError); + assert_equals(log[3], 2); + assert_not_equals(log[0], log[2]); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./instantiation-error-1.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./error-type-2.js" + onerror="unreachable()" onload="log.push(2)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.js new file mode 100644 index 0000000000..6b11397300 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-2.js @@ -0,0 +1,2 @@ +import './instantiation-error-1.js'; +import './syntaxerror.js'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html new file mode 100644 index 0000000000..8a16266f4c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<title>Handling of different types of errors</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + window.addEventListener("onunhandledrejection", unreachable); + + const test_load = async_test( + "instantiation error has higher priority than evaluation error"); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 5); + + // An evaluation error is reported for the first top-level + // <script> element for throw.js. + assert_equals(log[0], 'throw'); + assert_true(log[1].foo); + assert_equals(log[2], 1); + + // An instantiation error is reported for the second top-level <script>. + assert_equals(log[3].constructor, SyntaxError); + assert_equals(log[4], 2); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./throw.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./error-type-3.js" + onerror="unreachable()" onload="log.push(2)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.js new file mode 100644 index 0000000000..542be52846 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/error-type-3.js @@ -0,0 +1,2 @@ +import './throw.js'; +import './instantiation-error-1.js'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-common.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-common.js new file mode 100644 index 0000000000..4eb5597a58 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-common.js @@ -0,0 +1,10 @@ +function errorHandler(ev) +{ + document._errorReported.push("error"); +} + +document._errorReported = []; +window.addEventListener("error", errorHandler); +window.addEventListener("load", function () { + document._errorReported = document._errorReported.join(","); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependent.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependent.html new file mode 100644 index 0000000000..3a00f62f00 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependent.html @@ -0,0 +1,16 @@ +<!doctype html> +<html> +<head> + <title>html-script-module-errorHandling-parseError-Dependent</title> + <script src="errorhandling-parseerror-common.js"></script> +</head> +<body> + <script type="module" onerror="errorHandler(event);"> + + // No parse errors in the root module, just in the dependent module + import test from "./errorhandling-parseerror-dependent.js"; + document._errorReported = "shouldn't have run dependent module"; + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependent.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependent.js new file mode 100644 index 0000000000..71872c47cf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependent.js @@ -0,0 +1,2 @@ +// Parse error in a dependent module +1A diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependentmultiple.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependentmultiple.html new file mode 100644 index 0000000000..7775aeabb4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependentmultiple.html @@ -0,0 +1,24 @@ +<!doctype html> +<html> +<head> + <title>html-script-module-errorHandling-parseError-DependentMultiple</title> + <script src="errorhandling-parseerror-common.js"></script> +</head> +<body> + <script type="module" onerror="errorHandler(event)"> + + // No parse errors in the root module, just in the dependent module + import test from "./errorhandling-parseerror-dependentmultiple.js"; + document._errorReported = "shouldn't have run dependent module"; + + </script> + <script type="module" onerror="errorHandler(event)"> + + // With the broken dependent module already acquired, try to import it + // again from another root. This root should be unwound appropriately. + import test from "./errorhandling-parseerror-dependentmultiple.js"; + document._errorReported = "really shouldn't have run dependent module"; + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependentmultiple.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependentmultiple.js new file mode 100644 index 0000000000..71872c47cf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-dependentmultiple.js @@ -0,0 +1,2 @@ +// Parse error in a dependent module +1A diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-root.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-root.html new file mode 100644 index 0000000000..012f3e9b8c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-parseerror-root.html @@ -0,0 +1,15 @@ +<!doctype html> +<html> +<head> + <title>html-script-module-errorHandling-parseError-Root</title> + <script src="errorhandling-parseerror-common.js"></script> +</head> +<body> + <script type="module"> + + // Parse error in a root module + 1A + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-wrongMimetype-import.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-wrongMimetype-import.js new file mode 100644 index 0000000000..286e1a4229 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-wrongMimetype-import.js @@ -0,0 +1,8 @@ +import foo from "./errorhandling-wrongMimetype.js?pipe=header(Content-Type,text/plain)"; + +// We don't expect this code to run, the import above should fail! +// If we do run though, don't trigger an error that the testharness +// might misinterpret as the import itself failing to load. + +var A = null; +export { A }; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-wrongMimetype.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-wrongMimetype.js new file mode 100644 index 0000000000..373a532445 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling-wrongMimetype.js @@ -0,0 +1,7 @@ +// This is a plain JavaScript file, but since it will only be accessed with +// a Content-Type of text/plain and nosniff, it will be seen as invalid. +// The file itself will have no errors/effects, so if it does actually run, +// no error will be detected, and the test will fail. + +var foo = null; +export foo;
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling.html new file mode 100644 index 0000000000..cf47465b49 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/errorhandling.html @@ -0,0 +1,60 @@ +<!doctype html> +<html> +<head> + <title>html-script-module-errorHandling</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <style> + + iframe + { display: none; } + + </style> +</head> +<body> + <h1>html-script-module-errorHandling</h1> + <iframe id="iframe_parseError_Root" src="errorhandling-parseerror-root.html"></iframe> + <iframe id="iframe_parseError_Dependent" src="errorhandling-parseerror-dependent.html"></iframe> + <iframe id="iframe_parseError_DependentMultiple" src="errorhandling-parseerror-dependentmultiple.html"></iframe> + <script> + + var tests = [ + { "id": "iframe_parseError_Root", "expected": "error" }, + { "id": "iframe_parseError_Dependent", "expected": "error" }, + { "id": "iframe_parseError_DependentMultiple", "expected": "error,error" }, + ]; + tests.forEach(function (testObj) { + var testHandle = async_test("IFrame test: '" + testObj.id + "'"); + var testTarget = document.getElementById(testObj.id); + testTarget.addEventListener("load", testHandle.step_func(function () { + assert_equals(testTarget.contentDocument._errorReported, testObj.expected, "Unexpected _errorReported value"); + testHandle.done(); + })); + }); + + var test_wrongMimetype_root = async_test("External root module with non-script mimetype"); + var script_wrongMimetype_root = document.createElement("script"); + script_wrongMimetype_root.type = "module"; + script_wrongMimetype_root.src = "errorhandling-wrongMimetype.js?pipe=header(Content-Type,text/plain)"; + script_wrongMimetype_root.addEventListener("error", test_wrongMimetype_root.step_func(function () { + test_wrongMimetype_root.done(); + })); + script_wrongMimetype_root.addEventListener("load", test_wrongMimetype_root.step_func(function () { + assert_unreached("This script should not have loaded!"); + })); + document.body.appendChild(script_wrongMimetype_root); + + var test_wrongMimetype_import = async_test("Module with imported non-script mimetype"); + var script_wrongMimetype_import = document.createElement("script"); + script_wrongMimetype_import.type = "module"; + script_wrongMimetype_import.src = "errorhandling-wrongMimetype-import.js"; + script_wrongMimetype_import.addEventListener("error", test_wrongMimetype_import.step_func(function () { + test_wrongMimetype_import.done(); + })); + script_wrongMimetype_import.addEventListener("load", test_wrongMimetype_import.step_func(function () { + assert_unreached("This script should not have loaded!"); + })); + document.body.appendChild(script_wrongMimetype_import); + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html new file mode 100644 index 0000000000..3f2bb35f4e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-1.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<title>Handling of evaluation errors, 1</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + window.addEventListener("onunhandledrejection", unreachable); + + const test_load = async_test( + "Test that exceptions during evaluation lead to error events on " + + "window, and that exceptions are remembered.\n"); + window.addEventListener("load", test_load.step_func_done(ev => { + const exn = log[1]; + assert_array_equals(log, + ["throw", exn, "load", exn, "load", exn, "load", exn, "load"]); + assert_true(exn.foo); + })); + + function logLoad() { log.push("load") } + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="throw.js" onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="throw.js" onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="throw.js" async onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="throw.js" nomodule onerror="unreachable()" + onload="logLoad()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html new file mode 100644 index 0000000000..4f2b3c5a74 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-2.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<title>Handling of evaluation errors, 2</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + window.addEventListener("onunhandledrejection", unreachable); + + const test_load = async_test( + "Test that ill-founded cyclic dependencies cause ReferenceError " + + "during evaluation, which leads to error events on window, and that " + + "exceptions are remembered.\n"); + window.addEventListener("load", test_load.step_func_done(ev => { + const exn = log[1]; + assert_array_equals(log, + ["cycle-tdz-access-a", exn, "load", exn, "load", exn, "load"]); + assert_equals(exn.constructor, ReferenceError); + })); + + function logLoad() { log.push("load"); } + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="cycle-tdz-access.js" async onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="cycle-tdz-access.js" nomodule onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="cycle-tdz-access.js" onerror="unreachable()" + onload="logLoad()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html new file mode 100644 index 0000000000..9bfb5df2cf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-3.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<title>Handling of evaluation errors, 3</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + window.addEventListener("onunhandledrejection", unreachable); + + const test_load = async_test( + "Test that exceptions during evaluation lead to error events on " + + "window, and that exceptions are remembered.\n"); + window.addEventListener("load", test_load.step_func_done(ev => { + const exn = log[1]; + assert_array_equals(log, + ["throw", exn, "load", exn, "load", exn, "load", exn, "load", + exn, "load"]); + assert_true(exn.foo); + })); + + function logLoad() { log.push("load"); } + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./throw.js" onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="./throw.js" onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="./throw-nested.js" onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="./throw.js" onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="./throw-nested.js" onerror="unreachable()" + onload="logLoad()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html new file mode 100644 index 0000000000..0b4b7d1662 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/evaluation-error-4.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<title>Handling of evaluation errors, 4</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + window.addEventListener("onunhandledrejection", unreachable); + + const test_load = async_test( + "Test that exceptions during evaluation lead to error events on " + + "window, and that exceptions are remembered.\n"); + window.addEventListener("load", test_load.step_func_done(ev => { + const exn = log[1]; + assert_array_equals(log, + ["throw", exn, "load", exn, "load", exn, "load", exn, "load", + exn, "load"]); + assert_true(exn.foo); + })); + + function logLoad() { log.push("load"); } + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./throw-nested.js" onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="./throw-nested.js" onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="./throw.js" onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="./throw-nested.js" onerror="unreachable()" + onload="logLoad()"></script> +<script type="module" src="./throw.js" onerror="unreachable()" + onload="logLoad()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicordered2.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicordered2.js new file mode 100644 index 0000000000..d7115a2ac6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicordered2.js @@ -0,0 +1,3 @@ +test_dynamicOrdered.step(function() { + assert_execCount(1, 2, "External script element (#1) should have fired second"); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicordered3.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicordered3.js new file mode 100644 index 0000000000..c04e101bb8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicordered3.js @@ -0,0 +1,3 @@ +test_dynamicOrdered.step(function() { + assert_execCount(1, 3, "External script element (#2) should have fired third"); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicordered4.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicordered4.js new file mode 100644 index 0000000000..958736a3d8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicordered4.js @@ -0,0 +1,3 @@ +test_dynamicOrdered.step(function() { + assert_execCount(1, 4, "External script element (#3) should have fired fourth"); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicunordered1.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicunordered1.js new file mode 100644 index 0000000000..a54cb7a303 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicunordered1.js @@ -0,0 +1,3 @@ +test_dynamicUnordered1.step(function() { + test_dynamicUnordered1.done(); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicunordered2.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicunordered2.js new file mode 100644 index 0000000000..df0cd85421 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-dynamicunordered2.js @@ -0,0 +1,3 @@ +test_dynamicUnordered2.step(function() { + test_dynamicUnordered2.done(); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedordered2.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedordered2.js new file mode 100644 index 0000000000..fca73bd9db --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedordered2.js @@ -0,0 +1,3 @@ +test_parsedOrdered.step(function() { + assert_execCount(0, 2, "External deferred (#1) script element should have fired second"); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedordered4.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedordered4.js new file mode 100644 index 0000000000..6435333bb9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedordered4.js @@ -0,0 +1,3 @@ +test_parsedOrdered.step(function() { + assert_execCount(0, 4, "External deferred (#2) script element should have fired fourth"); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedunordered1.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedunordered1.js new file mode 100644 index 0000000000..ea0bb1b486 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedunordered1.js @@ -0,0 +1,3 @@ +test_parsedUnordered1.step(function() { + test_parsedUnordered1.done(); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedunordered2.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedunordered2.js new file mode 100644 index 0000000000..ce219ee0ea --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder-parsedunordered2.js @@ -0,0 +1,3 @@ +test_parsedUnordered2.step(function() { + test_parsedUnordered2.done(); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder.html new file mode 100644 index 0000000000..6a7513dc13 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/execorder.html @@ -0,0 +1,106 @@ +<!doctype html> +<html> +<head> + <title>html-script-module-execOrder</title> + <meta name=timeout content=long> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + + var execCounts = [ + 0, // test_parsedOrdered + 0, // test_dynamicOrdered + ]; + function assert_execCount(set, expected, description) + { + if (!execCounts[set]) + { + execCounts[set] = 0; + } + assert_equals(++execCounts[set], expected, description); + } + + function create_script(src, opts) + { + var element = document.createElement("script"); + element.src = src; + element.async = (opts.asyncOrdered ? false : true); + element.type = (opts.module ? "module" : "text/javascript"); + document.body.appendChild(element); + } + + </script> +</head> +<body> + <h1>html-script-module-execOrder</h1> + <script> + + ///// + // Start test_parsedUnordered* + ///// + var test_parsedUnordered1 = async_test("Unordered module script execution (parsed, unordered #1)"); + var test_parsedUnordered2 = async_test("Unordered module script execution (parsed, unordered #2)"); + </script> + <script type="module" src="execorder-parsedunordered1.js"></script> + <script type="module" src="execorder-parsedunordered2.js"></script> + <script> + ///// + // End test_parsedUnordered* + ///// + + ///// + // Start test_dynamicUnordered* + ///// + var test_dynamicUnordered1 = async_test("Unordered module script execution (dynamic, unordered #1)"); + var test_dynamicUnordered2 = async_test("Unordered module script execution (dynamic, unordered #2)"); + create_script("execorder-dynamicunordered1.js", { module: true }); + create_script("execorder-dynamicunordered2.js", { module: true }); + ///// + // End test_dynamicUnordered* + ///// + + ///// + // Begin test_parsedOrdered + ///// + var test_parsedOrdered = async_test("Interlaced module/non-module script execution (parsed, async-ordered)"); + window.addEventListener("load", test_parsedOrdered.step_func(function() { + assert_execCount(0, 5, "onload should have fired fifth"); + test_parsedOrdered.done(); + })); + </script> + <script src="execorder-parsedordered2.js" defer></script> + <script type="module"> + test_parsedOrdered.step(function() { + assert_execCount(0, 3, "Inline module-typed script element should have fired third"); + }); + </script> + <script src="execorder-parsedordered4.js" defer></script> + <script> + test_parsedOrdered.step(function() { + assert_execCount(0, 1, "Inline untyped script element should have fired first"); + }); + ///// + // End test_parsedOrdered + ///// + + ///// + // Start test_dynamicOrdered + ///// + var test_dynamicOrdered = async_test("Interlaced module/non-module script execution (dynamic, async-ordered)"); + window.addEventListener("load", test_dynamicOrdered.step_func(function() { + assert_execCount(1, 5, "onload should have fired fifth (last)"); + test_dynamicOrdered.done(); + })); + create_script("execorder-dynamicordered2.js", { asyncOrdered: true, module: false }); + create_script("execorder-dynamicordered3.js", { asyncOrdered: true, module: true }); + create_script("execorder-dynamicordered4.js", { asyncOrdered: true, module: false }); + test_dynamicOrdered.step(function() { + assert_execCount(1, 1, "Inline untyped script element should have fired first"); + }); + ///// + // End test_dynamicOrdered + ///// + + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/export-default.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/export-default.js new file mode 100644 index 0000000000..283830ab28 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/export-default.js @@ -0,0 +1,2 @@ +log.push("export-default"); +export default "fox"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/export-something-nested.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/export-something-nested.js new file mode 100644 index 0000000000..ca806eb8b1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/export-something-nested.js @@ -0,0 +1,2 @@ +log.push("export-something-nested"); +export * from "./export-something.js"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/export-something.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/export-something.js new file mode 100644 index 0000000000..cf2c3a99fe --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/export-something.js @@ -0,0 +1,3 @@ +log.push("export-something"); +export let foo = 42; +export function set_foo(x) { foo = x }; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/fetch-error-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/fetch-error-1.html new file mode 100644 index 0000000000..170bb665ff --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/fetch-error-1.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Handling of fetch errors, 1</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test that failure to fetch root leads to error event on script."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, ["script"]); + })); +</script> +<script type="module" src="./no-such-file.js" onerror="log.push('script')"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/fetch-error-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/fetch-error-2.html new file mode 100644 index 0000000000..9386ce603a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/fetch-error-2.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Handling of fetch errors, 2</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test that failure to fetch dependency leads to error event on script."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, ["script"]); + })); +</script> +<script type="module" src="./fetch-error-2.js" onerror="log.push('script')"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/fetch-error-2.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/fetch-error-2.js new file mode 100644 index 0000000000..20c0ea6402 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/fetch-error-2.js @@ -0,0 +1,2 @@ +import "./no-such-file.js" +import "./this.js"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-dependent.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-dependent.js new file mode 100644 index 0000000000..cfaeabc47e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-dependent.js @@ -0,0 +1 @@ +export let importMetaOnDependentModule = import.meta; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-object.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-object.any.js new file mode 100644 index 0000000000..494e168102 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-object.any.js @@ -0,0 +1,20 @@ +// META: global=dedicatedworker-module,sharedworker-module,serviceworker-module + +test(() => { + assert_equals(typeof import.meta, "object"); + assert_not_equals(import.meta, null); +}, "import.meta is an object"); + +test(() => { + import.meta.newProperty = 1; + assert_true(Object.isExtensible(import.meta)); +}, "import.meta is extensible"); + +test(() => { + for (const name of Reflect.ownKeys(import.meta)) { + const desc = Object.getOwnPropertyDescriptor(import.meta, name); + assert_equals(desc.writable, true); + assert_equals(desc.enumerable, true); + assert_equals(desc.configurable, true); + } +}, "import.meta's properties are writable, configurable, and enumerable"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-resolve-importmap.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-resolve-importmap.html new file mode 100644 index 0000000000..214b9bb59c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-resolve-importmap.html @@ -0,0 +1,57 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<!-- + More extensive tests of import maps and import.meta.resolve() will be + located in the import maps test suite. This contains some basic tests plus + tests some tricky parts of the import.meta.resolve() algorithm around string + conversion which are only testable with import maps. +--> + +<script type="importmap"> +{ + "imports": { + "bare": "https://example.com/", + "https://example.com/rewrite": "https://example.com/rewritten", + + "1": "https://example.com/PASS-1", + "null": "https://example.com/PASS-null", + "undefined": "https://example.com/PASS-undefined", + "[object Object]": "https://example.com/PASS-object", + + "./start": "./resources/export-1.mjs", + "./resources/export-1.mjs": "./resources/export-2.mjs" + } +} +</script> + +<script type="module"> +test(() => { + assert_equals(import.meta.resolve("bare"), "https://example.com/"); +}, "import.meta.resolve() given an import mapped bare specifier"); + +test(() => { + assert_equals(import.meta.resolve("https://example.com/rewrite"), "https://example.com/rewritten"); +}, "import.meta.resolve() given an import mapped URL-like specifier"); + +test(() => { + assert_equals(import.meta.resolve(), "https://example.com/PASS-undefined", "no-arg case"); + + assert_equals(import.meta.resolve(1), "https://example.com/PASS-1"); + assert_equals(import.meta.resolve(null), "https://example.com/PASS-null"); + assert_equals(import.meta.resolve(undefined), "https://example.com/PASS-undefined"); + + // Only toString() methods are consulted by ToString, not valueOf() ones. + // So this becomes "[object Object]". + assert_equals(import.meta.resolve({ valueOf() { return "./x"; } }), "https://example.com/PASS-object"); +}, "Testing the ToString() step of import.meta.resolve() via import maps"); + +promise_test(async () => { + const one = (await import("./start")).default; + assert_equals(one, 1); + + const two = (await import(import.meta.resolve("./start"))).default; + assert_equals(two, 2); +}, "import(import.meta.resolve(x)) can be different from import(x)"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-resolve-multiple-scripts.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-resolve-multiple-scripts.html new file mode 100644 index 0000000000..d2e0f185e0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-resolve-multiple-scripts.html @@ -0,0 +1,39 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<iframe src="resources/store-import-meta.html"></iframe> + +<script type="module"> +import * as otherImportMeta from "./resources/export-import-meta.mjs"; +setup({ explicit_done: true }); + +window.onload = () => { + test(() => { + assert_not_equals(frames[0].importMetaURL, import.meta.url, + "Precondition check: we've set things up so that the other script has a different import.meta.url"); + + const expected = (new URL("resources/x", location.href)).href; + assert_equals(frames[0].importMetaResolve("./x"), expected); + }, "import.meta.resolve resolves URLs relative to the import.meta.url, not relative to the active script when it is called: another global's inline script"); + + test(() => { + const otherFrameImportMetaResolve = frames[0].importMetaResolve; + + document.querySelector("iframe").remove(); + + const expected = (new URL("resources/x", location.href)).href; + assert_equals(otherFrameImportMetaResolve("./x"), expected); + }, "import.meta.resolve still works if its global has been destroyed (by detaching the iframe)"); + + test(() => { + assert_not_equals(otherImportMeta.url, import.meta.url, + "Precondition check: we've set things up so that the other script has a different import.meta.url"); + + const expected = (new URL("resources/x", location.href)).href; + assert_equals(otherImportMeta.resolve("./x"), expected); + }, "import.meta.resolve resolves URLs relative to the import.meta.url, not relative to the active script when it is called: another module script"); + + done(); +}; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-resolve.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-resolve.any.js new file mode 100644 index 0000000000..5b8a84efaf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-resolve.any.js @@ -0,0 +1,77 @@ +// META: global=dedicatedworker-module,sharedworker-module,serviceworker-module + +import { importMetaOnRootModule, importMetaOnDependentModule } + from "./import-meta-root.js"; + +test(() => { + assert_equals(typeof import.meta.resolve, "function"); + assert_equals(import.meta.resolve.name, "resolve"); + assert_equals(import.meta.resolve.length, 1); + assert_equals(Object.getPrototypeOf(import.meta.resolve), Function.prototype); +}, "import.meta.resolve is a function with the right properties"); + +test(() => { + assert_false(isConstructor(import.meta.resolve)); + + assert_throws_js(TypeError, () => new import.meta.resolve("./x")); +}, "import.meta.resolve is not a constructor"); + +test(() => { + // See also tests in ./import-meta-resolve-importmap.html. + + assert_equals(import.meta.resolve({ toString() { return "./x"; } }), resolveURL("x")); + assert_throws_js(TypeError, () => import.meta.resolve(Symbol("./x")), + "symbol"); + assert_throws_js(TypeError, () => import.meta.resolve(), + "no argument (which is treated like \"undefined\")"); +}, "import.meta.resolve ToString()s its argument"); + +test(() => { + assert_equals(import.meta.resolve("./x"), resolveURL("x"), + "current module import.meta"); + assert_equals(importMetaOnRootModule.resolve("./x"), resolveURL("x"), + "sibling module import.meta"); + assert_equals(importMetaOnDependentModule.resolve("./x"), resolveURL("x"), + "dependency module import.meta"); +}, "Relative URL-like specifier resolution"); + +test(() => { + assert_equals(import.meta.resolve("https://example.com/"), "https://example.com/", + "current module import.meta"); + assert_equals(importMetaOnRootModule.resolve("https://example.com/"), "https://example.com/", + "sibling module import.meta"); + assert_equals(importMetaOnDependentModule.resolve("https://example.com/"), "https://example.com/", + "dependency module import.meta"); +}, "Absolute URL-like specifier resolution"); + +test(() => { + const invalidSpecifiers = [ + "https://eggplant:b/c", + "pumpkins.js", + ".tomato", + "..zuccini.mjs", + ".\\yam.es" + ]; + + for (const specifier of invalidSpecifiers) { + assert_throws_js(TypeError, () => import.meta.resolve(specifier), specifier); + } +}, "Invalid module specifiers"); + +test(() => { + const { resolve } = import.meta; + assert_equals(resolve("https://example.com/"), "https://example.com/", "current module import.meta"); +}, "Works fine with no this value"); + +function resolveURL(urlRelativeToThisTest) { + return (new URL(urlRelativeToThisTest, location.href)).href; +} + +function isConstructor(o) { + try { + new (new Proxy(o, { construct: () => ({}) })); + return true; + } catch { + return false; + } +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-root.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-root.js new file mode 100644 index 0000000000..62ec082a8e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-root.js @@ -0,0 +1,2 @@ +export let importMetaOnRootModule = import.meta; +export { importMetaOnDependentModule } from "./import-meta-dependent.js"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.any.js new file mode 100644 index 0000000000..61d96f35af --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.any.js @@ -0,0 +1,38 @@ +// META: global=dedicatedworker-module,sharedworker-module,serviceworker-module + +import { importMetaOnRootModule, importMetaOnDependentModule } + from "./import-meta-root.js"; + +const base = location.href.slice(0, location.href.lastIndexOf('/')); + +test(() => { + assert_equals(importMetaOnRootModule.url, + base + "/import-meta-root.js"); +}, "import.meta.url in a root external script"); + +test(() => { + assert_equals(importMetaOnDependentModule.url, + base + "/import-meta-dependent.js"); +}, "import.meta.url in a dependent external script"); + + +import { importMetaOnRootModule as hashedImportMetaOnRootModule1, + importMetaOnDependentModule as hashedImportMetaOnDependentModule1 } + from "./import-meta-root.js#1"; + +import { importMetaOnRootModule as hashedImportMetaOnRootModule2, + importMetaOnDependentModule as hashedImportMetaOnDependentModule2 } + from "./import-meta-root.js#2"; + +test(() => { + assert_equals(hashedImportMetaOnRootModule1.url, + base + "/import-meta-root.js#1"); + assert_equals(hashedImportMetaOnRootModule2.url, + base + "/import-meta-root.js#2"); + + // Must not be affected + assert_equals(hashedImportMetaOnDependentModule1.url, + base + "/import-meta-dependent.js"); + assert_equals(hashedImportMetaOnDependentModule2.url, + base + "/import-meta-dependent.js"); +}, "import.meta.url when importing the module with different fragments"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html new file mode 100644 index 0000000000..284a15f2b2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.html @@ -0,0 +1,34 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="module" src="import-meta-url.any.js"></script> + +<script type="module"> +const base = location.href.slice(0, location.href.lastIndexOf('/')); + +test(() => { + assert_equals(import.meta.url, location.href); +}, "import.meta.url in a root inline script"); + +for (const workerType of ['DedicatedWorker', 'SharedWorker']) { + promise_test(async t => { + const worker_request_url = + new URL(`postmessage-worker.js?${workerType}`, location); + let w; + let port; + if (workerType === 'DedicatedWorker') { + w = new Worker(worker_request_url.href, {type: 'module'}); + port = w; + } else { + w = new SharedWorker(worker_request_url.href, {type: 'module'}); + port = w.port; + w.port.start(); + } + w.onerror = t.unreached_func('Worker error'); + const url = await new Promise(resolve => { + port.onmessage = evt => resolve(evt.data); + }); + assert_equals(url, worker_request_url.href); + }, `import.meta.url at top-level module ${workerType}`); +} +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/postmessage-worker.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/postmessage-worker.js new file mode 100644 index 0000000000..3618137aef --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/postmessage-worker.js @@ -0,0 +1,12 @@ +if ('DedicatedWorkerGlobalScope' in self && + self instanceof DedicatedWorkerGlobalScope) { + postMessage(import.meta.url); +} else if ( + 'SharedWorkerGlobalScope' in self && + self instanceof SharedWorkerGlobalScope) { + self.onconnect = function(e) { + const port = e.ports[0]; + port.start(); + port.postMessage(import.meta.url); + }; +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/export-1.mjs b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/export-1.mjs new file mode 100644 index 0000000000..aef22247d7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/export-1.mjs @@ -0,0 +1 @@ +export default 1; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/export-2.mjs b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/export-2.mjs new file mode 100644 index 0000000000..842e368a0a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/export-2.mjs @@ -0,0 +1 @@ +export default 2; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/export-import-meta.mjs b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/export-import-meta.mjs new file mode 100644 index 0000000000..488ca74c93 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/export-import-meta.mjs @@ -0,0 +1,2 @@ +export const url = import.meta.url; +export const resolve = import.meta.resolve; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/store-import-meta.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/store-import-meta.html new file mode 100644 index 0000000000..c9751da408 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-meta/resources/store-import-meta.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<script type="module"> +window.importMetaURL = import.meta.url; +window.importMetaResolve = import.meta.resolve; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-something-namespace.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-something-namespace.js new file mode 100644 index 0000000000..32d90287d7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-something-namespace.js @@ -0,0 +1,5 @@ +log.push("import-something-namespace"); +log.push(m.foo); +m.set_foo(43); +log.push(m.foo); +import * as m from "./export-something.js"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-subgraph-404.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-subgraph-404.html new file mode 100644 index 0000000000..4911a071a0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/import-subgraph-404.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="module"> +import { delayedLoaded } from "./resources/delayed-modulescript.py"; +import { A } from "./404.js"; +window.loadSuccess = delayedLoaded; +</script> +<script type="module"> +test(function () { + assert_equals(window.loadSuccess, undefined, + "module tree w/ its sub graph 404 should fail to load without crashing"); +}, "Import a module graph w/ sub-graph 404."); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-a.js new file mode 100644 index 0000000000..44d1ac96c2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-a.js @@ -0,0 +1,3 @@ +var A = { "from": "imports-a.js" }; +window.evaluated_imports_a = true; +export { A }; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-b.js new file mode 100644 index 0000000000..ae194e4d8a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-b.js @@ -0,0 +1 @@ +export var B = { "from": "imports-b.js" }; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-cycle-a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-cycle-a.js new file mode 100644 index 0000000000..8bd8526f76 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-cycle-a.js @@ -0,0 +1,2 @@ +import { CycleB } from "./imports-cycle-b.js"; +export var CycleA = "CycleA"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-cycle-b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-cycle-b.js new file mode 100644 index 0000000000..218f350c39 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-cycle-b.js @@ -0,0 +1,2 @@ +import { CycleA } from "./imports-cycle-a.js"; +export var CycleB = "CycleB"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-cycle.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-cycle.js new file mode 100644 index 0000000000..88a77a4d67 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-cycle.js @@ -0,0 +1,6 @@ +import { CycleA } from "./imports-cycle-a.js"; + +test_importCycle.step(function () { + assert_equals(CycleA, "CycleA"); + test_importCycle.done(); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-inc-a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-inc-a.js new file mode 100644 index 0000000000..8cb2298e8a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-inc-a.js @@ -0,0 +1,2 @@ +import { A } from "./imports-a.js"; +export { A as INC_A }; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-inc-ab.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-inc-ab.js new file mode 100644 index 0000000000..b7d84005c5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-inc-ab.js @@ -0,0 +1,5 @@ +import { A } from "./imports-a.js"; +export { A as INC_AB_A }; + +import { B } from "./imports-b.js"; +export { B as INC_AB_B }; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-inc-b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-inc-b.js new file mode 100644 index 0000000000..243b84fdd0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-inc-b.js @@ -0,0 +1,2 @@ +import { B } from "./imports-b.js"; +export { B as INC_B };
\ No newline at end of file diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-self-inner.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-self-inner.js new file mode 100644 index 0000000000..40eca1c8df --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-self-inner.js @@ -0,0 +1,2 @@ +import { SelfInner as SelfInnerA } from "./imports-self-inner.js"; +export var SelfInner = "SelfInner"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-self.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-self.js new file mode 100644 index 0000000000..05fa60e2dc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports-self.js @@ -0,0 +1,6 @@ +import { SelfInner } from "./imports-self-inner.js"; + +test_importSelf.step(function () { + assert_equals(SelfInner, "SelfInner"); + test_importSelf.done(); +}); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports.html new file mode 100644 index 0000000000..ca6900744d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/imports.html @@ -0,0 +1,64 @@ +<!DOCTYPE html> +<html> +<head> + <title>html-script-module-imports</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <h1>html-script-module-imports</h1> + + <script type="module"> + + import { A } from "./imports-a.js"; + + test(function () { + assert_equals(A.from, "imports-a.js", "Unexpected A"); + }, "Import a simple module"); + + </script> + <script type="module"> + + import { B as B_RENAMED } from "./imports-b.js"; + + test(function () { + assert_equals(B_RENAMED.from, "imports-b.js", "Unexpected B_RENAMED"); + + try + { + B; + assert_unreached("Unexpectedly defined B"); + } + catch (ex) + {} + }, "Import a simple module, renamed"); + + </script> + <script type="module"> + + import { INC_A } from "./imports-inc-a.js"; + import { INC_B } from "./imports-inc-b.js"; + import { INC_AB_A, INC_AB_B } from "./imports-inc-ab.js"; + + test(function () { + assert_equals(INC_A.from, "imports-a.js", "Unexpected INC_A"); + assert_equals(INC_B.from, "imports-b.js", "Unexpected INC_A"); + assert_equals(INC_AB_A.from, "imports-a.js", "Unexpected INC_A"); + assert_equals(INC_AB_B.from, "imports-b.js", "Unexpected INC_A"); + assert_equals(INC_A, INC_AB_A, "INC_A and INC_AB_A should be the same"); + assert_equals(INC_B, INC_AB_B, "INC_B and INC_AB_B should be the same"); + }, "Import the same module multiple times"); + + </script> + + <script> + var test_importSelf = async_test("Import a module that validly imports itself"); + </script> + <script type="module" src="imports-self.js"></script> + + <script> + var test_importCycle = async_test("Import a module with a valid cyclical module dependency"); + </script> + <script type="module" src="imports-cycle.js"></script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inactive-context-import.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inactive-context-import.html new file mode 100644 index 0000000000..ce88c0a152 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inactive-context-import.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Dynamic import triggered from inactive context should not crash</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id="container"> +<iframe></iframe> +</div> + +<script> +test(() => { + const iframe = document.querySelector('iframe'); + const otherWindow = iframe.contentWindow; + iframe.remove(); + + // Below should not crash + otherWindow.eval(`import('foobar');`); +}, 'dynamic import from inactive context should not crash'); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-async-execorder.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-async-execorder.html new file mode 100644 index 0000000000..db03612e82 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-async-execorder.html @@ -0,0 +1,29 @@ +<html> + <head> + <title>Inline async module script execution order</title> + <meta name=timeout content=long> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script> + let loaded = []; + let test = async_test("Inline async module script execution order"); + window.addEventListener("load", test.step_func(function() { + assert_array_equals(loaded, + ["fast", "fast", "fast", "slow", "slow", "slow"]); + test.done(); + })); + </script> + <script type="module" async src="resources/slow-module.js?pipe=trickle(d2)&unique=1"></script> + <script type="module" async> + import "./resources/slow-module.js?pipe=trickle(d2)&unique=2"; + loaded.push("slow"); + </script> + <script type="module" async src="resources/fast-module.js?unique=1"></script> + <script type="module" async> + import "./resources/fast-module.js?unique=2"; + loaded.push("fast"); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-async-onload.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-async-onload.html new file mode 100644 index 0000000000..314abc98dc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-async-onload.html @@ -0,0 +1,28 @@ +<html> + <head> + <title>Inline async module script without external deps onload blocking</title> + <meta name=timeout content=long> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script> + let loadFired = false; + let moduleRan = false + let test = async_test("Inline async module script vs. onload"); + window.addEventListener("load", test.step_func(function() { + loadFired = true; + assert_true(moduleRan, "Module should have run before the load event"); + test.step_timeout(function() { + test.done(); + }, 0); + })); + </script> + <script type="module" async> + moduleRan = true; + test.step_func(function() { + assert_false(loadFired, "onload should not have fired yet"); + }); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-defer-onload.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-defer-onload.html new file mode 100644 index 0000000000..0a0bc36f8b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-defer-onload.html @@ -0,0 +1,29 @@ +<html> + <head> + <title>Inline defer module script without external deps onload blocking</title> + <meta name=timeout content=long> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script> + let loadFired = false; + let moduleRan = false + let test = async_test("Inline defer module script vs. onload"); + window.addEventListener("load", test.step_func(function() { + loadFired = true; + assert_true(moduleRan, "Module should have run before the load event"); + test.step_timeout(function() { + test.done(); + }, 0); + })); + </script> + <!-- defer should be equivalent to neither defer nor async specified --> + <script type="module" defer> + moduleRan = true; + test.step_func(function() { + assert_false(loadFired, "onload should not have fired yet"); + }); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-no-async-onload.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-no-async-onload.html new file mode 100644 index 0000000000..50f42c6a38 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/inline-no-async-onload.html @@ -0,0 +1,28 @@ +<html> + <head> + <title>Inline module script without external deps onload blocking</title> + <meta name=timeout content=long> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + </head> + <body> + <script> + let loadFired = false; + let moduleRan = false + let test = async_test("Inline module script vs. onload"); + window.addEventListener("load", test.step_func(function() { + loadFired = true; + assert_true(moduleRan, "Module should have run before the load event"); + test.step_timeout(function() { + test.done(); + }, 0); + })); + </script> + <script type="module"> + moduleRan = true; + test.step_func(function() { + assert_false(loadFired, "onload should not have fired yet"); + }); + </script> + </body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html new file mode 100644 index 0000000000..57b40f5baa --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<title>Handling of instantiation errors, 1</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + const test_load = async_test( + "Test that missing exports lead to SyntaxError events on window and " + + "load events on script"); + + window.log = []; + window.addEventListener("error", ev => { + test_load.step(() => assert_equals(ev.error.constructor, SyntaxError)); + log.push(ev.message); + }); + + window.addEventListener("load", test_load.step_func_done(ev => { + const msg = log[0]; + assert_array_equals(log, [msg, 1, msg, 2, msg, 3, msg, 4, msg, 5]); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./missing-export.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./missing-export.js" + onerror="unreachable()" onload="log.push(2)"></script> +<script type="module" src="./missing-export-nested.js" + onerror="unreachable()" onload="log.push(3)"></script> +<script type="module" src="./missing-export.js" + onerror="unreachable()" onload="log.push(4)"></script> +<script type="module" src="./missing-export-nested.js" + onerror="unreachable()" onload="log.push(5)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.js new file mode 100644 index 0000000000..e317b01cc2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-1.js @@ -0,0 +1 @@ +import something from "./instantiation-error-1.js"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html new file mode 100644 index 0000000000..27ba006fc7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-2.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<title>Handling of instantiation errors, 2</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + const test_load = async_test( + "Test that missing exports lead to SyntaxError events on window and " + + "load events on script"); + + window.log = []; + window.addEventListener("error", ev => { + test_load.step(() => assert_equals(ev.error.constructor, SyntaxError)); + log.push(ev.message); + }); + + window.addEventListener("load", test_load.step_func_done(ev => { + const msg = log[0]; + assert_array_equals(log, [msg, 1, msg, 2, msg, 3, msg, 4, msg, 5]); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./missing-export-nested.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./missing-export-nested.js" + onerror="unreachable()" onload="log.push(2)"></script> +<script type="module" src="./missing-export.js" + onerror="unreachable()" onload="log.push(3)"></script> +<script type="module" src="./missing-export-nested.js" + onerror="unreachable()" onload="log.push(4)"></script> +<script type="module" src="./missing-export.js" + onerror="unreachable()" onload="log.push(5)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html new file mode 100644 index 0000000000..32f0a4a243 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-3.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<title>Handling of instantiation errors, 3</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + const test_load = async_test( + "Test that unresolvable cycles lead to SyntaxError events on window " + + "and load events on script"); + + window.log = []; + window.addEventListener("error", ev => { + test_load.step(() => assert_equals(ev.error.constructor, SyntaxError)); + log.push(ev.message); + }); + + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 6, 'Log length'); + assert_equals(log[1], 1); + assert_equals(log[3], 2); + assert_equals(log[5], 3); + assert_not_equals(log[0], log[2], + 'Instantiation error objects for different root scripts'); + assert_equals(log[0], log[4], + 'Instantiation error objects for the same root script'); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./cycle-unresolvable.js" + onerror="unreachable()" onload="log.push(1)" nomodule></script> +<script type="module" src="./cycle-unresolvable-a.js" + onerror="unreachable()" onload="log.push(2)"></script> +<script type="module" src="./cycle-unresolvable.js" + onerror="unreachable()" onload="log.push(3)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html new file mode 100644 index 0000000000..8d3f23819a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<title>Handling of instantiation errors, 4</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + const test_load = async_test( + "Test that loading a graph in which a module is already " + + "errored results in an error."); + + window.addEventListener("error", ev => { + test_load.step(() => assert_equals(ev.error.constructor, SyntaxError)); + log.push(ev.message); + }); + + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 4, 'Log length'); + assert_equals(log[1], 1); + assert_equals(log[3], 2); + assert_not_equals(log[0], log[2], + 'Instantiation error objects for different root scripts'); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./instantiation-error-4a.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./instantiation-error-4d.js" + onerror="unreachable()" onload="log.push(2)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4a.js new file mode 100644 index 0000000000..6fed27f1c7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4a.js @@ -0,0 +1,2 @@ +import "./instantiation-error-4b.js"; +log.push("instantiation-error-4a"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4b.js new file mode 100644 index 0000000000..4b702cae67 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4b.js @@ -0,0 +1,3 @@ +import "./instantiation-error-4c.js"; +import "./instantiation-error-4d.js"; +log.push("instantiation-error-4b"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4c.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4c.js new file mode 100644 index 0000000000..ef699f6ca3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4c.js @@ -0,0 +1,2 @@ +import {something} from "./instantiation-error-4c.js"; +log.push("instantiation-error-4c"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4d.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4d.js new file mode 100644 index 0000000000..ac04ccb9b3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-4d.js @@ -0,0 +1,2 @@ +import {something} from "./instantiation-error-4d.js"; +log.push("instantiation-error-4d"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html new file mode 100644 index 0000000000..20df0bb5c9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<title>Handling of instantiation errors, 5</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + const test_load = async_test( + "Test that loading a graph in which a module is already " + + "errored results an error."); + + window.log = []; + window.addEventListener("error", ev => { + test_load.step(() => assert_equals(ev.error.constructor, SyntaxError)); + log.push(ev.message); + }); + + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 4, 'Log length'); + assert_equals(log[1], 1); + assert_equals(log[3], 2); + assert_not_equals(log[0], log[2], + 'Instantiation error objects for different root scripts'); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./instantiation-error-5a.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./instantiation-error-5d.js" + onerror="unreachable()" onload="log.push(2)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5a.js new file mode 100644 index 0000000000..b2e6b106b2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5a.js @@ -0,0 +1,2 @@ +import "./instantiation-error-5b.js"; +log.push("instantiation-error-5a"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5b.js new file mode 100644 index 0000000000..2d37ae8fff --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5b.js @@ -0,0 +1,3 @@ +import "./instantiation-error-5c.js"; +import "./instantiation-error-5d.js"; +log.push("instantiation-error-5b"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5c.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5c.js new file mode 100644 index 0000000000..ba221b6fc0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5c.js @@ -0,0 +1,2 @@ +import {something} from "./instantiation-error-5c.js"; +log.push("instantiation-error-5c"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5d.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5d.js new file mode 100644 index 0000000000..9775e04f82 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5d.js @@ -0,0 +1,3 @@ +import "./instantiation-error-5e.js"; +import "./instantiation-error-5a.js"; +log.push("instantiation-error-5d"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5e.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5e.js new file mode 100644 index 0000000000..8bd3b3c3bf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-5e.js @@ -0,0 +1,2 @@ +import {something} from "./instantiation-error-5e.js"; +log.push("instantiation-error-5e"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6.html new file mode 100644 index 0000000000..8d3ce121ee --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<title>Handling of instantiation errors, 6</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that ambiguous star exports lead to an instantiation error " + + "and that the correct module is blamed."); + // Concretely, instantiation-error-6a.js fails to instantiate because it + // requests a name from instantion-error-6b.js that is ambiguous there. + // instantiation-error-6b.js itself, however, is fine, and it instantiates + // and evaluates successfully. + window.addEventListener("load", test_load.step_func_done(ev => { + const exn = log[0]; + assert_array_equals(log, [ + exn, 1, + "instantiation-error-6c", + "instantiation-error-6d", + "instantiation-error-6b", 2 + ]); + assert_equals(exn.constructor, SyntaxError); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./instantiation-error-6a.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./instantiation-error-6b.js" + onerror="unreachable()" onload="log.push(2)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6a.js new file mode 100644 index 0000000000..4db49c6c46 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6a.js @@ -0,0 +1,2 @@ +import {foo} from "./instantiation-error-6b.js"; +log.push("instantiation-error-6a"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6b.js new file mode 100644 index 0000000000..35272fe550 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6b.js @@ -0,0 +1,3 @@ +export * from "./instantiation-error-6c.js"; +export * from "./instantiation-error-6d.js"; +log.push("instantiation-error-6b"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6c.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6c.js new file mode 100644 index 0000000000..69d616b4ba --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6c.js @@ -0,0 +1,2 @@ +export let foo = "c"; +log.push("instantiation-error-6c"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6d.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6d.js new file mode 100644 index 0000000000..d1336a57a2 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-6d.js @@ -0,0 +1,2 @@ +export let foo = "d"; +log.push("instantiation-error-6d"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7.html new file mode 100644 index 0000000000..57f1f87216 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<title>Handling of instantiation errors, 7</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that ambiguous star exports lead to an instantiation error, " + + "even when discovered through a star export, and that the correct " + + "module is blamed."); + // This is a variation of instantiation-error-6.html (see the explanation + // there). + window.addEventListener("load", test_load.step_func_done(ev => { + const exn = log[0]; + assert_array_equals(log, [ + exn, 1, + "instantiation-error-7d", + "instantiation-error-7e", + "instantiation-error-7c", + "instantiation-error-7f", + "instantiation-error-7b", 2 + ]); + assert_equals(exn.constructor, SyntaxError); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./instantiation-error-7a.js" + onerror="unreachable()" onload="log.push(1)"></script> +<script type="module" src="./instantiation-error-7b.js" + onerror="unreachable()" onload="log.push(2)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7a.js new file mode 100644 index 0000000000..d27a44865c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7a.js @@ -0,0 +1,2 @@ +import {foo} from "./instantiation-error-7b.js"; +log.push("instantiation-error-7a"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7b.js new file mode 100644 index 0000000000..8c05d3b727 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7b.js @@ -0,0 +1,3 @@ +export * from "./instantiation-error-7c.js"; +export * from "./instantiation-error-7f.js"; +log.push("instantiation-error-7b"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7c.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7c.js new file mode 100644 index 0000000000..fff1368034 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7c.js @@ -0,0 +1,3 @@ +export * from "./instantiation-error-7d.js"; +export * from "./instantiation-error-7e.js"; +log.push("instantiation-error-7c"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7d.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7d.js new file mode 100644 index 0000000000..fa5e7651f4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7d.js @@ -0,0 +1,2 @@ +export let foo = "d"; +log.push("instantiation-error-7d"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7e.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7e.js new file mode 100644 index 0000000000..6547c3fe6a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7e.js @@ -0,0 +1,2 @@ +export let foo = "e"; +log.push("instantiation-error-7e"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7f.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7f.js new file mode 100644 index 0000000000..7f9ec5d12e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-7f.js @@ -0,0 +1,2 @@ +export let foo = "f"; +log.push("instantiation-error-7f"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-8.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-8.html new file mode 100644 index 0000000000..080b170233 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/instantiation-error-8.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>Handling of instantiation errors, 8</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- The below module tree should fail to instantiate, since it references undefined identifier. --> +<script type="module" src="instantiation-error-1.js"></script> +<script> +setup({allow_uncaught_exception: true}); + +promise_test(t => { + return new Promise(resolve => { + window.addEventListener("error", e => { + assert_equals(e.error.constructor, SyntaxError); + resolve(); + }, { once: true }); + }).then(() => new Promise(resolve => { + window.addEventListener("error", e => { + assert_equals(e.error.constructor, SyntaxError); + resolve(); + }, { once: true }); + // Load another module tree w/ previously instantiate-failed tree as its sub-tree. + document.head.appendChild(Object.assign( + document.createElement('script'), + { type: 'module', innerText: 'import "./instantiation-error-1.js"'})); + })); +}, "Instantiate attempt on a tree w/ previously instantiate-failed tree as a sub-tree shouldn't crash."); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-matches-inner.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-matches-inner.js new file mode 100644 index 0000000000..369b3e7827 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-matches-inner.js @@ -0,0 +1 @@ +window.matchesLog.push("integrity-matches-inner"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-matches.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-matches.js new file mode 100644 index 0000000000..d8c4219e90 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-matches.js @@ -0,0 +1,2 @@ +import "./integrity-matches-inner.js"; +window.matchesLog.push("integrity-matches"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-mismatches-inner.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-mismatches-inner.js new file mode 100644 index 0000000000..8182d4de16 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-mismatches-inner.js @@ -0,0 +1 @@ +window.mismatchesLog.push("integrity-mismatches-inner"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-mismatches.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-mismatches.js new file mode 100644 index 0000000000..2d47344a5a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity-mismatches.js @@ -0,0 +1,2 @@ +import "./integrity-mismatches-inner.js"; +window.mismatchesLog.push("integrity-mismatches"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity.html new file mode 100644 index 0000000000..c79843624f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/integrity.html @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title><script> integrity=""</title> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +window.inlineRan = false; + +window.matchesLog = []; +window.matchesEvents = []; + +window.mismatchesLog = []; +window.mismatchesEvents = []; +</script> + +<script type="module" integrity="sha384-garbage"> +window.inlineRan = true; +</script> + +<script type="module" src="integrity-matches.js" integrity="sha384-1/XwTy38IAlmvk1O674Efus1/REqfuX6x0V/B2/GX5R3lNbRjhrIwlWyEDPyOwpN" onload="window.matchesEvents.push('load');" onerror="window.matchesEvents.push('error')"></script> +<script type="module" src="integrity-mismatches.js" integrity="sha384-doesnotmatch" onload="window.mismatchesEvents.push('load');" onerror="window.mismatchesEvents.push('error')"></script> + +<script type="module"> +test(() => { + assert_true(window.inlineRan); +}, "The integrity attribute must have no affect on inline module scripts"); + +test(() => { + assert_array_equals(window.matchesLog, ["integrity-matches-inner", "integrity-matches"], "The module and its dependency must have executed"); + assert_array_equals(window.matchesEvents, ["load"], "The load event must have fired"); +}, "The integrity attribute must be verified on the top-level of a module and allow it to execute when it matches"); + +test(() => { + assert_array_equals(window.mismatchesLog, [], "The module and its dependency must not have executed"); + assert_array_equals(window.mismatchesEvents, ["error"], "The error event must have fired"); +}, "The integrity attribute must be verified on the top-level of a module and not allow it to execute when there's a mismatch"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/late-namespace-request.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/late-namespace-request.html new file mode 100644 index 0000000000..00269efdf9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/late-namespace-request.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<title>Late namespace request</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test the situation where a module is instantiated without the " + + "need for a namespace object, but later on a different module " + + "requests the namespace."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, + ["export-something", + "import-something-namespace", 42, 43]); + })); +</script> +<script type="module" src="export-something.js"></script> +<script type="module" src="import-something-namespace.js"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/late-star-export-request.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/late-star-export-request.html new file mode 100644 index 0000000000..d40bb0aca7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/late-star-export-request.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<title>Late star-export request</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test the situation where a module is instantiated without a use of " + + "its star-exports, but later on a different module requests them."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, [ + "export-something", "export-something-nested", + "import-something-namespace", 42, 43]); + })); +</script> +<script type="module" src="export-something-nested.js"></script> +<script type="module"> + log.push("import-something-namespace"); + log.push(foo); + set_foo(43); + log.push(foo); + import {foo, set_foo} from "./export-something-nested.js"; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/load-error-events-inline.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/load-error-events-inline.html new file mode 100644 index 0000000000..58397dd07d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/load-error-events-inline.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<head> +<title>load/error events for inline module scripts</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/load-error-events-helpers.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +</head> +<script> +"use strict"; + +var test1_load = event_test('src, 200, parser-inserted, defer, no async', false, false); +var test4_load = event_test('src, 200, parser-inserted, no defer, async', false, false); + +var test3_dynamic_load = event_test('src, 200, not parser-inserted, no defer, no async, no non-blocking', false, false); +var test4_dynamic_load = event_test('src, 200, not parser-inserted, no defer, async', false, false); + +var test1_error = event_test('src, 404, parser-inserted, defer, no async', false, true); +var test4_error = event_test('src, 404, parser-inserted, no defer, async', false, true); + +var test3_dynamic_error = event_test('src, 404, not parser-inserted, no defer, no async, no non-blocking', false, true); +var test4_dynamic_error = event_test('src, 404, not parser-inserted, no defer, async', false, true); + +var script3_dynamic_load = document.createElement('script'); +script3_dynamic_load.setAttribute('type', 'module'); +script3_dynamic_load.onload = () => onLoad(test3_dynamic_load); +script3_dynamic_load.onerror = () => onError(test3_dynamic_load); +script3_dynamic_load.async = false; +script3_dynamic_load.appendChild(document.createTextNode('onExecute(test3_dynamic_load);')); +document.head.appendChild(script3_dynamic_load); + +var script3_dynamic_error = document.createElement('script'); +script3_dynamic_error.setAttribute('type', 'module'); +script3_dynamic_error.onload = () => onLoad(test3_dynamic_error); +script3_dynamic_error.onerror = () => onError(test3_dynamic_error); +script3_dynamic_error.async = false; +script3_dynamic_error.appendChild(document.createTextNode('import "./not_found.js";')); +document.head.appendChild(script3_dynamic_error); + +var script4_dynamic_load = document.createElement('script'); +script4_dynamic_load.setAttribute('type', 'module'); +script4_dynamic_load.onload = () => onLoad(test4_dynamic_load); +script4_dynamic_load.onerror = () => onError(test4_dynamic_load); +script4_dynamic_load.async = true; +script4_dynamic_load.appendChild(document.createTextNode('onExecute(test4_dynamic_load);')); +document.head.appendChild(script4_dynamic_load); + +var script4_dynamic_error = document.createElement('script'); +script4_dynamic_error.setAttribute('type', 'module'); +script4_dynamic_error.onload = () => onLoad(test4_dynamic_error); +script4_dynamic_error.onerror = () => onError(test4_dynamic_error); +script4_dynamic_error.async = true; +script4_dynamic_error.appendChild(document.createTextNode('import "./not_found.js";')); +document.head.appendChild(script4_dynamic_error); +</script> + +<script onload="onLoad(test1_load);" onerror="onError(test1_load);" type="module">"use strict";onExecute(test1_load);</script> +<script onload="onLoad(test4_load);" onerror="onError(test4_load);" type="module" async>"use strict";onExecute(test4_load);</script> +<script onload="onLoad(test1_error);" onerror="onError(test1_error);" type="module">"use strict";import "./not_found.js";</script> +<script onload="onLoad(test4_error);" onerror="onError(test4_error);" type="module" async>"use strict";import "./not_found.js";</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/load-error-events.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/load-error-events.html new file mode 100644 index 0000000000..d9bf05226c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/load-error-events.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<head> +<title>load/error events for external module scripts</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="../resources/load-error-events-helpers.js"></script> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +</head> +<script> +"use strict"; + +var test1_load = event_test('src, 200, parser-inserted, defer, no async', true, false); +var test4_load = event_test('src, 200, parser-inserted, no defer, async', true, false); + +var test3_dynamic_load = event_test('src, 200, not parser-inserted, no defer, no async, no non-blocking', true, false); +var test4_dynamic_load = event_test('src, 200, not parser-inserted, no defer, async', true, false); + +var test1_error = event_test('src, 404, parser-inserted, defer, no async', false, true); +var test4_error = event_test('src, 404, parser-inserted, no defer, async', false, true); + +var test3_dynamic_error = event_test('src, 404, not parser-inserted, no defer, no async, no non-blocking', false, true); +var test4_dynamic_error = event_test('src, 404, not parser-inserted, no defer, async', false, true); + +var script3_dynamic_load = document.createElement('script'); +script3_dynamic_load.setAttribute('type', 'module'); +script3_dynamic_load.onload = () => onLoad(test3_dynamic_load); +script3_dynamic_load.onerror = () => onError(test3_dynamic_load); +script3_dynamic_load.async = false; +script3_dynamic_load.src = "../resources/load-error-events.py?test=test3_dynamic_load"; +document.head.appendChild(script3_dynamic_load); + +var script3_dynamic_error = document.createElement('script'); +script3_dynamic_error.setAttribute('type', 'module'); +script3_dynamic_error.onload = () => onLoad(test3_dynamic_error); +script3_dynamic_error.onerror = () => onError(test3_dynamic_error); +script3_dynamic_error.async = false; +script3_dynamic_error.src = "../resources/load-error-events.py?test=test3_dynamic_error"; +document.head.appendChild(script3_dynamic_error); + +var script4_dynamic_load = document.createElement('script'); +script4_dynamic_load.setAttribute('type', 'module'); +script4_dynamic_load.onload = () => onLoad(test4_dynamic_load); +script4_dynamic_load.onerror = () => onError(test4_dynamic_load); +script4_dynamic_load.async = true; +script4_dynamic_load.src = "../resources/load-error-events.py?test=test4_dynamic_load"; +document.head.appendChild(script4_dynamic_load); + +var script4_dynamic_error = document.createElement('script'); +script4_dynamic_error.setAttribute('type', 'module'); +script4_dynamic_error.onload = () => onLoad(test4_dynamic_error); +script4_dynamic_error.onerror = () => onError(test4_dynamic_error); +script4_dynamic_error.async = true; +script4_dynamic_error.src = "../resources/load-error-events.py?test=test4_dynamic_error"; +document.head.appendChild(script4_dynamic_error); +</script> + +<script src="../resources/load-error-events.py?test=test1_load" onload="onLoad(test1_load);" onerror="onError(test1_load);" type="module"></script> +<script src="../resources/load-error-events.py?test=test4_load" onload="onLoad(test4_load);" onerror="onError(test4_load);" type="module" async></script> +<script src="../resources/load-error-events.py?test=test1_error" onload="onLoad(test1_error);" onerror="onError(test1_error);" type="module"></script> +<script src="../resources/load-error-events.py?test=test4_error" onload="onLoad(test4_error);" onerror="onError(test4_error);" type="module" async></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/missing-export-nested.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/missing-export-nested.js new file mode 100644 index 0000000000..860d2bf341 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/missing-export-nested.js @@ -0,0 +1,2 @@ +import "./missing-export.js"; +log.push("nested-missing-export"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/missing-export.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/missing-export.js new file mode 100644 index 0000000000..e6f5746eb7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/missing-export.js @@ -0,0 +1,2 @@ +import something from "./missing-export.js"; +log.push("missing-export"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-import-referrer.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-import-referrer.html new file mode 100644 index 0000000000..7348b88075 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-import-referrer.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html> +<head> +<title>Referrer for module imports</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script>setup({ explicit_done: true })</script> +</head> +<body> +<script type="module"> + +import { referrerExternalStatic, referrerExternalDynamic } from "./module-import-referrer.js"; + +// "name" parameter is necessary for bypassing the module map. +import { referrer as referrerInlineStatic } from "./resources/referrer-checker.py?name=internal-static" +const { referrer: referrerInlineDynamic } = await import("./resources/referrer-checker.py?name=internal-dynamic"); + +const scriptURL = new URL("module-import-referrer.js", location.href) + +test(t => { + assert_equals( + referrerInlineStatic, location.href, + "Referrer should be the document URL"); +}, "Static imports from inline modules in the HTML document"); + +test(t => { + assert_equals( + referrerInlineDynamic, location.href, + "Referrer should be the document URL"); +}, "Dynamic imports from inline modules in the HTML document"); + +test(t => { + assert_equals( + referrerExternalStatic, scriptURL.href, + "Referrer should be the importer module URL"); +}, "Static imports from external modules"); + +test(t => { + assert_equals( + referrerExternalDynamic, scriptURL.href, + "Referrer should be the document URL"); +}, "Dynamic imports from external modules"); + +done(); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-import-referrer.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-import-referrer.js new file mode 100644 index 0000000000..8710f5c621 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-import-referrer.js @@ -0,0 +1,2 @@ +export { referrer as referrerExternalStatic } from "./resources/referrer-checker.py?name=external-static" +export const { referrer: referrerExternalDynamic } = await import("./resources/referrer-checker.py?name=external-dynamic"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-in-xhtml.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-in-xhtml.xhtml new file mode 100644 index 0000000000..1655e61a7c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-in-xhtml.xhtml @@ -0,0 +1,20 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" +"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> +window.evaluated_module_script = true; +</script> +<script> + var test = async_test("module script in XHTML documents should be evaluated."); + window.addEventListener("load", () => { + test.step(() => { assert_true(window.evaluated_module_script); }); + test.done(); + }); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-vs-script-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-vs-script-1.html new file mode 100644 index 0000000000..ae82e1348a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-vs-script-1.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<title>Once as module script, once as classic script</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test that evaluating something as classic script does not prevent " + + "it from being evaluated as module script."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, [window, undefined]); + })); +</script> +<script type="module" src="this.js"></script> +<script src="this.js"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-vs-script-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-vs-script-2.html new file mode 100644 index 0000000000..fb512b4b30 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/module-vs-script-2.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<title>Once as classic script, once as module script</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test that evaluating something as classic script does not prevent " + + "it from being evaluated as module script."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, [window, undefined]); + })); +</script> +<script src="this.js"></script> +<script type="module" src="this.js"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-a.js new file mode 100644 index 0000000000..a127aeb559 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-a.js @@ -0,0 +1 @@ +import { b } from "./nested-imports-b.js"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-b.js new file mode 100644 index 0000000000..18a5af40cc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-b.js @@ -0,0 +1,2 @@ +import { c } from "./nested-imports-c.js"; +export const b = "b"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-c.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-c.js new file mode 100644 index 0000000000..ec44596aea --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-c.js @@ -0,0 +1,2 @@ +import { d } from "./nested-imports-d.js"; +export const c = "c"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-d.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-d.js new file mode 100644 index 0000000000..cee87849c6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-d.js @@ -0,0 +1,3 @@ +import { e } from "./nested-imports-e.js"; +import "./resources/delayed-modulescript.py"; +export const d = "d"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-e.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-e.js new file mode 100644 index 0000000000..ec6f0360a6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-e.js @@ -0,0 +1,2 @@ +import { f } from "./nested-imports-f.js"; +export const e = "e"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-f.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-f.js new file mode 100644 index 0000000000..0591e0b316 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-f.js @@ -0,0 +1,2 @@ +import { g } from "./nested-imports-g.js"; +export const f = "f"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-g.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-g.js new file mode 100644 index 0000000000..86cbe7d3f8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-g.js @@ -0,0 +1,2 @@ +import { h } from "./nested-imports-h.js"; +export const g = "g"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-h.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-h.js new file mode 100644 index 0000000000..a161291259 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports-h.js @@ -0,0 +1,2 @@ +import { c } from "./nested-imports-c.js"; +export const h = "h"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports.html new file mode 100644 index 0000000000..23bb595d0e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-imports.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> +<title>Test imports under more than 3 levels in different modules</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({ allow_uncaught_exception: true }); + + window.log = []; + + const test_load = async_test("should load all modules successfully"); + window.addEventListener( + "load", + test_load.step_func_done((ev) => { + assert_equals(log.length, 2); + + assert_equals(log[0], 1); + assert_equals(log[1], 2); + }) + ); + + function unreachable() { + log.push("unexpected"); + } +</script> +<script type="module" src="./nested-imports-a.js" onerror="unreachable()" + onload="log.push(1)"></script> +<script type="module" src="./nested-imports-e.js" onerror="unreachable()" + onload="log.push(2)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-missing-export.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-missing-export.js new file mode 100644 index 0000000000..3801ae847a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nested-missing-export.js @@ -0,0 +1,2 @@ +import "./missing-export.js"; +log.push("missing-export-nested"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nomodule-attribute.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nomodule-attribute.html new file mode 100644 index 0000000000..656c99b292 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/nomodule-attribute.html @@ -0,0 +1,18 @@ +<!DOCTYPE html> +<title>The 'nomodule' attribute</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test that 'nomodule' has the desired effect on classic scripts, but " + + "no effect on module scripts."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, [undefined]); + })); + +</script> +<script type="module" src="this.js" nomodule></script> +<script src="this.js" nomodule></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html new file mode 100644 index 0000000000..b8866f9511 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-no-referrer.sub.html @@ -0,0 +1,68 @@ +<!DOCTYPE html> +<html> +<head> +<title>Referrer with the no-referrer policy</title> +<meta name="referrer" content="no-referrer"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> + +// "name" parameter is necessary for bypassing the module map. + +import { referrer as referrerSame } from "./resources/referrer-checker.py?name=same"; + +import { referrer as referrerRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name=remote"; + +import { referrer as referrerSameSame } from "./resources/import-referrer-checker.sub.js?name=same_same"; + +import { referrer as referrerSameRemote } from "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote"; + +import { referrer as referrerRemoteRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_remote"; + +import { referrer as referrerRemoteSame } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js?name=remote_same"; + +test(t => { + assert_equals( + referrerSame, "", + "Referrer should not be sent for the same-origin top-level script."); +}, "Importing a same-origin top-level script with the no-referrer policy."); + +test(t => { + assert_equals( + referrerRemote, "", + "Referrer should not be sent for the remote-origin top-level script."); +}, "Importing a remote-origin top-level script with the no-referrer policy."); + +test(t => { + assert_equals( + referrerSameSame, "", + "Referrer should not be sent for the same-origin descendant script."); +}, "Importing a same-origin descendant script from a same-origin top-level " + + "script with the no-referrer policy."); + +test(t => { + assert_equals( + referrerSameRemote, "", + "Referrer should not be sent for the remote-origin descendant script."); +}, "Importing a remote-origin descendant script from a same-origin top-level " + + "script with the no-referrer policy."); + +test(t => { + assert_equals( + referrerRemoteRemote, "", + "Referrer should not be sent for the remote-origin descendant script."); +}, "Importing a remote-origin descendant script from a remote-origin " + + "top-level script with the no-referrer policy."); + +test(t => { + assert_equals( + referrerRemoteSame, "", + "Referrer should not be sent for the same-origin descendant script."); +}, "Importing a same-origin descendant script from a remote-origin " + + "top-level script with the no-referrer policy."); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html new file mode 100644 index 0000000000..fd4c1ea496 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html @@ -0,0 +1,82 @@ +<!DOCTYPE html> +<html> +<head> +<title>Referrer with the origin-when-cross-origin policy</title> +<meta name="referrer" content="origin-when-cross-origin"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> + +// "name" parameter is necessary for bypassing the module map. + +import { referrer as referrerSame } from "./resources/referrer-checker.py?name=same"; + +import { referrer as referrerRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name=remote"; + +import { referrer as referrerSameSame } from "./resources/import-referrer-checker.sub.js?name=same_same"; + +import { referrer as referrerSameRemote } from "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote"; + +import { referrer as referrerRemoteRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_remote"; + +import { referrer as referrerRemoteSame } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js?name=remote_same"; + +const origin = (new URL(location.href)).origin + "/"; +const remoteOrigin = new URL("http://{{domains[www1]}}:{{ports[http][0]}}/").origin + "/"; + +test(t => { + assert_equals( + referrerSame, location.href, + "Full referrer should be sent for the same-origin top-level script."); +}, "Importing a same-origin top-level script with the " + + "origin-when-cross-origin policy."); + +test(t => { + assert_equals( + referrerRemote, origin, + "Referrer should be stripped to the origin when importing " + + "remote-origin top-level script."); +}, "Importing a remote-origin top-level script with the " + + "origin-when-cross-origin policy."); + +test(t => { + const scriptURL = + new URL("resources/import-referrer-checker.sub.js", location.href) + assert_equals( + referrerSameSame, scriptURL + "?name=same_same", + "Full referrer should be sent for same-origin descendant script" + + "imported by same-origin top-level script."); +}, "Importing a same-origin descendant script from a same-origin top-level " + + "script with the origin-when-cross-origin policy."); + +test(t => { + assert_equals( + referrerSameRemote, origin, + "Referrer should be stripped to the origin for the remote-origin " + + "descendant script imported from same-origin top-level script."); +}, "Importing a remote-origin descendant script from a same-origin top-level " + + "script with the origin-when-cross-origin policy."); + +test(t => { + const scriptURL = new URL( + "html/semantics/scripting-1/the-script-element/module/resources/" + + "import-referrer-checker.sub.js", + remoteOrigin); + assert_equals(referrerRemoteRemote, scriptURL + "?name=remote_remote", + "Full referrer should be sent for the remote-origin descendant script " + + "imported from a remote-origin top-level script."); +}, "Importing a remote-origin descendant script from a remote-origin " + + "top-level script with the origin-when-cross-origin policy."); + +test(t => { + assert_equals(referrerRemoteSame, remoteOrigin, + "Referrer should be stripped to the origin for the same-origin " + + "descendant script imported by remote-origin top-level script."); +}, "Importing a same-origin descendant script from a remote-origin " + + "top-level script with the origin-when-cross-origin policy."); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html new file mode 100644 index 0000000000..a554fb4b0c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-origin.sub.html @@ -0,0 +1,71 @@ +<!DOCTYPE html> +<html> +<head> +<title>Referrer with the origin policy</title> +<meta name="referrer" content="origin"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> + +// "name" parameter is necessary for bypassing the module map. + +import { referrer as referrerSame } from "./resources/referrer-checker.py?name=same"; + +import { referrer as referrerRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name=remote"; + +import { referrer as referrerSameSame } from "./resources/import-referrer-checker.sub.js?name=same_same"; + +import { referrer as referrerSameRemote } from "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote"; + +import { referrer as referrerRemoteRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_remote"; + +import { referrer as referrerRemoteSame } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js?name=remote_same"; + +const origin = (new URL(location.href)).origin + "/"; +const remoteOrigin = "http://{{domains[www1]}}:{{ports[http][0]}}/"; + +test(t => { + assert_equals( + referrerSame, origin, + "Referrer should be sent for the same-origin top-level script."); +}, "Importing a same-origin top-level script with the origin policy."); + +test(t => { + assert_equals( + referrerRemote, origin, + "Referrer should be sent for the remote-origin top-level script."); +}, "Importing a remote-origin top-level script with the origin policy."); + +test(t => { + assert_equals( + referrerSameSame, origin, + "Referrer should be sent for the same-origin descendant script."); +}, "Importing a same-origin descendant script from a same-origin top-level " + + "script with the origin policy."); + +test(t => { + assert_equals( + referrerSameRemote, origin, + "Referrer should be sent for the remote-origin descendant script."); +}, "Importing a remote-origin descendant script from a same-origin top-level " + + "script with the origin policy."); + +test(t => { + assert_equals( + referrerRemoteRemote, remoteOrigin, + "Referrer should be sent for the remote-origin descendant script."); +}, "Importing a remote-origin descendant script from a remote-origin " + + "top-level script with the origin policy."); + +test(t => { + assert_equals( + referrerRemoteSame, remoteOrigin, + "Referrer should be sent for the same-origin descendant script."); +}, "Importing a same-origin descendant script from a remote-origin " + + "top-level script with the origin policy."); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-policy-for-descendants.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-policy-for-descendants.sub.html new file mode 100644 index 0000000000..4a7005da84 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-policy-for-descendants.sub.html @@ -0,0 +1,122 @@ +<!DOCTYPE html> +<html> +<head> +<title>Module script descendants use the referrer policy on their ancestor, if one exists</title> +<link rel=help href="https://github.com/whatwg/html/pull/9210"> +<meta name="referrer" content="no-referrer"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> + +// "name" parameter is necessary for bypassing the module map. +// +// The case where the parent module script is sent with no referrer policy at +// all is covered in `referrer-no-referrer.sub.html` (and others like it). In +// that case, the parent module inherits its referencing document's referrer +// policy for use in descendant imports. + +import { referrer as parentWithNoReferrerWhenDowngrade } from + "./resources/import-referrer-checker.sub.js?name=same_same&pipe=header(Referrer-Policy,no-referrer-when-downgrade)"; + +import { referrer as parentWithOrigin} from + "./resources/import-referrer-checker.sub.js?name=same_remote&pipe=header(Referrer-Policy,origin)"; + +import { referrer as parentWithSameOrigin} from + "./resources/import-referrer-checker.sub.js?name=same_remote_so&pipe=header(Referrer-Policy,same-origin)"; + +import { referrer as parentWithOriginWhenCrossOriginRemoteDescendant} from + "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote_owco&pipe=header(Referrer-Policy,origin-when-cross-origin)"; + +import { referrer as remoteParentWithOriginWhenCrossOriginSameOriginDescendant} from + "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_same&pipe=header(Referrer-Policy,origin-when-cross-origin)"; + +import { referrer as remoteParentWithSameOriginWhenCrossOriginSameOriginDescendant} from + "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_same_so&pipe=header(Referrer-Policy,same-origin)"; + +import { referrer as remoteParentWithOriginWhenCrossOriginRemoteDescendant} from + "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js?name=remote_remote&pipe=header(Referrer-Policy,origin-when-cross-origin)"; + +import { referrer as remoteParentWithSameOriginWhenCrossOriginRemoteDescendant} from + "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js?name=remote_remote_so&pipe=header(Referrer-Policy,same-origin)"; + +import { referrer as parentWithInvalidPolicy } from + "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_same_invalid&pipe=header(Referrer-Policy,invalid-policy)"; + +test(t => { + const expected_url = + new URL("html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=same_same&pipe=header(Referrer-Policy,no-referrer-when-downgrade)", + window.origin); + assert_equals( + parentWithNoReferrerWhenDowngrade, expected_url.toString(), + "Descendant referrer should be the parent's full URL."); +}, "Parent module delivered with `no-referrer-when-downgrade` policy importing a same-origin descendant script."); + +test(t => { + assert_equals( + parentWithOrigin, window.origin + "/", + "Descendant referrer should be the parent's origin."); +}, "Parent module delivered with `origin` policy importing a same-origin descendant script."); + +test(t => { + const expected_url = + new URL("html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=same_remote_so&pipe=header(Referrer-Policy,same-origin)", + window.origin); + assert_equals( + parentWithSameOrigin, expected_url.toString(), + "Descendant referrer should be the parent's full URL."); +}, "Parent module delivered with `same-origin` policy importing a same-origin descendant script."); + +test(t => { + assert_equals( + parentWithOriginWhenCrossOriginRemoteDescendant, window.origin + "/", + "Remote descendant referrer should be the parent's origin."); +}, "Parent module delivered with `origin-when-cross-origin` policy importing a cross-origin descendant script."); + +test(t => { + const expected_url = + new URL("/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_same&pipe=header(Referrer-Policy,origin-when-cross-origin)", + "http://{{domains[www1]}}:{{ports[http][0]}}/"); + assert_equals( + remoteParentWithOriginWhenCrossOriginSameOriginDescendant, expected_url.toString(), + "Same-origin descendant referrer should be the parent's full URL."); +}, "Remote parent module delivered with `origin-when-cross-origin` policy importing a same-origin-to-parent-module descendant script."); + +test(t => { + const expected_url = + new URL("/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_same_so&pipe=header(Referrer-Policy,same-origin)", + "http://{{domains[www1]}}:{{ports[http][0]}}/"); + assert_equals( + remoteParentWithSameOriginWhenCrossOriginSameOriginDescendant, expected_url.toString(), + "Same-origin descendant referrer should be the parent's full URL."); +}, "Remote parent module delivered with `same-origin` policy importing a same-origin-to-parent-module descendant script."); + +test(t => { + assert_equals( + remoteParentWithOriginWhenCrossOriginRemoteDescendant, "http://{{domains[www1]}}:{{ports[http][0]}}/", + "Remote-origin descendant referrer should be the parent's origin."); +}, "Remote parent module delivered with `origin-when-cross-origin` policy importing a cross-origin-to-parent-module descendant script."); + +test(t => { + assert_equals( + remoteParentWithSameOriginWhenCrossOriginRemoteDescendant, ""); +}, "Remote parent module delivered with `same-origin` policy importing a cross-origin-to-parent-module descendant script."); + +// This tests the following spec line: +// +// "If referrerPolicy is not the empty string, set options's referrer policy to +// referrerPolicy." +// +// In other words, invalid referrer policies are ignored, so the referrer policy +// from the referencing document is inherited as usual, which is `no-referrer` +// in this case. +test(t => { + assert_equals( + parentWithInvalidPolicy, "", + "Descendant referrer should be empty."); +}, "Parent module delivered with invalid policy importing a same-origin descendant script."); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html new file mode 100644 index 0000000000..7d6d515a47 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-same-origin.sub.html @@ -0,0 +1,77 @@ +<!DOCTYPE html> +<html> +<head> +<title>Referrer with the same-origin policy</title> +<meta name="referrer" content="same-origin"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> + +// "name" parameter is necessary for bypassing the module map. + +import { referrer as referrerSame } from "./resources/referrer-checker.py?name=same"; + +import { referrer as referrerRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name=remote"; + +import { referrer as referrerSameSame } from "./resources/import-referrer-checker.sub.js?name=same_same"; + +import { referrer as referrerSameRemote } from "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote"; + +import { referrer as referrerRemoteRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_remote"; + +import { referrer as referrerRemoteSame } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js?name=remote_same"; + +const remoteOrigin = "http://{{domains[www1]}}:{{ports[http][0]}}/"; + +test(t => { + assert_equals( + referrerSame, location.href, + "Referrer should be sent for the same-origin top-level script."); +}, "Importing a same-origin top-level script with the same-origin policy."); + +test(t => { + assert_equals( + referrerRemote, "", + "Referrer should not be sent for the remote-origin top-level script."); +}, "Importing a remote-origin top-level script with the same-origin policy."); + +test(t => { + const path = + new URL("resources/import-referrer-checker.sub.js", location.href); + assert_equals( + referrerSameSame, path + `?name=same_same`, + "Referrer should be sent for the same-origin descendant script."); +}, "Importing a same-origin descendant script from a same-origin top-level " + + "script with the same-origin policy."); + +test(t => { + assert_equals( + referrerSameRemote, "", + "Referrer should not be sent for the remote-origin descendant script."); +}, "Importing a remote-origin descendant script from a same-origin top-level " + + "script with the same-origin policy."); + +test(t => { + const scriptURL = new URL( + "html/semantics/scripting-1/the-script-element/module/resources/" + + "import-referrer-checker.sub.js", remoteOrigin); + assert_equals( + referrerRemoteRemote, scriptURL + "?name=remote_remote", + "Referrer should be sent for the remote-origin descendant script " + + "when it is imported from a top-level script in the same remote-origin."); +}, "Importing a remote-origin descendant script from a remote-origin " + + "top-level script with the same-origin policy."); + +test(t => { + assert_equals( + referrerRemoteSame, "", + "Referrer should not be sent for the same-origin descendant script " + + "when it is imported from a top-level remote-origin script."); +}, "Importing a same-origin descendant script from a remote-origin " + + "top-level script with the same-origin policy."); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-strict-policies.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-strict-policies.sub.html new file mode 100644 index 0000000000..1984d875b3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-strict-policies.sub.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<html> +<head> +<title>Referrer with the strict-origin referrer policy</title> +<meta name="referrer" content="strict-origin"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> + +// "name" parameter is necessary for bypassing the module map in descendant import. + +import { referrer as insecureImport } from "./resources/import-referrer-checker-insecure.sub.js?name=insecure_import"; +import { referrer as secureImport } from "https://{{domains[www]}}:{{ports[https][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker-insecure.sub.js?name=secure_import"; + +const origin = (new URL(location.href)).origin + "/"; + +test(t => { + assert_equals( + insecureImport, origin, + "A document with the strict-origin referrer policy served over HTTP, " + + "imports an module script over HTTP, that imports a descendant script " + + "over HTTP. The request for the descendant script is sent with a " + + "`Referer` header with the page's origin"); + + assert_equals( + secureImport, "", + "A document with the strict-origin referrer policy served over HTTP, " + + "imports an module script over HTTPS, that imports a descendant script " + + "over HTTP. The request for the descendant script is sent with no " + + "`Referer` header"); +}, "The strict-* referrer policies compare the trustworthiness of a " + + "request's referrer string against its URL"); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html new file mode 100644 index 0000000000..443731c1b8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/referrer-unsafe-url.sub.html @@ -0,0 +1,81 @@ +<!DOCTYPE html> +<html> +<head> +<title>Referrer with the unsafe-url policy</title> +<meta name="referrer" content="unsafe-url"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script type="module"> + +// "name" parameter is necessary for bypassing the module map. + +import { referrer as referrerSame } from "./resources/referrer-checker.py?name=same"; + +import { referrer as referrerRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name=remote"; + +import { referrer as referrerSameSame } from "./resources/import-referrer-checker.sub.js?name=same_same"; + +import { referrer as referrerSameRemote } from "./resources/import-remote-origin-referrer-checker.sub.js?name=same_remote"; + +import { referrer as referrerRemoteRemote } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js?name=remote_remote"; + +import { referrer as referrerRemoteSame } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js?name=remote_same"; + +test(t => { + assert_equals( + referrerSame, location.href, + "Referrer should be sent for the same-origin top-level script."); +}, "Importing a same-origin top-level script with the unsafe-url policy."); + +test(t => { + assert_equals( + referrerRemote, location.href, + "Referrer should be sent for the remote-origin top-level script."); +}, "Importing a remote-origin top-level script with the unsafe-url policy."); + +test(t => { + const scriptURL = + new URL("resources/import-referrer-checker.sub.js", location.href) + assert_equals( + referrerSameSame, scriptURL + "?name=same_same", + "Referrer should be sent for the same-origin descendant script."); +}, "Importing a same-origin descendant script from a same-origin top-level " + + "script with the unsafe-url policy."); + +test(t => { + const scriptURL = + new URL("resources/import-remote-origin-referrer-checker.sub.js", + location.href) + assert_equals( + referrerSameRemote, scriptURL + "?name=same_remote", + "Referrer should be sent for the remote-origin descendant script."); +}, "Importing a remote-origin descendant script from a same-origin top-level " + + "script with the unsafe-url policy."); + +test(t => { + const scriptURL = + "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/" + + "scripting-1/the-script-element/module/resources/" + + "import-referrer-checker.sub.js"; + assert_equals( + referrerRemoteRemote, scriptURL + "?name=remote_remote", + "Referrer should be sent for the remote-origin descendant script."); +}, "Importing a remote-origin descendant script from a remote-origin " + + "top-level script with the unsafe-url policy."); + +test(t => { + const scriptURL = + "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/" + + "scripting-1/the-script-element/module/resources/" + + "import-same-origin-referrer-checker-from-remote-origin.sub.js"; + assert_equals( + referrerRemoteSame, scriptURL + "?name=remote_same", + "Referrer should be sent for the same-origin descendant script."); +}, "Importing a same-origin descendant script from a remote-origin " + + "top-level script with the unsafe-url policy."); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/404-but-js.asis b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/404-but-js.asis new file mode 100644 index 0000000000..0fe1379e56 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/404-but-js.asis @@ -0,0 +1,4 @@ +HTTP/1.1 404 Not Found +Content-Type: text/javascript + +window.ran404 = true; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/500-but-js.asis b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/500-but-js.asis new file mode 100644 index 0000000000..c81202f7ef --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/500-but-js.asis @@ -0,0 +1,4 @@ +HTTP/1.1 500 Not Found +Content-Type: text/javascript + +window.ran500 = true; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py new file mode 100644 index 0000000000..90551e92c3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py @@ -0,0 +1,20 @@ +def main(request, response): + headers = [ + (b"Content-Type", b"text/javascript"), + (b"Access-Control-Allow-Origin", request.GET.first(b"origin")), + (b"Access-Control-Allow-Credentials", b"true") + ] + identifier = request.GET.first(b"id") + cookie_name = request.GET.first(b"cookieName") + cookie = request.cookies.first(cookie_name, None) + if identifier is None or cookie_name is None: + return headers, b"" + + if cookie is None: + result = b"not found" + elif cookie.value == b"1": + result = b"found" + else: + result = b"different value: " + cookie.value + + return headers, b"window." + identifier + b" = '" + result + b"';" diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/credentials-iframe.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/credentials-iframe.sub.html new file mode 100644 index 0000000000..dbc14dffec --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/credentials-iframe.sub.html @@ -0,0 +1,50 @@ +<!DOCTYPE html> +<meta charset="utf-8"> + +<script type="module" + src="check-cookie.py?id=sameOriginNone&cookieName=same&origin=http://{{host}}:{{ports[http][0]}}"> +</script> +<script type="module" + src="check-cookie.py?id=sameOriginAnonymous&cookieName=same&origin=http://{{host}}:{{ports[http][0]}}" + crossOrigin="anonymous"> +</script> +<script type="module" + src="check-cookie.py?id=sameOriginUseCredentials&cookieName=same&origin=http://{{host}}:{{ports[http][0]}}" + crossOrigin="use-credentials"> +</script> +<script type="module" + src="http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py?id=crossOriginNone&cookieName=cross&origin=http://{{host}}:{{ports[http][0]}}"> +</script> +<script type="module" + src="http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py?id=crossOriginAnonymous&cookieName=cross&origin=http://{{host}}:{{ports[http][0]}}" + crossOrigin="anonymous"> +</script> +<script type="module" + src="http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py?id=crossOriginUseCredentials&cookieName=cross&origin=http://{{host}}:{{ports[http][0]}}" + crossOrigin="use-credentials"> +</script> + +<script type="module"> +import "./check-cookie.py?id=sameOriginNoneDescendant&cookieName=same&origin=http://{{host}}:{{ports[http][0]}}"; +</script> +<script type="module" crossOrigin="anonymous"> +import "./check-cookie.py?id=sameOriginAnonymousDescendant&cookieName=same&origin=http://{{host}}:{{ports[http][0]}}"; +</script> +<script type="module" crossOrigin="use-credentials"> +import "./check-cookie.py?id=sameOriginUseCredentialsDescendant&cookieName=same&origin=http://{{host}}:{{ports[http][0]}}"; +</script> +<script type="module"> +import "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py?id=crossOriginNoneDescendant&cookieName=cross&origin=http://{{host}}:{{ports[http][0]}}"; +</script> +<script type="module" crossOrigin="anonymous"> +import "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py?id=crossOriginAnonymousDescendant&cookieName=cross&origin=http://{{host}}:{{ports[http][0]}}"; +</script> +<script type="module" crossOrigin="use-credentials"> +import "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py?id=crossOriginUseCredentialsDescendant&cookieName=cross&origin=http://{{host}}:{{ports[http][0]}}"; +</script> + +<script type="text/javascript"> +window.addEventListener('load', event => { + window.parent.postMessage({}, '*'); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/delayed-modulescript.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/delayed-modulescript.py new file mode 100644 index 0000000000..52dbfba445 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/delayed-modulescript.py @@ -0,0 +1,7 @@ +import time + +def main(request, response): + delay = float(request.GET.first(b"ms", 500)) + time.sleep(delay / 1E3) + + return [(b"Content-type", b"text/javascript")], u"export let delayedLoaded = true;" diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/dynamic-import-credentials-helper.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/dynamic-import-credentials-helper.sub.js new file mode 100644 index 0000000000..7d9b024e75 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/dynamic-import-credentials-helper.sub.js @@ -0,0 +1,67 @@ +// runTestsFromIframe() is used in the top-level HTML to set cookies and then +// start actual tests in iframe. +function runTestsFromIframe(iframe_url) { + const setSameOriginCookiePromise = fetch( + '/cookies/resources/set-cookie.py?name=same&path=/html/semantics/scripting-1/the-script-element/module/', + { + mode: 'no-cors', + credentials: 'include', + }); + const setCrossOriginCookiePromise = fetch( + 'http://{{domains[www2]}}:{{ports[http][0]}}/cookies/resources/set-cookie.py?name=cross&path=/html/semantics/scripting-1/the-script-element/module/', + { + mode: 'no-cors', + credentials: 'include', + }); + const windowLoadPromise = new Promise(resolve => { + window.addEventListener('load', () => { + resolve(); + }); + }); + + const iframe = document.createElement('iframe'); + Promise.all([setSameOriginCookiePromise, + setCrossOriginCookiePromise, + windowLoadPromise]).then(() => { + iframe.src = iframe_url; + document.body.appendChild(iframe); + fetch_tests_from_window(iframe.contentWindow); + }); +} + +// The functions below are used from tests within the iframe. + +let testNumber = 0; + +// importFunc and setTimeoutFunc is used to make the active script at the time +// of import() to be the script elements that call `runTest()`, +// NOT this script defining runTest(). + +function runTest(importFunc, origin, expected, source) { + let url; + let description; + if (origin === 'same') { + url = "./check-cookie.py"; + description = "Same-origin dynamic import from " + source; + } else { + url = "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/check-cookie.py"; + description = "Cross-origin dynamic import from " + source; + } + promise_test(() => { + const id = "test" + testNumber; + testNumber += 1; + return importFunc(url + "?id=" + id + "&cookieName=" + origin + "&origin=" + location.origin) + .then(() => { + assert_equals(window[id], expected, "cookie"); + }); + }, description); +} + +function setTimeoutWrapper(setTimeoutFunc) { + return url => { + return new Promise(resolve => { + window.resolve = resolve; + setTimeoutFunc(`import("${url}").then(window.resolve)`); + }); + }; +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/dynamic-import-credentials-iframe.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/dynamic-import-credentials-iframe.sub.html new file mode 100644 index 0000000000..88204ef00b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/dynamic-import-credentials-iframe.sub.html @@ -0,0 +1,51 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="dynamic-import-credentials-helper.sub.js"></script> + +<!-- +The active script at the time of import() is the script elements below, and +thus the credentials mode of the fetch options of the script elements below +are used for dynamic import requests. +--> + +<script> +runTest(url => import(url), + "same", "found", "classic script (crossOrigin not specified)"); +runTest(url => import(url), + "cross", "not found", "classic script (crossOrigin not specified)"); +</script> + +<script crossOrigin="anonymous"> +runTest(url => import(url), "same", "found", + "classic script (crossOrigin=anonymous)"); +runTest(url => import(url), "cross", "not found", + "classic script (crossOrigin=anonymous)"); +</script> + +<script crossOrigin="use-credentials"> +runTest(url => import(url), + "same", "found", "classic script (crossOrigin=use-credentials)"); +runTest(url => import(url), + "cross", "found", "classic script (crossOrigin=use-credentials)"); +</script> + +<script type="module"> +runTest(url => import(url), + "same", "found", "module script (crossOrigin not specified)"); +runTest(url => import(url), + "cross", "not found", "module script (crossOrigin not specified)"); +</script> + +<script type="module" crossOrigin="anonymous"> +runTest(url => import(url), "same", "found", + "module script (crossOrigin=anonymous)"); +runTest(url => import(url), "cross", "not found", + "module script (crossOrigin=anonymous)"); +</script> + +<script type="module" crossOrigin="use-credentials"> +runTest(url => import(url), + "same", "found", "module script (crossOrigin=use-credentials)"); +runTest(url => import(url), + "cross", "found", "module script (crossOrigin=use-credentials)"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/dynamic-import-credentials-setTimeout-iframe.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/dynamic-import-credentials-setTimeout-iframe.sub.html new file mode 100644 index 0000000000..ffba141527 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/dynamic-import-credentials-setTimeout-iframe.sub.html @@ -0,0 +1,56 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="dynamic-import-credentials-helper.sub.js"></script> + +<!-- +The active script at the time of import() is the classic script created by +https://html.spec.whatwg.org/multipage/C/#timer-initialisation-steps +and the active script at the time of setTimeout() is the script elements below, +thus the credentials mode of the fetch options of the script elements below +are used for dynamic import requests. + +setTimeout() calls below can't be wrapped (e.g. by step_timeout()) +because wrapping setTimeout() would set active scripts differently. +--> + +<script> +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "same", "found", "setTimeout(string) from classic script (crossOrigin not specified)"); +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "cross", "not found", "setTimeout(string) from classic script (crossOrigin not specified)"); +</script> + +<script crossOrigin="anonymous"> +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "same", "found", "setTimeout(string) from classic script (crossOrigin=anonymous)"); +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "cross", "not found", "setTimeout(string) from classic script (crossOrigin=anonymous)"); +</script> + +<script crossOrigin="use-credentials"> +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "same", "found", "setTimeout(string) from classic script (crossOrigin=use-credentials)"); +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "cross", "found", "setTimeout(string) from classic script (crossOrigin=use-credentials)"); +</script> + +<script type="module"> +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "same", "found", "setTimeout(string) from module script (crossOrigin not specified)"); +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "cross", "not found", "setTimeout(string) from module script (crossOrigin not specified)"); +</script> + +<script type="module" crossOrigin="anonymous"> +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "same", "found", "setTimeout(string) from module script (crossOrigin=anonymous)"); +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "cross", "not found", "setTimeout(string) from module script (crossOrigin=anonymous)"); +</script> + +<script type="module" crossOrigin="use-credentials"> +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "same", "found", "setTimeout(string) from module script (crossOrigin=use-credentials)"); +runTest(setTimeoutWrapper(x => setTimeout(x, 0)), + "cross", "found", "setTimeout(string) from module script (crossOrigin=use-credentials)"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/fast-module.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/fast-module.js new file mode 100644 index 0000000000..3a76cf71f6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/fast-module.js @@ -0,0 +1 @@ +loaded.push("fast"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-non-utf8-with-charset-header.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-non-utf8-with-charset-header.js new file mode 100644 index 0000000000..6fc4ad395c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-non-utf8-with-charset-header.js @@ -0,0 +1 @@ +import "../../serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript%3Bcharset=windows-1250&dummy=6"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-non-utf8.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-non-utf8.js new file mode 100644 index 0000000000..3ae805d78d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-non-utf8.js @@ -0,0 +1 @@ +import "../../serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript&dummy=5"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker-insecure.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker-insecure.sub.js new file mode 100644 index 0000000000..2d6fd96712 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker-insecure.sub.js @@ -0,0 +1 @@ +export { referrer } from 'http://{{host}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name={{GET[name]}}'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker-insecure.sub.js.headers b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker-insecure.sub.js.headers new file mode 100644 index 0000000000..cb762eff80 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker-insecure.sub.js.headers @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js new file mode 100644 index 0000000000..2c7dce9dff --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js @@ -0,0 +1,2 @@ +import { referrer as referrerImport } from './referrer-checker.py?name={{GET[name]}}'; +export const referrer = referrerImport; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js.headers b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js.headers new file mode 100644 index 0000000000..cb762eff80 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-referrer-checker.sub.js.headers @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-remote-origin-referrer-checker.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-remote-origin-referrer-checker.sub.js new file mode 100644 index 0000000000..45a2520b68 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-remote-origin-referrer-checker.sub.js @@ -0,0 +1,2 @@ +import { referrer as referrerImport } from 'http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name={{GET[name]}}'; +export const referrer = referrerImport; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js new file mode 100644 index 0000000000..5a53bcd4d5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js @@ -0,0 +1,2 @@ +import { referrer as referrerImport } from 'http://{{host}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py?name={{GET[name]}}'; +export const referrer = referrerImport; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js.headers b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js.headers new file mode 100644 index 0000000000..cb762eff80 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js.headers @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-utf8-with-charset-header.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-utf8-with-charset-header.js new file mode 100644 index 0000000000..c2ccab7c62 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-utf8-with-charset-header.js @@ -0,0 +1 @@ +import "../../serve-with-content-type.py?fn=external-script-utf8.js&ct=text/javascript%3Bcharset=windows-1250&dummy=6"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-utf8.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-utf8.js new file mode 100644 index 0000000000..5708a26e07 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/import-utf8.js @@ -0,0 +1 @@ +import "../../serve-with-content-type.py?fn=external-script-utf8.js&ct=text/javascript&dummy=5"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/imports-404-but-js.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/imports-404-but-js.js new file mode 100644 index 0000000000..d62e4f05be --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/imports-404-but-js.js @@ -0,0 +1 @@ +import "./404-but-js.asis"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/imports-500-but-js.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/imports-500-but-js.js new file mode 100644 index 0000000000..d62e4f05be --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/imports-500-but-js.js @@ -0,0 +1 @@ +import "./404-but-js.asis"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/imports-b-cross-origin.sub.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/imports-b-cross-origin.sub.js new file mode 100644 index 0000000000..6db57b5017 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/imports-b-cross-origin.sub.js @@ -0,0 +1 @@ +import "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/imports-b.js"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py new file mode 100644 index 0000000000..413f48d381 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/referrer-checker.py @@ -0,0 +1,6 @@ +def main(request, response): + referrer = request.headers.get(b"referer", b"") + response_headers = [(b"Content-Type", b"text/javascript"), + (b"Access-Control-Allow-Origin", b"*")] + return (200, response_headers, + b"export const referrer = '" + referrer + b"';") diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/slow-module.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/slow-module.js new file mode 100644 index 0000000000..4623ef7360 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/resources/slow-module.js @@ -0,0 +1,3 @@ +// This module is imported with pipe=trickle(d2) to make it load more slowly +// than fast-module.js +loaded.push("slow"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/script-for-event.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/script-for-event.html new file mode 100644 index 0000000000..e3b8e15b41 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/script-for-event.html @@ -0,0 +1,93 @@ +<!DOCTYPE html> +<title>Module scripts with for and event attributes</title> +<link rel="author" title="Matheus Kerschbaum" href="mailto:matjk7@gmail.com"> +<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +var expected = [ + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, +]; +var run = expected.map(function() { return false }); +</script> +<script for="wİndow" event="onload" type="module"> +run[0] = true; +</script> +<script for="window" event="onload x" type="module"> +run[1] = true; +</script> +<script for="window" event="onload(x" type="module"> +run[2] = true; +</script> +<script for="window" event="onload(x)" type="module"> +run[3] = true; +</script> +<script for="window" event="onclick" type="module"> +run[4] = true; +</script> +<script for="" event="onload" type="module"> +run[5] = true; +</script> +<script for="window" event="" type="module"> +run[6] = true; +</script> +<script for="" event="" type="module"> +run[7] = true; +</script> +<script for=" window" event="onload" type="module"> +run[8] = true; +</script> +<script for="window " event="onload" type="module"> +run[9] = true; +</script> +<script for="window" event=" onload" type="module"> +run[10] = true; +</script> +<script for="window" event="onload " type="module"> +run[11] = true; +</script> +<script for=" window " event=" onload " type="module"> +run[12] = true; +</script> +<script for=" window " event=" onload() " type="module"> +run[13] = true; +</script> +<script for="object" event="handler" type="module"> +run[14] = true; +</script> +<script event="handler" type="module"> +run[15] = true; +</script> +<script for="object" type="module"> +run[16] = true; +</script> +<script type="module"> +test(function() { + for (var i = 0; i < run.length; ++i) { + test(function() { + var script = document.querySelectorAll("script[for], script[event]")[i]; + assert_equals(run[i], expected[i], + "script for=" + format_value(script.getAttribute("for")) + + " event=" + format_value(script.getAttribute("event"))); + }, "Script " + i); + } +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/set-currentScript-on-window.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/set-currentScript-on-window.js new file mode 100644 index 0000000000..6863075bd9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/set-currentScript-on-window.js @@ -0,0 +1 @@ +window.currentScriptRecorded = document.currentScript; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/single-evaluation-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/single-evaluation-1.html new file mode 100644 index 0000000000..cc4e2d69b7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/single-evaluation-1.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<title>Single evaluation, 1</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test that a module is evaluated only once, and that 'this' is " + + "undefined (because of strict mode)."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, [undefined, "this-nested"]); + })); +</script> +<script type="module" src="this.js"></script> +<script type="module" src="this.js"></script> +<script type="module" src="this-nested.js"></script> +<script type="module" src="this.js"></script> +<script type="module" src="this-nested.js"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/single-evaluation-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/single-evaluation-2.html new file mode 100644 index 0000000000..790e2fa9c6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/single-evaluation-2.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<title>Single evaluation, 2</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.log = []; + + const test_load = async_test( + "Test that a module is evaluated only once, and that 'this' is " + + "undefined (because of strict mode)."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_array_equals(log, [undefined, "this-nested"]); + })); +</script> +<script type="module" src="this-nested.js"></script> +<script type="module" src="this-nested.js"></script> +<script type="module" src="this.js"></script> +<script type="module" src="this-nested.js"></script> +<script type="module" src="this.js"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/slow-cycle.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/slow-cycle.html new file mode 100644 index 0000000000..3a42cf9e30 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/slow-cycle.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<title>Cyclic graph with slow imports</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script type="module"> +import { loaded } from "./slow-module-graph-a.js"; + +test(() => { + assert_true(loaded); +}, "module graph with cycles load even if part of the graph loads slow"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/slow-module-graph-a.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/slow-module-graph-a.js new file mode 100644 index 0000000000..48701aa1d0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/slow-module-graph-a.js @@ -0,0 +1,3 @@ +import "./slow-module-graph-b.js"; +import "./resources/delayed-modulescript.py" +export let loaded = true; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/slow-module-graph-b.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/slow-module-graph-b.js new file mode 100644 index 0000000000..53a8f2026e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/slow-module-graph-b.js @@ -0,0 +1 @@ +import "./slow-module-graph-a.js"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/specifier-error.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/specifier-error.html new file mode 100644 index 0000000000..d07005caaa --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/specifier-error.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<title>Handling of invalid specifiers</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + setup({allow_uncaught_exception: true}); + + window.log = []; + + window.addEventListener("error", ev => log.push(ev.error)); + + const test_load = async_test( + "Test that invalid module specifier leads to TypeError on window."); + window.addEventListener("load", test_load.step_func_done(ev => { + assert_equals(log.length, 1); + assert_equals(log[0].constructor, TypeError); + })); + + function unreachable() { log.push("unexpected"); } +</script> +<script type="module" src="./bad-module-specifier.js" onerror="unreachable()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/syntaxerror-nested.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/syntaxerror-nested.js new file mode 100644 index 0000000000..de1b053c5a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/syntaxerror-nested.js @@ -0,0 +1,2 @@ +import "./syntaxerror.js"; +log.push("nested-syntaxerror"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/syntaxerror.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/syntaxerror.js new file mode 100644 index 0000000000..31a9e2cbdf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/syntaxerror.js @@ -0,0 +1,2 @@ +log.push("syntaxerror"); +%!#$@#$@#$@ diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/this-nested.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/this-nested.js new file mode 100644 index 0000000000..f204812fd1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/this-nested.js @@ -0,0 +1,2 @@ +import "./this.js"; +log.push("this-nested"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/this.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/this.js new file mode 100644 index 0000000000..996a439df0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/this.js @@ -0,0 +1 @@ +log.push(this); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw-error.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw-error.js new file mode 100644 index 0000000000..9769c84b23 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw-error.js @@ -0,0 +1,3 @@ +window.before_throwing_error = true; +throw new Error; +window.after_throwing_error = true; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw-nested.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw-nested.js new file mode 100644 index 0000000000..f1801ea366 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw-nested.js @@ -0,0 +1,2 @@ +import "./throw.js"; +log.push("throw-nested"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw.js new file mode 100644 index 0000000000..cef7918216 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw.js @@ -0,0 +1,2 @@ +log.push("throw"); +throw {foo: true} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw2.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw2.js new file mode 100644 index 0000000000..2931eec500 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/throw2.js @@ -0,0 +1,2 @@ +log.push("throw2"); +throw {bar: true} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked.any.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked.any.js new file mode 100644 index 0000000000..820f995aaf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked.any.js @@ -0,0 +1,11 @@ +promise_test(async t => { + const { checkMicrotask } = await import("./sibling-imports-not-blocked__microtask__parent.js"); + + assert_equals(checkMicrotask, "PASS"); +}, "Async modules only scheduling microtasks don't block execution of sibling modules"); + +promise_test(async t => { + const { checkTask } = await import("./sibling-imports-not-blocked__task__parent.js"); + + assert_equals(checkTask, "PASS"); +}, "Async modules scheduling tasks don't block execution of sibling modules"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__microtask__check-get-sync.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__microtask__check-get-sync.js new file mode 100644 index 0000000000..063697310a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__microtask__check-get-sync.js @@ -0,0 +1 @@ +export const { checkMicrotask } = globalThis; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__microtask__check-set-async.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__microtask__check-set-async.js new file mode 100644 index 0000000000..98930fed0b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__microtask__check-set-async.js @@ -0,0 +1,3 @@ +globalThis.checkMicrotask = "PASS"; +await 0; +globalThis.checkMicrotask = "FAIL"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__microtask__parent.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__microtask__parent.js new file mode 100644 index 0000000000..a28fcef9cb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__microtask__parent.js @@ -0,0 +1,2 @@ +import "./sibling-imports-not-blocked__microtask__check-set-async.js"; +export { checkMicrotask } from "./sibling-imports-not-blocked__microtask__check-get-sync.js"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__task__check-get-sync.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__task__check-get-sync.js new file mode 100644 index 0000000000..833acdd7ec --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__task__check-get-sync.js @@ -0,0 +1 @@ +export const { checkTask } = globalThis; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__task__check-set-async.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__task__check-set-async.js new file mode 100644 index 0000000000..0973b3c65a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__task__check-set-async.js @@ -0,0 +1,3 @@ +globalThis.checkTask = "PASS"; +await new Promise(r => setTimeout(r, 0)); +globalThis.checkTask = "FAIL"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__task__parent.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__task__parent.js new file mode 100644 index 0000000000..56ee5134d7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/top-level-await/sibling-imports-not-blocked__task__parent.js @@ -0,0 +1,2 @@ +import "./sibling-imports-not-blocked__task__check-set-async.js"; +export { checkTask } from "./sibling-imports-not-blocked__task__check-get-sync.js"; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/type.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/type.html new file mode 100644 index 0000000000..5817ae4d43 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/module/type.html @@ -0,0 +1,24 @@ +<!DOCTYPE html> +<title>Type attribute of module scripts</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +window.t1 = async_test('type="module"'); +window.t2 = async_test('type="MODULE"'); +window.t3 = async_test('type="Module"'); +window.t4 = async_test('type="module "'); +window.t5 = async_test('type=" module"'); +</script> +<script type="module">window.t1.done();</script> +<script type="MODULE">window.t2.done();</script> +<script type="Module">window.t3.done();</script> +<script type="module ">window.t4.unreached_func('Unexpectedly evaluated');</script> +<script type=" module">window.t5.unreached_func('Unexpectedly evaluated');</script> +<script type="module"> +window.t1.unreached_func('Unexpectedly not evaluated')(); +window.t2.unreached_func('Unexpectedly not evaluated')(); +window.t3.unreached_func('Unexpectedly not evaluated')(); +window.t4.done(); +window.t5.done(); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents-during-evaluation.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents-during-evaluation.html new file mode 100644 index 0000000000..e4cd887c61 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents-during-evaluation.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Moving script elements between documents during evaluation</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<script id="outerScript"> +"use strict"; + +async_test(t => { + const outerScript = document.querySelector('#outerScript'); + assert_equals(document.currentScript, outerScript); + + const innerScript = document.createElement('script'); + window.innerScript = innerScript; + + window.innerScriptEvaluated = false; + window.anotherDocument = null; + + innerScript.innerText = ` + window.innerScriptEvaluated = true; + const innerScript = window.innerScript; + assert_equals(document.currentScript, innerScript, + '[1] Before move: currentScript of source Document'); + assert_equals(innerScript.ownerDocument, document, + '[1] Before move: ownerDocument'); + + window.anotherDocument = document.implementation.createHTMLDocument(); + window.anotherDocument.body.appendChild(innerScript); + + assert_equals(innerScript.ownerDocument, anotherDocument, + '[2] Just after move: ownerDocument'); + assert_equals(document.currentScript, innerScript, + '[2] Just after move: currentScript of source Document'); + assert_equals(anotherDocument.currentScript, null, + '[2] Just after move: currentScript of destination Document'); + `; + + document.body.appendChild(innerScript); + assert_true(window.innerScriptEvaluated, + 'Inner script should be evaluated synchronously'); + + assert_equals(document.currentScript, outerScript, + '[3] After inner script: currentScript of source Document'); + assert_equals(window.anotherDocument.currentScript, null, + '[3] After inner script: currentScript of destination Document'); + + t.step_timeout(() => { + assert_equals(document.currentScript, null, + '[4] After outer script: currentScript of source Document'); + assert_equals(anotherDocument.currentScript, null, + '[4] After outer script: currentScript of destination Document'); + t.done(); + }, 0); +}, 'Script moved between documents during evaluation'); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/README.md b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/README.md new file mode 100644 index 0000000000..f95e0a63a3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/README.md @@ -0,0 +1,16 @@ +The tests in this directory are for script elements moved between documents. + +Use + +``` +$ tools/generate.py +``` + +to generate test HTML files (except for tests in subdirectories). + +Background: + +- https://www.w3.org/Bugs/Public/show_bug.cgi?id=11323 +- https://github.com/whatwg/html/issues/2137 +- https://github.com/whatwg/html/issues/2469 +- https://github.com/whatwg/html/pull/2673 diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-fetch-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-fetch-error-external-classic.html new file mode 100644 index 0000000000..2b84ae8088 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-fetch-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "createHTMLDocument", "fetch-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-fetch-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-fetch-error-external-module.html new file mode 100644 index 0000000000..09ee1490c1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-fetch-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "createHTMLDocument", "fetch-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-parse-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-parse-error-external-classic.html new file mode 100644 index 0000000000..477abd32cf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-parse-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "createHTMLDocument", "parse-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-parse-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-parse-error-external-module.html new file mode 100644 index 0000000000..9da2276408 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-parse-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "createHTMLDocument", "parse-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-success-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-success-external-classic.html new file mode 100644 index 0000000000..bc4deb6f17 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-success-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "createHTMLDocument", "success", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-success-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-success-external-module.html new file mode 100644 index 0000000000..ff76954f9d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-createHTMLDocument-success-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "createHTMLDocument", "success", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-fetch-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-fetch-error-external-classic.html new file mode 100644 index 0000000000..768120e9d8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-fetch-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "iframe", "fetch-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-fetch-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-fetch-error-external-module.html new file mode 100644 index 0000000000..50dd80662d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-fetch-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "iframe", "fetch-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-parse-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-parse-error-external-classic.html new file mode 100644 index 0000000000..981a068230 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-parse-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "iframe", "parse-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-parse-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-parse-error-external-module.html new file mode 100644 index 0000000000..6debb4189e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-parse-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "iframe", "parse-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-parse-error-inline-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-parse-error-inline-classic.html new file mode 100644 index 0000000000..53389f20db --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-parse-error-inline-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "iframe", "parse-error", "inline", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-success-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-success-external-classic.html new file mode 100644 index 0000000000..9c4a12226a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-success-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "iframe", "success", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-success-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-success-external-module.html new file mode 100644 index 0000000000..0a0490cfc1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-success-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "iframe", "success", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-success-inline-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-success-inline-classic.html new file mode 100644 index 0000000000..932825709f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/after-prepare-iframe-success-inline-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("after-prepare", "iframe", "success", "inline", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-fetch-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-fetch-error-external-classic.html new file mode 100644 index 0000000000..444382ac20 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-fetch-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "fetch-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-fetch-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-fetch-error-external-module.html new file mode 100644 index 0000000000..e1a1f7c08f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-fetch-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "fetch-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-external-classic.html new file mode 100644 index 0000000000..6bb5ebddbd --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "parse-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-external-module.html new file mode 100644 index 0000000000..10a6549f62 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "parse-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-inline-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-inline-classic.html new file mode 100644 index 0000000000..28bd935995 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-inline-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "parse-error", "inline", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-inline-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-inline-module.html new file mode 100644 index 0000000000..e665a75629 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-parse-error-inline-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "parse-error", "inline", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-empty-src-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-empty-src-classic.html new file mode 100644 index 0000000000..8ee0dd1de1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-empty-src-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "success", "empty-src", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-empty-src-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-empty-src-module.html new file mode 100644 index 0000000000..4791149c57 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-empty-src-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "success", "empty-src", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-external-classic.html new file mode 100644 index 0000000000..3a3aceaf26 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "success", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-external-module.html new file mode 100644 index 0000000000..c15b4fc77f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "success", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-inline-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-inline-classic.html new file mode 100644 index 0000000000..576f4d4684 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-inline-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "success", "inline", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-inline-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-inline-module.html new file mode 100644 index 0000000000..c84d61c89a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-createHTMLDocument-success-inline-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "createHTMLDocument", "success", "inline", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-fetch-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-fetch-error-external-classic.html new file mode 100644 index 0000000000..febf6fcc55 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-fetch-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "fetch-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-fetch-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-fetch-error-external-module.html new file mode 100644 index 0000000000..f936260b8c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-fetch-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "fetch-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-external-classic.html new file mode 100644 index 0000000000..870c900abf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "parse-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-external-module.html new file mode 100644 index 0000000000..fb44a89df1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "parse-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-inline-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-inline-classic.html new file mode 100644 index 0000000000..986e4fa396 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-inline-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "parse-error", "inline", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-inline-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-inline-module.html new file mode 100644 index 0000000000..3a3fc38479 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-parse-error-inline-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "parse-error", "inline", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-empty-src-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-empty-src-classic.html new file mode 100644 index 0000000000..4f03a94358 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-empty-src-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "success", "empty-src", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-empty-src-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-empty-src-module.html new file mode 100644 index 0000000000..a7bd42fd32 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-empty-src-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "success", "empty-src", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-external-classic.html new file mode 100644 index 0000000000..08a8ac4afa --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "success", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-external-module.html new file mode 100644 index 0000000000..b8c3f79fea --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "success", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-inline-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-inline-classic.html new file mode 100644 index 0000000000..b639f6109d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-inline-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "success", "inline", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-inline-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-inline-module.html new file mode 100644 index 0000000000..616e46310f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/before-prepare-iframe-success-inline-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("before-prepare", "iframe", "success", "inline", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-fetch-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-fetch-error-external-classic.html new file mode 100644 index 0000000000..745c62d898 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-fetch-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "createHTMLDocument", "fetch-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-fetch-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-fetch-error-external-module.html new file mode 100644 index 0000000000..f6353a05fc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-fetch-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "createHTMLDocument", "fetch-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-parse-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-parse-error-external-classic.html new file mode 100644 index 0000000000..21099c3ff9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-parse-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "createHTMLDocument", "parse-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-parse-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-parse-error-external-module.html new file mode 100644 index 0000000000..2eb153acfe --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-parse-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "createHTMLDocument", "parse-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-success-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-success-external-classic.html new file mode 100644 index 0000000000..88821826ed --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-success-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "createHTMLDocument", "success", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-success-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-success-external-module.html new file mode 100644 index 0000000000..f2a9d95741 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-createHTMLDocument-success-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "createHTMLDocument", "success", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-fetch-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-fetch-error-external-classic.html new file mode 100644 index 0000000000..d96bfe0d50 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-fetch-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "iframe", "fetch-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-fetch-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-fetch-error-external-module.html new file mode 100644 index 0000000000..7e71bfbe15 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-fetch-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "iframe", "fetch-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-parse-error-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-parse-error-external-classic.html new file mode 100644 index 0000000000..757c879897 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-parse-error-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "iframe", "parse-error", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-parse-error-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-parse-error-external-module.html new file mode 100644 index 0000000000..6ec6c5970e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-parse-error-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "iframe", "parse-error", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-parse-error-inline-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-parse-error-inline-classic.html new file mode 100644 index 0000000000..c0b0f9d404 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-parse-error-inline-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "iframe", "parse-error", "inline", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-external-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-external-classic.html new file mode 100644 index 0000000000..7955dbce62 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-external-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "iframe", "success", "external", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-external-module.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-external-module.html new file mode 100644 index 0000000000..af17eb01f7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-external-module.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "iframe", "success", "external", "module"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-inline-classic.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-inline-classic.html new file mode 100644 index 0000000000..8a44e2feaf --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/move-back-iframe-success-inline-classic.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("move-back", "iframe", "success", "inline", "classic"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/README.md b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/README.md new file mode 100644 index 0000000000..dcf5597e2d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/README.md @@ -0,0 +1,6 @@ +The tests in this directory checks side effects (other than script +evaluation/event firing, which is covered by the tests in the parent directory) +caused by scripts moved between Documents. + +The tests assume that script loading is not canceled when moved between +documents (which is not explicitly specified as of Jan 2022). diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/delay-load-event-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/delay-load-event-1.html new file mode 100644 index 0000000000..c5812765eb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/delay-load-event-1.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="helper.js"></script> + +<body> +<script> +runDelayEventTest('Script elements (parser-blocking)'); +</script> + +<script id="to-be-moved" src="../../resources/throw.js?pipe=trickle(d3)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/delay-load-event-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/delay-load-event-2.html new file mode 100644 index 0000000000..916673894d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/delay-load-event-2.html @@ -0,0 +1,15 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="helper.js"></script> + +<body> +<script> +runDelayEventTest('Script elements (async)'); + +const script = document.createElement('script'); +script.setAttribute('id', 'to-be-moved'); +script.setAttribute('src', '../../resources/throw.js?pipe=trickle(d3)'); +document.body.appendChild(script); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/delay-load-event-iframe.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/delay-load-event-iframe.html new file mode 100644 index 0000000000..efec7657c3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/delay-load-event-iframe.html @@ -0,0 +1,4 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<body onload="parent.onloadIframe()"> +<script src="../../resources/throw.js?pipe=trickle(d2)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/helper.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/helper.js new file mode 100644 index 0000000000..cb5f45eb0d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/helper.js @@ -0,0 +1,31 @@ +function runDelayEventTest(description) { + const t_original = async_test(description + + ' still delay the load event in the original Document after move'); + const t_new = async_test(description + + ' does not delay the load event in the new Document after move'); + const iframe = document.createElement('iframe'); + iframe.setAttribute('src', 'delay-load-event-iframe.html'); + const start_time = performance.now(); + document.body.appendChild(iframe); + + window.onload = t_original.step_func_done(() => { + // The `#to-be-moved` script should delay the load event until it is loaded + // (i.e. 3 seconds), not just until it is moved out to another Document + // (i.e. 1 second). Here we expect the delay should be at least 2 seconds, + // as the latency can be slightly less than 3 seconds due to preloading. + assert_greater_than(performance.now() - start_time, 2000, + 'Load event should be delayed until script is loaded'); + }); + + window.onloadIframe = t_new.step_func_done(() => { + // The iframe's load event is fired after 2 seconds of its subresource + // loading, and shouldn't wait for the `#to-be-moved` script. + assert_less_than(performance.now() - start_time, 3000, + 'Load event should not be delayed until moved script is loaded'); + }); + + t_original.step_timeout(() => { + const script = document.querySelector('#to-be-moved'); + iframe.contentDocument.body.appendChild(script); + }, 1000); +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/in-order.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/in-order.html new file mode 100644 index 0000000000..6a3e2b54a7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/in-order.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="help" href="https://html.spec.whatwg.org/C/#list-of-scripts-that-will-execute-in-order-as-soon-as-possible"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="helper.js"></script> +<body> +<script> +const t = async_test('Script elements (in-order) still block subsequent in-order scripts in the original Document after moved to another Document'); +const start_time = performance.now(); +const iframe = document.createElement('iframe'); +document.body.appendChild(iframe); + +const onScript2Evaluated = t.step_func_done(() => { + // `script1` should remain the + // #list-of-scripts-that-will-execute-in-order-as-soon-as-possible of the + // original Document and thus blocks `script2` evaluation until it is loaded. + assert_greater_than(performance.now() - start_time, 2000, + 'In-order scripts should block subsequent in-order scripts'); +}); + +const script1 = document.createElement('script'); +script1.async = false; +script1.setAttribute('src', '../../resources/throw.js?pipe=trickle(d2)'); +document.body.appendChild(script1); + +const script2 = document.createElement('script'); +script2.async = false; +script2.setAttribute('src', 'data:text/javascript,onScript2Evaluated()'); +document.body.appendChild(script2); + +t.step_timeout(() => { + iframe.contentDocument.body.appendChild(script1); +}, 1000); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/parser-blocking.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/parser-blocking.html new file mode 100644 index 0000000000..9edde13736 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/parser-blocking.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="help" href="https://html.spec.whatwg.org/C/#pending-parsing-blocking-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="helper.js"></script> +<body> +<script> +const t = async_test('Script elements (parser-blocking) still block the parser in the original Document after moved to another Document'); +const start_time = performance.now(); +const iframe = document.createElement('iframe'); +document.body.appendChild(iframe); + +t.step_timeout(() => { + const script = document.querySelector('#to-be-moved'); + iframe.contentDocument.body.appendChild(script); +}, 1000); + +let syncScriptEvaluated = false; + +const onSyncScript = t.step_func(() => { + syncScriptEvaluated = true; + + // The `#to-be-moved` script should block the parser and thus the sync + // script after `#to-be-moved` should be delayed until `#to-be-moved` is + // loaded (i.e. 3 seconds). + // Here we expect the delay should be at least 2 seconds, + // as the latency can be slightly less than 3 seconds due to preloading. + assert_greater_than(performance.now() - start_time, 2000, + 'Parser should be blocked until script is loaded'); +}); + +document.addEventListener('DOMContentLoaded', t.step_func_done(() => { + assert_true(syncScriptEvaluated, + 'sync script should be evaluated before DOMContentLoaded'); + assert_greater_than(performance.now() - start_time, 2000, + 'DOMContentLoaded event should be delayed until script is loaded'); +})); +</script> +<script id="to-be-moved" src="../../resources/throw.js?pipe=trickle(d3)"></script> +<script src="data:text/javascript,onSyncScript()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/resources/moving-between-documents-helper.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/resources/moving-between-documents-helper.js new file mode 100644 index 0000000000..de4af6ac10 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/resources/moving-between-documents-helper.js @@ -0,0 +1,214 @@ +"use strict"; + +function createDocument(documentType, result, inlineOrExternal, type, hasBlockingStylesheet) { + return new Promise((resolve, reject) => { + const iframe = document.createElement("iframe"); + iframe.src = + "resources/moving-between-documents-iframe.py" + + "?result=" + result + + "&inlineOrExternal=" + inlineOrExternal + + "&type=" + type + + "&hasBlockingStylesheet=" + hasBlockingStylesheet + + "&cache=" + Math.random(); + // As blocking stylesheets delays Document load events, we use + // DOMContentLoaded here. + // After that point, we expect iframe.contentDocument exists + // while still waiting for blocking stylesheet loading. + document.body.appendChild(iframe); + + window.addEventListener('message', (event) => { + if (documentType === "iframe") { + resolve([iframe.contentWindow, iframe.contentDocument]); + } else if (documentType === "createHTMLDocument") { + resolve([ + iframe.contentWindow, + iframe.contentDocument.implementation.createHTMLDocument("")]); + } else { + reject(new Error("Invalid document type: " + documentType)); + } + }, {once: true}); + }); +} + +window.didExecute = undefined; + +// For a script, there are three associated Documents that can +// potentially different: +// +// [1] script's parser document +// https://html.spec.whatwg.org/C/#parser-document +// +// [2] script's preparation-time document +// https://html.spec.whatwg.org/C/#preparation-time-document +// == script's node document at the beginning of #prepare-a-script +// +// [3] script's node document at the beginning of +// #execute-the-script-block +// +// This helper is for tests where [1]/[2]/[3] are different. + +// In the spec, scripts are executed only if [1]/[2]/[3] are all the same +// (or [1] is null and [2]==[3]). +// +// A check for [1]==[2] is in #prepare-a-script and +// a check for [1]==[3] is in #execute-the-script-block, +// but these are under debate: https://github.com/whatwg/html/issues/2137 +// +// A check for [2]==[3] is in #execute-the-script-block, which is added by +// https://github.com/whatwg/html/pull/2673 + +// timing: +// "before-prepare": +// A <script> is moved during parsing before #prepare-a-script. +// [1] != [2] == [3] +// +// "after-prepare": +// A <script> is moved after parsing/#prepare-a-script but +// before #execute-the-script-block. +// [1] == [2] != [3] +// +// To move such scripts, #has-a-style-sheet-that-is-blocking-scripts +// is utilized to block inline scripts after #prepare-a-script. +// Note: this is a corner case in the spec which might be removed +// from the spec in the future, e.g. +// https://github.com/whatwg/html/issues/1349 +// https://github.com/chrishtr/rendering/blob/master/stylesheet-loading-proposal.md +// +// TODO(domfarolino): Remove the "parsing but moved back" tests, because if a +// <script> is moved before #prepare-a-script, per spec it should never make +// it to #execute-the-script-block. If an implementation does not implement +// the check in #prepare-a-script, then it will fail the "before-prepare" +// tests, so these are not necessary. +// "parsing but moved back" +// A <script> is moved before #prepare-a-script, but moved back again +// to the original Document after #prepare-a-script. +// [1] == [3] != [2] +// +// destType: "iframe" or "createHTMLDocument". +// result: "fetch-error", "parse-error", or "success". +// inlineOrExternal: "inline" or "external" or "empty-src". +// type: "classic" or "module". +async function runTest(timing, destType, result, inlineOrExternal, type) { + const description = + `Move ${result} ${inlineOrExternal} ${type} script ` + + `to ${destType} ${timing}`; + + const t = async_test("Eval: " + description); + const tScriptLoadEvent = async_test("<script> load: " + description); + const tScriptErrorEvent = async_test("<script> error: " + description); + const tWindowErrorEvent = async_test("window error: " + description); + + // If scripts should be moved after #prepare-a-script before + // #execute-the-script-block, we add a style sheet that is + // blocking scripts. + const hasBlockingStylesheet = + timing === "after-prepare" || timing === "move-back"; + + const [sourceWindow, sourceDocument] = await createDocument( + "iframe", result, inlineOrExternal, type, hasBlockingStylesheet); + + // Due to https://crbug.com/1034176, Chromium needs + // blocking stylesheets also in the destination Documents. + const [destWindow, destDocument] = await createDocument( + destType, null, null, null, hasBlockingStylesheet); + + const scriptOnLoad = + tScriptLoadEvent.unreached_func("Script load event fired unexpectedly"); + const scriptOnError = (event) => { + // For Firefox: Prevent window.onerror is fired due to propagation + // from <script>'s error event. + event.stopPropagation(); + + tScriptErrorEvent.unreached_func("Script error evennt fired unexpectedly")(); + }; + + sourceWindow.didExecute = false; + sourceWindow.t = t; + sourceWindow.scriptOnLoad = scriptOnLoad; + sourceWindow.scriptOnError = scriptOnError; + sourceWindow.onerror = tWindowErrorEvent.unreached_func( + "Window error event shouldn't fired on source window"); + sourceWindow.readyToEvaluate = false; + + destWindow.didExecute = false; + destWindow.t = t; + destWindow.scriptOnLoad = scriptOnLoad; + destWindow.scriptOnError = scriptOnError; + destWindow.onerror = tWindowErrorEvent.unreached_func( + "Window error event shouldn't fired on destination window"); + destWindow.readyToEvaluate = false; + + // t=0 sec: Move between documents before #prepare-a-script. + // At this time, the script element is not yet inserted to the DOM. + if (timing === "before-prepare" || timing === "move-back") { + destDocument.body.appendChild( + sourceDocument.querySelector("streaming-element")); + } + if (timing === "before-prepare") { + sourceWindow.readyToEvaluate = true; + destWindow.readyToEvaluate = true; + } + + // t=1 sec: the script element is inserted to the DOM, i.e. + // #prepare-a-script is triggered (see monving-between-documents-iframe.py). + // In the case of `before-prepare`, the script can be evaluated. + // In other cases, the script evaluation is blocked by a style sheet. + await new Promise(resolve => step_timeout(resolve, 2000)); + + // t=2 sec: Move between documents after #prepare-a-script. + if (timing === "after-prepare") { + // At this point, the script hasn't been moved yet, so we'll move it for the + // first time, after #prepare-a-script, but before #execute-the-script-block. + destDocument.body.appendChild( + sourceDocument.querySelector("streaming-element")); + } else if (timing === "move-back") { + // At this point the script has already been moved to the destination block + // before #prepare-a-script, so we'll move it back to the source document + // before #execute-the-script-block. + sourceDocument.body.appendChild( + destDocument.querySelector("streaming-element")); + } + sourceWindow.readyToEvaluate = true; + destWindow.readyToEvaluate = true; + + // t=3 or 5 sec: Blocking stylesheet and external script are loaded, + // and thus script evaulation is unblocked. + + // Note: scripts are expected to be loaded at t=3, because the fetch + // is started by #prepare-a-script at t=1, and the script's delay is + // 2 seconds. However in Chromium, due to preload scanner, the script + // loading might take 4 seconds, because the first request by preload + // scanner of the source Document takes 2 seconds (between t=1 and t=3) + // which blocks the second request by #prepare-a-script that takes + // another 2 seconds (between t=3 and t=5). + + // t=6 sec: After all possible script evaluation points, test whether + // the script/events were evaluated/fired or not. + // As we have concurrent tests, a single global step_timeout() is + // used instead of multiple `t.step_timeout()` etc., + // to avoid potential race conditions between `t.step_timeout()`s. + return new Promise(resolve => { + step_timeout(() => { + tWindowErrorEvent.done(); + tScriptLoadEvent.done(); + tScriptErrorEvent.done(); + + t.step_func_done(() => { + assert_false(sourceWindow.didExecute, + "The script must not have executed in source window"); + assert_false(destWindow.didExecute, + "The script must not have executed in destination window"); + })(); + resolve(); + }, 4000); + }); +} + +async_test(t => { + t.step_timeout(() => { + assert_equals(window.didExecute, undefined, + "The script must not have executed in the top-level window"); + t.done(); + }, + 4000); +}, "Sanity check around top-level Window"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/resources/moving-between-documents-iframe.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/resources/moving-between-documents-iframe.py new file mode 100644 index 0000000000..dbcfe9b8d0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/resources/moving-between-documents-iframe.py @@ -0,0 +1,102 @@ +import random +import time + +from wptserve.utils import isomorphic_decode + + +""" +This script serves +""" + +def main(request, response): + inlineOrExternal = request.GET.first(b"inlineOrExternal", b"null") + hasBlockingStylesheet = request.GET.first(b"hasBlockingStylesheet", b"true") == b"true" + result = request.GET.first(b"result", b"success") + type = u"text/javascript" if request.GET.first(b"type", b"classic") == b"classic" else u"module" + + response.headers.set(b"Content-Type", b"text/html; charset=utf-8") + response.headers.set(b"Transfer-Encoding", b"chunked") + response.write_status_headers() + + # Step 1: Start parsing. + body = u"""<!DOCTYPE html> + <head> + <script> + parent.postMessage("fox", "*"); + </script> + """ + + if hasBlockingStylesheet: + body += u""" + <link rel="stylesheet" href="slow-flag-setter.py?result=css&cache=%f"> + """ % random.random() + + body += u""" + </head> + <body> + """ + + if inlineOrExternal == b"inline" or inlineOrExternal == b"external" or inlineOrExternal == b"empty-src": + body += u""" + <streaming-element> + """ + + # Trigger DOM processing + body += u"A" * 100000 + + response.writer.write(u"%x\r\n" % len(body)) + response.writer.write(body) + response.writer.write(u"\r\n") + + body = u"" + + if inlineOrExternal == b"inline": + time.sleep(1) + body += u""" + <script id="s1" type="%s" + onload="scriptOnLoad()" + onerror="scriptOnError(event)"> + if (!window.readyToEvaluate) { + window.didExecute = "executed too early"; + } else { + window.didExecute = "executed"; + } + """ % type + if result == b"parse-error": + body += u"1=2 parse error\n" + + body += u""" + </script> + </streaming-element> + """ + elif inlineOrExternal == b"external": + time.sleep(1) + body += u""" + <script id="s1" type="%s" + src="slow-flag-setter.py?result=%s&cache=%s" + onload="scriptOnLoad()" + onerror="scriptOnError(event)"></script> + </streaming-element> + """ % (type, isomorphic_decode(result), random.random()) + elif inlineOrExternal == b"empty-src": + time.sleep(1) + body += u""" + <script id="s1" type="%s" + src="" + onload="scriptOnLoad()" + onerror="scriptOnError(event)"></script> + </streaming-element> + """ % (type,) + + # // if readyToEvaluate is false, the script is probably + # // wasn't blocked by stylesheets as expected. + + # Trigger DOM processing + body += u"B" * 100000 + + response.writer.write(u"%x\r\n" % len(body)) + response.writer.write(body) + response.writer.write(u"\r\n") + + response.writer.write(u"0\r\n") + response.writer.write(u"\r\n") diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/resources/slow-flag-setter.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/resources/slow-flag-setter.py new file mode 100644 index 0000000000..20d7ed4bd0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/resources/slow-flag-setter.py @@ -0,0 +1,29 @@ + +import time + +def main(request, response): + headers = [(b"Content-Type", b"text/javascript")] + + result = request.GET.first(b"result", b"success") + if result == b"css": + time.sleep(3) + headers = [(b"Content-Type", b"text/css")] + body = u"" + else: + time.sleep(2) + + body = u""" + fetch('exec'); + console.log('exec'); + if (!window.readyToEvaluate) { + window.didExecute = "executed too early"; + } else { + window.didExecute = "executed"; + } + """ + if result == b"parse-error": + body = u"1=2 parse error;" + if result == b"fetch-error": + return 404, [(b'Content-Type', b'text/plain')], u"""window.didExecute = "fetch error";""" + + return headers, body diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/tools/generate.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/tools/generate.py new file mode 100644 index 0000000000..80a655e821 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/moving-between-documents/tools/generate.py @@ -0,0 +1,61 @@ +template = '''<!DOCTYPE html> +<meta charset="utf-8"> +<meta name="timeout" content="long"> +<title>Moving script elements between documents</title> +<!-- This is generated by tools/generate.py. Do not manually edit. --> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#execute-the-script-block"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/moving-between-documents-helper.js"></script> + +<body> +<script> +runTest("%s", "%s", "%s", "%s", "%s"); +</script> +''' + +n = 0 +for timing in ["before-prepare", "after-prepare", "move-back"]: + for destType in ["iframe", "createHTMLDocument"]: + for inlineOrExternal in ["inline", "external", "empty-src"]: + for result in ["fetch-error", "parse-error", "success"]: + for type in ["classic", "module"]: + # The |inlineOrExternal| keyword creates a certain kind of script, + # and the |result| keyword can influence the generated script in + # different ways i.e., giving the script a parse-error, or creating + # a script that fails to load. When we're creating an inline script, + # it doesn't make sense to test the fetch-error case, so we ignore + # this combination, as the server will not react to it in any + # meaningful way. + if inlineOrExternal == "inline" and result == "fetch-error": + continue + + if inlineOrExternal == "empty-src": + # The "empty-src" tests aim to exercise #prepare-a-script step 26 + # substep 2, where the <script> has a src attribute that is empty: + # "If src is the empty string, queue a task to fire an event named + # error at the element, and return." + # Therefore, the server will generate a script that does not have a + # "parse-error" or "fetch-error", so we can ignore these combinations. + if result != "success": + continue + + # The "empty-src" tests check that the parser document <=> node document + # check is implemented correctly in #prepare-a-script. Therefore we're + # only interested in tests that move the <script> before #prepare-a-script. + if timing != "before-prepare": + continue + + # The current test helper uses + # #has-a-style-sheet-that-is-blocking-scripts to block script + # evaluation after #prepare-a-script, but in some cases this + # doesn't work: + # - inline scripts to createHTMLDocument + if timing != "before-prepare" and destType == "createHTMLDocument" and inlineOrExternal == "inline": + continue + # - module inline scripts https://github.com/whatwg/html/issues/3890 + if timing != "before-prepare" and inlineOrExternal == "inline" and type == "module": + continue + + with open('%s-%s-%s-%s-%s.html' % (timing, destType, result, inlineOrExternal, type), 'w') as f: + f.write(template % (timing, destType, result, inlineOrExternal, type)) diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/muted-errors-iframe.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/muted-errors-iframe.html new file mode 100644 index 0000000000..255e79e191 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/muted-errors-iframe.html @@ -0,0 +1,2 @@ +<!DOCTYPE html> +<script src="cacheable-script-throw.py?iframe"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/muted-errors.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/muted-errors.sub.html new file mode 100644 index 0000000000..61643c5f08 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/muted-errors.sub.html @@ -0,0 +1,85 @@ +<!DOCTYPE html> +<title>Muted Errors</title> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +// https://html.spec.whatwg.org/multipage/webappapis.html#report-the-error +// If script's muted errors is true, then set message to "Script error.", +// urlString to the empty string, line and col to 0, and errorValue to null. + setup({allow_uncaught_exception: true}); + + window.log = []; + window.addEventListener("error", ev => log.push(ev)); + + function check(shouldBeMuted) { + assert_equals(log.length, 1); + var ev = log[0]; + log = []; + if (shouldBeMuted) { + assert_equals(ev.message, "Script error."); + assert_equals(ev.error, null, 'error'); + assert_equals(ev.filename, "", 'filename'); + assert_equals(ev.lineno, 0, 'lineno'); + assert_equals(ev.colno, 0, 'colno'); + } else { + assert_not_equals(ev.message, "Script error."); + assert_not_equals(ev.error, null); + } + } + + var test1 = async_test("Errors for same-origin script shouldn't be muted"); + var check1 = test1.step_func_done(() => check(false)); + + var test2 = async_test("Errors for cross-origin script should be muted"); + var check2 = test2.step_func_done(() => check(true)); + + var test3 = async_test("Errors for cross-origin script should be muted " + + "even if the script is once loaded as same-origin"); + function step3() { + var script = document.createElement('script'); + script.setAttribute('src', "//{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/cacheable-script-throw.py?iframe"); + script.onerror = test3.unreached_func(); + script.onload = test3.step_func_done(() => check(true)); + document.body.appendChild(script); + } + + var test4 = async_test("Errors for same-origin scripts redirected to a " + + "cross-origin url and redirected back to " + + "same-origin should be muted"); + var check4 = test4.step_func_done(() => check(true)); + + var test5 = async_test("Errors for cross-origin scripts redirected to a " + + "same-origin url should be muted"); + var check5 = test5.step_func_done(() => check(true)); + + const test6 = async_test("Non-synthetic errors for same-origin scripts redirected to a " + + "cross-origin URL and redirected back to same-origin should be " + + "muted"); + const check6 = test6.step_func_done(() => check(true)); + + const test7 = async_test("Syntax error for same-origin script redirected to a " + + "cross-origin URL and redirected back to same-origin should be " + + "muted"); + const check7 = test7.step_func_done(() => check(true)); + + function unreachable() { log.push("unexpected"); } +</script> +<script src="cacheable-script-throw.py" onerror="test1.unreached_func()()" onload="check1()"></script> +<script src="//{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/cacheable-script-throw.py" + onerror="test2.unreached_func()()" onload="check2()"></script> +<iframe src="//{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/muted-errors-iframe.html" + onerror="test3.unreached_func()()" onload="step3()"></iframe> +<script src="/fetch/api/resources/redirect.py?location= +//{{domains[www2]}}:{{ports[http][0]}}/fetch/api/resources/redirect.py?location= +//{{host}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/cacheable-script-throw.py?same-cross-same" +onerror="test4.unreached_func()()" onload="check4()"></script> +<script src="//{{domains[www2]}}:{{ports[http][0]}}/fetch/api/resources/redirect.py?location= +//{{host}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/cacheable-script-throw.py?cross-same" +onerror="test5.unreached_func()()" onload="check5()"></script> +<script src="//{{domains[www2]}}:{{ports[http][0]}}/fetch/api/resources/redirect.py?location= +//{{host}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/resources/throw.js" +onerror="test6.unreached_func()()" onload="check6()"></script> +<script src="//{{domains[www2]}}:{{ports[http][0]}}/fetch/api/resources/redirect.py?location= +//{{host}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/resources/syntax-error.js" +onerror="test7.unreached_func()()" onload="check7()"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-reflect.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-reflect.html new file mode 100644 index 0000000000..d6a850f58f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-reflect.html @@ -0,0 +1,75 @@ +<!DOCTYPE html> +<html> +<head> +<title>noModule IDL attribute must reflect nomodule content attribute</title> +<link rel="author" title="Yusuke Suzuki" href="mailto:utatane.tea@gmail.com"> +<link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script id="classicWithoutNomodule"></script> +<script id="classicWithNomodule" nomodule></script> +<script id="moduleWithoutNomodule" type=module></script> +<script id="moduleWithNomodule" type=module nomodule></script> +<script> + +test(() => { + assert_false(document.getElementById('classicWithoutNomodule').noModule); +}, 'noModule IDL attribute on a parser created classic script element without nomodule content attribute'); + +test(() => { + assert_true(document.getElementById('classicWithNomodule').noModule); +}, 'noModule IDL attribute on a parser created classic script element with nomodule content attribute'); + +test(() => { + assert_false(document.getElementById('moduleWithoutNomodule').noModule); +}, 'noModule IDL attribute on a parser created module script element without nomodule content attribute'); + +test(() => { + assert_true(document.getElementById('moduleWithNomodule').noModule); +}, 'noModule IDL attribute on a parser created module script element with nomodule content attribute'); + + +test(() => { + const script = document.createElement('script'); + assert_false(script.noModule); +}, 'noModule IDL attribute on a dynamically created script element without nomodule content attribute'); + +test(() => { + const script = document.createElement('script'); + script.setAttribute('nomodule', 'nomodule'); + assert_true(script.noModule); +}, 'noModule IDL attribute on a dynamically created script element after nomodule content attribute is set to "nomodule"'); + +test(() => { + const script = document.createElement('script'); + script.setAttribute('nomodule', ''); + assert_true(script.noModule); +}, 'noModule IDL attribute on a dynamically created script element after nomodule content attribute is set to ""'); + +test(() => { + const script = document.createElement('script'); + script.setAttribute('nomodule', 'nomodule'); + assert_true(script.noModule); + script.removeAttribute('nomodule'); + assert_false(script.noModule); +}, 'noModule IDL attribute on a dynamically created script element after nomodule content attribute had been removed'); + +test(() => { + const script = document.createElement('script'); + assert_false(script.hasAttribute('nomodule')); + script.noModule = true; + assert_true(script.hasAttribute('nomodule')); +}, 'noModule IDL attribute must add nomodule content attribute on setting to true'); + +test(() => { + const script = document.createElement('script'); + script.setAttribute('nomodule', 'nomodule'); + script.noModule = false; + assert_false(script.hasAttribute('nomodule')); +}, 'noModule IDL attribute must remove nomodule content attribute on setting to false'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-async-classic-script.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-async-classic-script.html new file mode 100644 index 0000000000..25de796830 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-async-classic-script.html @@ -0,0 +1,63 @@ +<!DOCTYPE html> +<html> +<head> +<title>External classic scripts with nomodule content attribute must not run</title> +<link rel="author" title="Yusuke Suzuki" href="mailto:utatane.tea@gmail.com"> +<link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<!-- Load this script synchronously to ensure test cases below can load it in 200ms --> +<script src="resources/set-script-executed.js"></script> +</head> +<body> +<script> +let supportsNoModule = "noModule" in document.getElementsByTagName("script")[0]; + +waitForLoadEvent = new Promise((resolve) => { + window.onload = resolve; +}); + +promise_test(() => { + window.executed = false; + let loaded = false; + let errored = false; + + let script = document.createElement('script'); + + script.src = './resources/set-script-executed.js'; + script.onload = () => loaded = true; + script.onerror = () => errored = true; + script.noModule = false; + document.body.appendChild(script); + + return waitForLoadEvent.then(() => { + assert_true(supportsNoModule); + assert_true(executed); + assert_true(loaded); + assert_false(errored); + }); +}, 'An asynchronously loaded classic script with noModule set to false must run'); + +promise_test(() => { + window.executed = false; + let loaded = false; + let errored = false; + + let script = document.createElement('script'); + script.src = './resources/set-script-executed.js'; + script.onload = () => loaded = true; + script.onerror = () => errored = true; + script.noModule = true; + document.body.appendChild(script); + + return waitForLoadEvent.then(() => { + assert_true(supportsNoModule); + assert_false(executed); + assert_false(loaded); + assert_false(errored); + }); +}, 'An asynchronously loaded classic script with noModule set to true must not run'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-external-module-script.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-external-module-script.html new file mode 100644 index 0000000000..138b33c9fa --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-external-module-script.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<html> +<head> +<title>An external module script with nomodule must run</title> +<link rel="author" title="Yusuke Suzuki" href="mailto:utatane.tea@gmail.com"> +<link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script nomodule type="module" src="./resources/exports-cocoa.js"></script> +<script> + +waitForLoadEvent = new Promise((resolve) => { + window.onload = resolve; +}); + +promise_test(() => { + return waitForLoadEvent.then(() => { + assert_equals(typeof cocoa, 'undefined'); + assert_equals(typeof exportedCocoa, 'object'); + assert_equals(exportedCocoa.taste(), 'awesome'); + }); +}, 'An external module script with nomodule content attribute must run'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-inline-classic-scripts.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-inline-classic-scripts.html new file mode 100644 index 0000000000..588d59975c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-inline-classic-scripts.html @@ -0,0 +1,56 @@ +<!DOCTYPE html> +<html> +<head> +<title>Inline classic scripts with nomodule content attribute must not run</title> +<link rel="author" title="Yusuke Suzuki" href="mailto:utatane.tea@gmail.com"> +<link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +window.executed = true; +</script> +<script> + +test(() => { + assert_true(executed); +}, 'An inline classic script without nomodule content attribute must run'); + + +window.executed = false; +</script> +<script nomodule> +window.executed = true; +</script> +<script> + +test(() => { + assert_false(executed); +}, 'An inline classic script with nomodule content attribute must not run'); + +</script> +<script> + +test(() => { + window.executed = false; + const element = document.createElement("script"); + element.noModule = false; + element.textContent = `window.executed = true`; + document.body.appendChild(element); + assert_true(window.executed); +}, 'An inline classic script element dynamically inserted after noModule was set to false must run.'); + +test(() => { + window.executed = false; + const element = document.createElement("script"); + element.noModule = true; + element.textContent = `window.executed = true`; + document.body.appendChild(element); + assert_false(window.executed); +}, 'An inline classic script element dynamically inserted after noModule was set to true must not run.'); + +window.executed = false; +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-inline-module-script.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-inline-module-script.html new file mode 100644 index 0000000000..b11c25932e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-inline-module-script.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<title>An inline module script with nomodule must run</title> +<link rel="author" title="Yusuke Suzuki" href="mailto:utatane.tea@gmail.com"> +<link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script nomodule type="module"> +import Cocoa from "./resources/cocoa-module.js"; +var cocoa = new Cocoa(); +window.exportedCocoa = cocoa; +</script> +<script> + +waitForLoadEvent = new Promise((resolve) => { + window.onload = resolve; +}); + +promise_test(() => { + return waitForLoadEvent.then(() => { + assert_equals(typeof cocoa, 'undefined'); + assert_equals(typeof exportedCocoa, 'object'); + assert_equals(exportedCocoa.taste(), 'awesome'); + }); +}, 'An inline module script with nomodule content attribute must run'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-synchronously-loaded-classic-scripts.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-synchronously-loaded-classic-scripts.html new file mode 100644 index 0000000000..9f6207c9a5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/nomodule-set-on-synchronously-loaded-classic-scripts.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> +<head> +<title>External classic scripts with nomodule content attribute must not run</title> +<link rel="author" title="Yusuke Suzuki" href="mailto:utatane.tea@gmail.com"> +<link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> + +window.executed = false; +window.loaded = false; +window.errored = false; +</script> +<script src="./resources/set-script-executed.js" onload="loaded = true" onerror="errored = false"></script> +<script> + +test(() => { + assert_true(executed); + assert_true(loaded); + assert_false(errored); +}, 'A synchronously loaded external classic script without nomodule content attribute must run'); + +window.executed = false; +window.loaded = false; +window.errored = false; +</script> +<script nomodule src="./resources/set-script-executed.js" onload="loaded = true" onerror="errored = false"></script> +<script> + +test(() => { + assert_false(executed); + assert_false(loaded); + assert_false(errored); +}, 'A synchronously loaded external classic script with nomodule content attribute must not run'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/promise-reject-and-remove.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/promise-reject-and-remove.html new file mode 100644 index 0000000000..a3b2730e56 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/promise-reject-and-remove.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +async_test(t => { + window.onload = t.step_func_done(); +}, 'Removing iframe in promise reject handler should not crash'); +</script> +<iframe src="resources/promise-reject-and-remove-iframe.html"></iframe> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/bom-utf-16be.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/bom-utf-16be.js Binary files differnew file mode 100644 index 0000000000..8a529e10b1 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/bom-utf-16be.js diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/bom-utf-16le.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/bom-utf-16le.js Binary files differnew file mode 100644 index 0000000000..578f7f1951 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/bom-utf-16le.js diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/bom-utf-8.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/bom-utf-8.js new file mode 100644 index 0000000000..fb88bdda2a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/bom-utf-8.js @@ -0,0 +1,2 @@ +// JavaScript file with UTF-8 BOM. +window.executed_utf8_bom = '三æ‘ã‹ãªå'; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/cocoa-module.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/cocoa-module.js new file mode 100644 index 0000000000..24360a7bfe --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/cocoa-module.js @@ -0,0 +1,5 @@ +export default class Cocoa { + taste() { + return "awesome"; + } +}; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/cross-origin.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/cross-origin.py new file mode 100644 index 0000000000..abac1901b7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/cross-origin.py @@ -0,0 +1,20 @@ +def main(request, response): + origin = request.headers.get(b"origin") + + if origin is not None: + response.headers.set(b"Access-Control-Allow-Origin", origin) + response.headers.set(b"Access-Control-Allow-Methods", b"GET") + response.headers.set(b"Access-Control-Allow-Credentials", b"true") + + if request.method == u"OPTIONS": + return u"" + + headers = [(b"Content-Type", b"text/javascript")] + milk = request.cookies.first(b"milk", None) + + if milk is None: + return headers, u"var included = false;" + elif milk.value == b"yes": + return headers, u"var included = true;" + + return headers, u"var included = false;" diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/exports-cocoa.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/exports-cocoa.js new file mode 100644 index 0000000000..02967bc631 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/exports-cocoa.js @@ -0,0 +1,3 @@ +import Cocoa from "./cocoa-module.js"; +var cocoa = new Cocoa(); +window.exportedCocoa = cocoa; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/flag-setter.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/flag-setter.js new file mode 100644 index 0000000000..3274e5bfeb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/flag-setter.js @@ -0,0 +1,3 @@ +"use strict"; + +window.didExecute = true; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/load-error-events-helpers.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/load-error-events-helpers.js new file mode 100644 index 0000000000..bbd6b09c6c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/load-error-events-helpers.js @@ -0,0 +1,47 @@ +"use strict"; +// Helper functions to be used from load-error-events*.html tests. + +function event_test(name, load_to_be_fired, error_to_be_fired) { + return { + test: async_test(name), + executed: false, + load_event_to_be_fired: load_to_be_fired, + error_event_to_be_fired: error_to_be_fired + }; +} + +// Should be used as load/error event handlers of script tags, +// with |t| = the object returned by event_test(). +function onLoad(t) { + t.test.step(function() { + if (t.load_event_to_be_fired) { + assert_true(t.executed, + 'Load event should be fired after script execution'); + // Delay done() a little so that if an error event happens + // the assert_unreached is reached and fails the test. + t.test.step_timeout(() => t.test.done(), 100); + } else { + assert_unreached('Load event should not be fired.'); + } + }); +}; +function onError(t) { + t.test.step(function() { + if (t.error_event_to_be_fired) { + assert_false(t.executed); + // Delay done() a little so that if a load event happens + // the assert_unreached is reached and fails the test. + t.test.step_timeout(() => t.test.done(), 100); + } else { + assert_unreached('Error event should not be fired.'); + } + }); +}; + +// To be called from inline scripts, which expect no load/error events. +function onExecute(t) { + t.executed = true; + // Delay done() a little so that if a load/error event happens + // the assert_unreached is reached and fails the test. + t.test.step_timeout(() => t.test.done(), 100); +} diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/load-error-events.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/load-error-events.py new file mode 100644 index 0000000000..1eb82cd497 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/load-error-events.py @@ -0,0 +1,15 @@ +import re + +def main(request, response): + headers = [(b"Content-Type", b"text/javascript")] + test = request.GET.first(b'test') + assert(re.match(b'^[a-zA-Z0-9_]+$', test)) + + if test.find(b'_load') >= 0: + status = 200 + content = b'"use strict"; %s.executed = true;' % test + else: + status = 404 + content = b'"use strict"; %s.test.step(function() { assert_unreached("404 script should not be executed"); });' % test + + return status, headers, content diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/promise-reject-and-remove-iframe.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/promise-reject-and-remove-iframe.html new file mode 100644 index 0000000000..6da274469f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/promise-reject-and-remove-iframe.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<script> +const promise = Promise.reject(); + +window.onload = () => { + promise.catch(() => parent.document.querySelector('iframe').remove()); +}; +</script> + +<!-- Load a slow script to delay window.onload for a while. + Without this, crashes are flaky. --> +<script src="/common/slow.py"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/script-type-and-language-js.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/script-type-and-language-js.js new file mode 100644 index 0000000000..d357bc4994 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/script-type-and-language-js.js @@ -0,0 +1,141 @@ +function testAttribute(attr, val, shouldRun) { + test(function() { + assert_false(window.ran, "ran variable not reset"); + let script; + if (document.contentType === 'image/svg+xml') { + // SVG + script = document.createElementNS("http://www.w3.org/2000/svg", "script"); + } else { + // HTML or XHTML + script = document.createElement("script"); + } + script.setAttribute(attr, val); + script.textContent = "window.ran = true;"; + document.querySelector('#script-placeholder').appendChild(script); + assert_equals(window.ran, shouldRun); + }, "Script should" + (shouldRun ? "" : "n't") + " run with " + attr + "=" + + format_value(val)); + window.ran = false; +} +function testTypeShouldRun(type) { + testAttribute("type", type, true); +} +function testLanguageShouldRun(lang) { + testAttribute("language", lang, true); +} +function testTypeShouldNotRun(type) { + testAttribute("type", type, false); +} +function testLanguageShouldNotRunUnlessSVG(lang) { + // In SVGs, there is no concrete spec but all browsers agree that + // language attributes have no effects and thus script elements + // without type attributes are always expected to run regardless of + // language attributes. + const expectedToRun = document.contentType === 'image/svg+xml'; + testAttribute("language", lang, expectedToRun); +} + +// Unlike `test*()` methods above, there should be a (parser-inserted) script +// with an invalid type/language that would set `window.ran` to true just +// before `testParserInsertedDidNotRun()`, and +// `testParserInsertedDidNotRun()` asserts that the script did not run. +// `window.ran` should be reset where needed. For example: +// <script>window.ran = false;</script> +// <script type="invalid-type">window.ran = true;</script> +// <script>testParserInsertedDidNotRun('type=invalid-type');</script> +function testParserInsertedDidNotRun(description) { + test(() => assert_false(window.ran), + "Script shouldn't run with " + description + " (parser-inserted)"); + window.ran = false; +} + +// When prefixed by "application/", these match with +// https://mimesniff.spec.whatwg.org/#javascript-mime-type +const application = [ + "ecmascript", + "javascript", + "x-ecmascript", + "x-javascript" +]; + +// When prefixed by "text/", these match with +// https://mimesniff.spec.whatwg.org/#javascript-mime-type +const text = [ + "ecmascript", + "javascript", + "javascript1.0", + "javascript1.1", + "javascript1.2", + "javascript1.3", + "javascript1.4", + "javascript1.5", + "jscript", + "livescript", + "x-ecmascript", + "x-javascript" +]; + +const legacyTypes = [ + "javascript1.6", + "javascript1.7", + "javascript1.8", + "javascript1.9" +]; + +const spaces = [" ", "\t", "\n", "\r", "\f"]; + +window.ran = false; + +// Type attribute + +testTypeShouldRun(""); +testTypeShouldNotRun(" "); + +application.map(t => "application/" + t).forEach(testTypeShouldRun); +application.map(t => ("application/" + t).toUpperCase()).forEach( + testTypeShouldRun); + +spaces.forEach(function(s) { + application.map(t => "application/" + t + s).forEach(testTypeShouldRun); + application.map(t => s + "application/" + t).forEach(testTypeShouldRun); +}); + +application.map(t => "application/" + t + "\0").forEach(testTypeShouldNotRun); +application.map(t => "application/" + t + "\0foo").forEach( + testTypeShouldNotRun); + +text.map(t => "text/" + t).forEach(testTypeShouldRun); +text.map(t => ("text/" + t).toUpperCase()).forEach(testTypeShouldRun); + +legacyTypes.map(t => "text/" + t).forEach(testTypeShouldNotRun); + +spaces.forEach(function(s) { + text.map(t => "text/" + t + s).forEach(testTypeShouldRun); + text.map(t => s + "text/" + t).forEach(testTypeShouldRun); +}); + +text.map(t => "text/" + t + "\0").forEach(testTypeShouldNotRun); +text.map(t => "text/" + t + "\0foo").forEach(testTypeShouldNotRun); + +text.forEach(testTypeShouldNotRun); +legacyTypes.forEach(testTypeShouldNotRun); + +// Language attribute + +testLanguageShouldRun(""); +testLanguageShouldNotRunUnlessSVG(" "); + +text.forEach(testLanguageShouldRun); +text.map(t => t.toUpperCase()).forEach(testLanguageShouldRun); + +legacyTypes.forEach(testLanguageShouldNotRunUnlessSVG); + +spaces.forEach(function(s) { + text.map(t => t + s).forEach(testLanguageShouldNotRunUnlessSVG); + text.map(t => s + t).forEach(testLanguageShouldNotRunUnlessSVG); +}); +text.map(t => t + "xyz").forEach(testLanguageShouldNotRunUnlessSVG); +text.map(t => "xyz" + t).forEach(testLanguageShouldNotRunUnlessSVG); + +text.map(t => t + "\0").forEach(testLanguageShouldNotRunUnlessSVG); +text.map(t => t + "\0foo").forEach(testLanguageShouldNotRunUnlessSVG); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/set-script-executed.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/set-script-executed.js new file mode 100644 index 0000000000..a6095097dd --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/set-script-executed.js @@ -0,0 +1 @@ +window.executed = true; diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/syntax-error.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/syntax-error.js new file mode 100644 index 0000000000..40dc81dcfa --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/syntax-error.js @@ -0,0 +1 @@ +This cannot be parsed as JavaScript diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/throw.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/throw.js new file mode 100644 index 0000000000..be53dd1ef3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/resources/throw.js @@ -0,0 +1 @@ +document.querySelector(":::not-going-to-be-valid"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-charset-01.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-charset-01.html new file mode 100644 index 0000000000..c5ac0d0a62 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-charset-01.html @@ -0,0 +1,89 @@ +<!DOCTYPE html> +<head> + <meta charset="utf-8"> + <title>Script @type: unknown parameters</title> + <link rel="author" title="askalski" href="github.com/askalski"> + <link rel="help" href="https://html.spec.whatwg.org/multipage/#scriptingLanguages"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <div id="log"></div> + + <!-- "Step1" tests --> + <!-- charset is set incorrectly via Content Type "text/javascript;charset=utf-8" in response + which has priority before a correct setting in "charset" attribute of script tag. + --> + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript%3Bcharset=utf-8" charset="windows-1250"> + </script> + <script> + test(function() { + //these strings should not match, since the file charset is set incorrectly + assert_not_equals(window.getSomeString(), "śćążź"); + }); + </script> + <!-- charset is set correctly via Content Type "text/javascript;charset=utf-8" in response + which has priority before a incorrect setting in "charset" attribute of script tag. + --> + + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript%3Bcharset=windows-1250" charset="utf-8"> + </script> + <script> + //the charset is set correctly via Content Type "text/javascript;charset=windows-1250" in respones + test(function() { + assert_equals(window.getSomeString(), "śćążź"); + }); + </script> + + <!-- end of step1 tests, now step2 tests --> + <!-- in this case, the response's Content Type does not bring charset information. + Second step takes block character encoding if available.--> + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript" charset="utf-8"> + </script> + <script> + test(function() { + //these strings should not match, since the file charset is set incorrectly in "charset" tag of <script> above + assert_not_equals(window.getSomeString(), "śćążź"); + }); + </script> + <!-- charset is set correctly via Content Type "text/javascript;charset=utf-8" in response + which has priority before a incorrect setting in "charset" attribute of script tag. + --> + + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript" charset="windows-1250"> + </script> + <script> + //the charset is set correctly via content attribute in <script> above + test(function() { + assert_equals(window.getSomeString(), "śćążź"); + }); + </script> + + <!-- end of step2 tests, now step3 tests --> + <!-- in this case, neither response's Content Type nor charset attribute bring correct charset information. + Third step takes this document's character encoding (declared correctly as UTF-8).--> + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript"> + </script> + <script> + test(function() { + //these strings should not match, since the tested file is in windows-1250, and document is utf-8 + assert_not_equals(window.getSomeString(), "śćążź"); + }); + </script> + + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-utf8.js&ct=text/javascript"> + </script> + <script> + //these strings should match, both document and tested file are utf-8 + test(function() { + assert_equals(window.getSomeString(), "śćążź"); + }); + </script> + + <!-- the last portion of tests (step4) are in file script-charset-02.html + +</head> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-charset-02.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-charset-02.html new file mode 100644 index 0000000000..63cbe838e0 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-charset-02.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<head> + <title>Script encoding for document encoding windows-1250</title> + <link rel="author" title="askalski" href="github.com/askalski"> + <link rel="author" title="Aaqa Ishtyaq" href="github.com/aaqaishtyaq"> + <link rel="help" href="https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-classic-script"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <div id="log"></div> + <!-- to avoid conflating tests for script encoding declaring the encoding at the top of file. i.e, windows-1250--> + <meta charset="windows-1250"> + <script> + test(function() { + assert_equals(document.characterSet, "windows-1250") + }, "assumption: document encoding is windows-1250"); + </script> + + <!-- in this case, neither response's Content Type nor charset attribute bring correct charset information. + --> + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-windows1250.js&ct=text/javascript"> + </script> + + <script> + test(function() { + //these string should match since, windows-1250 is the fallback encoding. + assert_equals(window.getSomeString(), "\u015b\u0107\u0105\u017c\u017a"); + }, "windows-1250 script decoded using document encoding (also windows-1250)"); + </script> + + <script type="text/javascript" + src="serve-with-content-type.py?fn=external-script-utf8.js&ct=text/javascript"> + </script> + <script> + //these strings should match, since this string is the result of decoding the utf-8 text as windows-1250. + test(function() { + assert_equals(window.getSomeString(), "\u0139\u203a\xc4\u2021\xc4\u2026\u0139\u013d\u0139\u015f"); + }, "UTF-8 script decoded using document encoding (windows-1250)"); + </script> + +</head> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-charset-03.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-charset-03.html new file mode 100644 index 0000000000..4ff4cc6b0b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-charset-03.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<head> +<meta charset="utf-8"> +<title>Script changing @charset</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#scriptingLanguages"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +async_test(function() { + var s = document.createElement("script"); + s.src = "external-script-windows1250.js"; + s.charset = "windows-1250"; + document.body.appendChild(s); + s.charset = "utf-8"; + window.onload = this.step_func_done(function() { + assert_equals(window.getSomeString(), "\u015b\u0107\u0105\u017c\u017a"); + }); +}) +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-crossorigin-network.sub.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-crossorigin-network.sub.html new file mode 100644 index 0000000000..5886ab6f32 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-crossorigin-network.sub.html @@ -0,0 +1,120 @@ +<!doctype html> +<meta charset="utf-8"> +<title>HTMLScriptElement: crossorigin attribute network test</title> +<link rel="author" title="KiChjang" href="mailto:kungfukeith11@gmail.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#cors-settings-attribute"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> + <script type="text/javascript"> + var test1 = async_test("same-origin use-credentials"); + var test2 = async_test("same-origin invalid"); + var test3 = async_test("same-origin missing"); + var test4 = async_test("cross-origin use-credentials"); + var test5 = async_test("cross-origin invalid"); + var test6 = async_test("cross-origin missing"); + var test7 = async_test("cross-origin use-credentials mixed case"); + var test8 = async_test("cross-origin use-credentials non-ASCII"); + + var same = "resources/cross-origin.py"; + var cross = new URL(same, location); + cross.port = {{ports[http][1]}}; + + var script1 = document.createElement("script"); + script1.src = same; + script1.crossOrigin = "use-credentials"; + + var script2 = document.createElement("script"); + script2.src = same; + script2.crossOrigin = "gibberish"; + + var script3 = document.createElement("script"); + script3.src = same; + + var script4 = document.createElement("script"); + script4.src = cross; + script4.crossOrigin = "use-credentials"; + + var script5 = document.createElement("script"); + script5.src = cross; + script5.crossOrigin = "gibberish"; + + var script6 = document.createElement("script"); + script6.src = cross; + + var script7 = document.createElement("script"); + script7.src = cross; + script7.crossOrigin = "UsE-cReDenTiAlS"; + + var script8 = document.createElement("script"); + script8.src = cross; + script8.crossOrigin = "uÅ¿e-credentialÅ¿"; + + document.cookie = "milk=yes"; + + document.body.appendChild(script1); + script1.onload = function() { + test1.step(function() { + assert_true(included, "credentials included (credentialsMode include)"); + test1.done(); + }); + }; + + document.body.appendChild(script2); + script2.onload = function() { + test2.step(function() { + assert_true(included, "credentials included (credentialsMode same-origin)"); + test2.done(); + }); + }; + + document.body.appendChild(script3); + script3.onload = function() { + test3.step(function() { + assert_true(included, "credentials included (credentialsMode include)"); + test3.done(); + }); + }; + + document.body.appendChild(script4); + script4.onload = function() { + test4.step(function() { + assert_true(included, "credentials included (credentialsMode include)"); + test4.done(); + }); + }; + + document.body.appendChild(script5); + script5.onload = function() { + test5.step(function() { + assert_false(included, "credentials excluded (credentialsMode same-origin)"); + test5.done(); + }); + }; + + document.body.appendChild(script6); + script6.onload = function() { + test6.step(function() { + assert_true(included, "credentials included (credentialsMode include)"); + test6.done(); + }); + }; + + document.body.appendChild(script7); + script7.onload = function() { + test7.step(function() { + assert_true(included, "credentials included (credentialsMode include)"); + test7.done(); + }); + }; + + document.body.appendChild(script8); + script8.onload = function() { + test8.step(function() { + assert_false(included, "credentials excluded (credentialsMode same-origin)"); + test8.done(); + }); + }; + </script> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-crossorigin.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-crossorigin.html new file mode 100644 index 0000000000..52857a08ea --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-crossorigin.html @@ -0,0 +1,39 @@ +<!doctype html> +<meta charset="utf-8"> +<title>HTMLScriptElement: crossOrigin IDL attribute</title> +<link rel="author" title="KiChjang" href="mailto:kungfukeith11@gmail.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#cors-settings-attribute"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script id="script1"></script> +<script id="script2" crossorigin=""></script> +<script id="script3" crossorigin="foo"></script> +<script id="script4" crossorigin="anonymous"></script> +<script id="script5" crossorigin="use-credentials"></script> +<script> +test(function() { + var script1 = document.getElementById("script1"); + var script2 = document.getElementById("script2"); + var script3 = document.getElementById("script3"); + var script4 = document.getElementById("script4"); + var script5 = document.getElementById("script5"); + + assert_equals(script1.crossOrigin, null, "Missing value default should be null"); + assert_equals(script2.crossOrigin, "anonymous", "Empty string should map to anonymous"); + assert_equals(script3.crossOrigin, "anonymous", "Invalid value default should be anonymous"); + assert_equals(script4.crossOrigin, "anonymous", "anonymous should be parsed correctly"); + assert_equals(script5.crossOrigin, "use-credentials", "use-credentials should be parsed correctly"); + + script1.crossOrigin = "bar"; + assert_equals(script1.crossOrigin, "anonymous", "Setting to invalid value would default to anonymous"); + + script2.crossOrigin = null; + assert_equals(script2.crossOrigin, null, "Resetting to null should work"); + + script4.crossOrigin = "use-credentials"; + assert_equals(script4.crossOrigin, "use-credentials", "Switching from anonymous to use-credentials should work"); + + script5.crossOrigin = "anonymous"; + assert_equals(script5.crossOrigin, "anonymous", "Switching from use-credentials to anonymous should work"); +}, document.title); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-defer-xhtml.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-defer-xhtml.xhtml new file mode 100644 index 0000000000..3f4a50f779 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-defer-xhtml.xhtml @@ -0,0 +1,31 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>XHTML Test: HTMLScriptElement - defer</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta charset="utf-8" /> +</head> +<body> +<div id="log"></div> + +<script> + +let script_run_status = "inline"; +let t = async_test("the defer script run later"); + +</script> + +<script type="text/javascript" src="defer.js" defer="defer"></script> + +<script> + +t.step(() => { + assert_equals(script_run_status, "inline", "the script run status"); + script_run_status = "deferred"; +}); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-defer.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-defer.html new file mode 100644 index 0000000000..80eb98dc75 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-defer.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>HTML Test: HTMLScriptElement - defer</title> +<link rel="author" title="Intel" href="http://www.intel.com/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<div id="log"></div> + +<script> + +let script_run_status = "inline"; +let t = async_test("the defer script run later"); + +</script> + +<script type="text/javascript" src="defer.js" defer></script> + +<script> + +t.step(() => { + assert_equals(script_run_status, "inline", "the script run status"); + script_run_status = "deferred"; +}); + +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-for-event-xhtml.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-for-event-xhtml.xhtml new file mode 100644 index 0000000000..69c4ef1f81 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-for-event-xhtml.xhtml @@ -0,0 +1,22 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Scripts with for and event attributes</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> + <div id="log"></div> + <script> + var run = false; + </script> + <script for="window" event="bar"> + // This script should not run, but should not cause a parse error either. + run = true; + </script> + <script> + test(function() { + assert_false(run, "Script was unexpectedly run.") + }, "Scripts with for and event attributes should not run.") + </script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-for-event.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-for-event.html new file mode 100644 index 0000000000..552ea7041a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-for-event.html @@ -0,0 +1,93 @@ +<!DOCTYPE html> +<title>Scripts with for and event attributes</title> +<link rel="author" title="Matheus Kerschbaum" href="mailto:matjk7@gmail.com"> +<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +var expected = [ + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + true, + true, + false, + true, + true, +]; +var run = expected.map(function() { return false }); +</script> +<script for="wİndow" event="onload"> +run[0] = true; +</script> +<script for="window" event="onload x"> +run[1] = true; +</script> +<script for="window" event="onload(x"> +run[2] = true; +</script> +<script for="window" event="onload(x)"> +run[3] = true; +</script> +<script for="window" event="onclick"> +run[4] = true; +</script> +<script for="" event="onload"> +run[5] = true; +</script> +<script for="window" event=""> +run[6] = true; +</script> +<script for="" event=""> +run[7] = true; +</script> +<script for=" window" event="onload"> +run[8] = true; +</script> +<script for="window " event="onload"> +run[9] = true; +</script> +<script for="window" event=" onload"> +run[10] = true; +</script> +<script for="window" event="onload "> +run[11] = true; +</script> +<script for=" window " event=" onload "> +run[12] = true; +</script> +<script for=" window " event=" onload() "> +run[13] = true; +</script> +<script for="object" event="handler"> +run[14] = true; +</script> +<script event="handler"> +run[15] = true; +</script> +<script for="object"> +run[16] = true; +</script> +<script> +test(function() { + for (var i = 0; i < run.length; ++i) { + test(function() { + var script = document.querySelectorAll("script[for], script[event]")[i]; + assert_equals(run[i], expected[i], + "script for=" + format_value(script.getAttribute("for")) + + " event=" + format_value(script.getAttribute("event"))); + }, "Script " + i); + } +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-noembed-noframes-iframe.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-noembed-noframes-iframe.xhtml new file mode 100644 index 0000000000..8dd9ceb9a6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-noembed-noframes-iframe.xhtml @@ -0,0 +1,36 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Script inside noembed, noframes and iframe</title> +<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"/> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="log"></div> +<script> +var run = []; +</script> +<div id="test"> +<noembed> +<script> +run.push("noembed"); +</script> +</noembed> +<noframes> +<script> +run.push("noframes"); +</script> +</noframes> +<iframe> +<script> +run.push("iframe"); +</script> +</iframe> +</div> +<script> +test(function() { + assert_array_equals(run, ["noembed", "noframes", "iframe"], "Haven't run."); +}); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown-child.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown-child.html new file mode 100644 index 0000000000..2f3ce2368d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown-child.html @@ -0,0 +1,12 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Script is not executed after script thread is shutdown</title> +<script> +onload = function() { + script_executed = parent.script_executed; + s = document.createElement('script'); + s.type = 'text/javascript'; + s.src = 'script-not-executed-after-shutdown.js?pipe=trickle(d3)'; + document.body.appendChild(s); +}; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html new file mode 100644 index 0000000000..eb4def3ec4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.html @@ -0,0 +1,19 @@ +<!doctype html> +<meta charset="utf-8"> +<title>Script is not executed after script thread is shutdown</title> +<meta name="timeout" content="long"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<iframe id="testiframe" src="script-not-executed-after-shutdown-child.html"></iframe> +<script> +async_test(function(t) { + window.script_executed = t.unreached_func("script executed in removed iframe"); + let iframe = document.getElementById("testiframe"); + iframe.onload = function() { + iframe.parentNode.removeChild(iframe); + }; + setTimeout(function() { + t.done(); + }, 5000); +}); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.js new file mode 100644 index 0000000000..ccdf14c0cd --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-executed-after-shutdown.js @@ -0,0 +1 @@ +script_executed(); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed-2.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed-2.py new file mode 100644 index 0000000000..4ff5be7374 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed-2.py @@ -0,0 +1,4 @@ +def main(request, response): + headers = [(b"Content-Type", b"text/javascript")] + body = u"test2_token = \"script executed\";" + return 200, headers, body diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html new file mode 100644 index 0000000000..44ad30b018 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.html @@ -0,0 +1,19 @@ +<!doctype html> +<meta charset="utf-8"> +<title></title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script>var test1_token = "script not executed";</script> +<script src="script-not-found-not-executed.py"></script> +<script> +test(function(){ + assert_equals(test1_token, "script not executed"); +}, "Script that 404"); +</script> +<script>var test2_token = "script not executed";</script> +<script src="script-not-found-not-executed-2.py"></script> +<script> +test(function(){ + assert_equals(test2_token, "script executed"); +}, "Script that does not 404"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.py new file mode 100644 index 0000000000..9354d42703 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-not-found-not-executed.py @@ -0,0 +1,4 @@ +def main(request, response): + headers = [(b"Content-Type", b"text/javascript")] + body = u"test1_token = \"script executed\";" + return 404, headers, body diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html new file mode 100644 index 0000000000..0fe39b11a8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-1.html @@ -0,0 +1,12 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test that the insertion point is defined in the error event of a parser-inserted script that actually started a fetch (but just had it fail).</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> + var t = async_test(""); + var writeDone = t.step_func_done(function(text) { + assert_equals(text, "Some text"); + }); +</script> +<iframe src="support/script-onerror-insertion-point-1-helper.html"></iframe> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-2.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-2.html new file mode 100644 index 0000000000..6d3f3ef09e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onerror-insertion-point-2.html @@ -0,0 +1,13 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test that the insertion point is not defined in the error event of a + parser-inserted script that has an unparseable URL</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> + var t = async_test(""); + var writeDone = t.step_func_done(function(text) { + assert_equals(text, "text"); + }); +</script> +<iframe src="support/script-onerror-insertion-point-2-helper.html"></iframe> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onload-insertion-point.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onload-insertion-point.html new file mode 100644 index 0000000000..ce3ddeee65 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onload-insertion-point.html @@ -0,0 +1,12 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test that the insertion point is defined in the load event of a parser-inserted script.</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> + var t = async_test(""); + var writeDone = t.step_func_done(function(text) { + assert_equals(text, "Some text"); + }); +</script> +<iframe src="support/script-onload-insertion-point-helper.html"></iframe> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onload-string.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onload-string.html new file mode 100644 index 0000000000..85f2d4dcfa --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-onload-string.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<title>Script: setting onload to a string</title> +<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<script> +test(function() { + var s = document.createElement("script"); + assert_equals(s.onload, null); + var dummy = function() {}; + s.onload = dummy; + assert_equals(s.onload, dummy); + s.onload = "w('load DOM appended')"; + assert_equals(s.onload, null); +}, "Setting onload to a string should convert to null."); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-referrerpolicy-idl.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-referrerpolicy-idl.html new file mode 100644 index 0000000000..bf01cb83b8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-referrerpolicy-idl.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title><script> referrerPolicy IDL</title> +<link rel="author" href="mailto:masonf@chromium.org"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#referrer-policy-attribute"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> +<script> + test(() => { + const script = document.createElement('script'); + document.body.appendChild(script); + assert_equals(script.referrerPolicy,"",'Missing content attribute should reflect as empty'); + script.setAttribute('referrerpolicy','no-referrer'); + assert_equals(script.referrerPolicy,"no-referrer",'Valid value should reflect'); + script.setAttribute('referrerpolicy',''); + assert_equals(script.referrerPolicy,"",'Empty string should reflect as empty'); + script.setAttribute('referrerpolicy','invalid-value-here'); + assert_equals(script.referrerPolicy,"",'Invalid values should reflect as empty'); + script.referrerPolicy = 'no-referrer'; + assert_equals(script.referrerPolicy,"no-referrer",'Valid value via IDL'); + script.referrerPolicy = null; + assert_equals(script.referrerPolicy,"",'Null should reflect as empty'); + },'Missing/invalid/null referrerPolicy should reflect as the empty string') +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-supports.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-supports.html new file mode 100644 index 0000000000..495056fce9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-supports.html @@ -0,0 +1,52 @@ +<!doctype html> +<meta charset=utf-8> +<title>HTMLScriptElement.supports</title> +<link rel=help href="https://html.spec.whatwg.org/#dom-script-supports"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + assert_equals(typeof HTMLScriptElement.supports, 'function'); +}, 'Type of HTMLScriptElement.supports is function'); + +test(function() { + assert_true(HTMLScriptElement.supports('classic')); +}, 'HTMLScriptElement.supports resurns true for \'classic\''); + +test(function() { + assert_true(HTMLScriptElement.supports('module')); +}, 'HTMLScriptElement.supports resurns true for \'module\''); + +test(function() { + assert_false(HTMLScriptElement.supports('application/ecmascript')); + assert_false(HTMLScriptElement.supports('application/javascript')); + assert_false(HTMLScriptElement.supports('application/x-ecmascript')); + assert_false(HTMLScriptElement.supports('application/x-javascript')); + assert_false(HTMLScriptElement.supports('text/ecmascript')); + assert_false(HTMLScriptElement.supports('text/javascript')); + assert_false(HTMLScriptElement.supports('text/javascript1.0')); + assert_false(HTMLScriptElement.supports('text/javascript1.1')); + assert_false(HTMLScriptElement.supports('text/javascript1.2')); + assert_false(HTMLScriptElement.supports('text/javascript1.3')); + assert_false(HTMLScriptElement.supports('text/javascript1.4')); + assert_false(HTMLScriptElement.supports('text/javascript1.5')); + assert_false(HTMLScriptElement.supports('text/jscript')); + assert_false(HTMLScriptElement.supports('text/livescript')); + assert_false(HTMLScriptElement.supports('text/x-ecmascript')); + assert_false(HTMLScriptElement.supports('text/x-javascript')); +}, 'HTMLScriptElement.supports returns false for JavaScript MIME types'); + +test(function() { + assert_false(HTMLScriptElement.supports('')); + assert_false(HTMLScriptElement.supports(' ')); + assert_false(HTMLScriptElement.supports('classic ')); + assert_false(HTMLScriptElement.supports('module ')); + assert_false(HTMLScriptElement.supports(' classic ')); + assert_false(HTMLScriptElement.supports(' module ')); + assert_false(HTMLScriptElement.supports('classics')); + assert_false(HTMLScriptElement.supports('modules')); + assert_false(HTMLScriptElement.supports('Classic')); + assert_false(HTMLScriptElement.supports('Module')); + assert_false(HTMLScriptElement.supports('unsupported')); +}, 'HTMLScriptElement.supports returns false for unsupported types'); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text-modifications-csp.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text-modifications-csp.html new file mode 100644 index 0000000000..a991151066 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text-modifications-csp.html @@ -0,0 +1,52 @@ +<!doctype html> +<head> +<meta charset=utf-8> +<title>Modify HTMLScriptElement's text after #prepare-a-script that violates CSP</title> +<link rel=help href="https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<meta http-equiv="content-security-policy" content="script-src + 'nonce-allow' + 'sha256-2+5xh6b9uuIi4GaJtmHWtgR2nwRXJpBtMY4nVaOBpfc=' +"> +<!-- The hash is that of the original content of `script0`. --> + +<script nonce="allow"> +window.t = async_test("Modify inline script element's text " + + "after prepare-a-script before evaluation (CSP)"); + +const updatedText = + 't.unreached_func("CSP check was done against the original text but the updated text was evaluated")();'; + +function changeScriptText() { + document.querySelector('#script0').textContent = updatedText; +} + +t.step_timeout(changeScriptText, 500); +</script> + +<!-- This is "a style sheet that is blocking scripts" and thus ... --> +<link rel="stylesheet" href="/common/slow.py?pipe=trickle(d1)"></link> + +<!-- This inline script becomes a parser-blocking script, and thus +the step_timeout is evaluated after script0 is inserted into DOM, +prepare-a-script'ed, but before its evaluation. --> +<script id="script0"> +t.step(() => { + // When this is evaluated after the stylesheet is loaded, + // script0's textContent is modified by the async script above, + // but the evaluated script is still the original script here, + // not what is overwritten, because "child text content" is taken in + // #prepare-a-script and passed to "creating a classic script". + var s = document.getElementById('script0'); + assert_equals(s.textContent, updatedText, + "<script>'s textContent should be already modified"); + t.done(); + }); +</script> +<script nonce="allow"> +// If this makes the test fail, it indicates `script0` (the original or updated +// text) was not evaluated, probably blocked by CSP that was checked against the +// updated text. +t.unreached_func("CSP check was done against the updated text")(); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text-modifications.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text-modifications.html new file mode 100644 index 0000000000..cb54da6995 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text-modifications.html @@ -0,0 +1,40 @@ +<!doctype html> +<head> +<meta charset=utf-8> +<title>Modify HTMLScriptElement's text after #prepare-a-script</title> +<link rel=help href="https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +var t = async_test("Modify inline script element's text " + + "after prepare-a-script before evaluation"); + +function changeScriptText() { + document.querySelector('#script0').textContent = + 't.unreached_func("This should not be evaluated")();'; +} + +t.step_timeout(changeScriptText, 500); +</script> + +<!-- This is "a style sheet that is blocking scripts" and thus ... --> +<link rel="stylesheet" href="/common/slow.py?pipe=trickle(d1)"></link> + +<!-- This inline script becomes a parser-blocking script, and thus +the step_timeout is evaluated after script0 is inserted into DOM, +prepare-a-script'ed, but before its evaluation. --> +<script id="script0"> +t.step(() => { + // When this is evaluated after the stylesheet is loaded, + // script0's textContent is modified by the async script above, + // but the evaluated script is still the original script here, + // not what is overwritten, because "child text content" is taken in + // #prepare-a-script and passed to "creating a classic script". + var s = document.getElementById('script0'); + assert_equals(s.textContent, + 't.unreached_func("This should not be evaluated")();', + "<script>'s textContent should be already modified"); + t.done(); + }); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text-xhtml.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text-xhtml.xhtml new file mode 100644 index 0000000000..33a4635db3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text-xhtml.xhtml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>HTMLScriptElement.text</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-script-text"/> +<script src="/resources/testharness.js"/> +<script src="/resources/testharnessreport.js"/> +</head> +<body> +<div id="log"></div> +<script> +<x>7;</x> +<![CDATA[ + var x = "y"; +]]> +</script> +<script> +var script; +setup(function() { + script = document.body.getElementsByTagName("script")[0]; +}) +test(function() { + assert_equals(script.text, '\n\n\n var x = "y";\n\n') + assert_equals(script.textContent, '\n7;\n\n var x = "y";\n\n') +}, "Getter with CDATA section") +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text.html new file mode 100644 index 0000000000..6e86472246 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-text.html @@ -0,0 +1,72 @@ +<!doctype html> +<meta charset=utf-8> +<title>HTMLScriptElement.text</title> +<link rel=help href="https://html.spec.whatwg.org/multipage/#dom-script-text"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="log"></div> +<script> +var script; +setup(function() { + script = document.createElement("script") + script.appendChild(document.createComment("COMMENT")) + script.appendChild(document.createTextNode(" TEXT ")) + script.appendChild(document.createProcessingInstruction("P", "I")) + script.appendChild(document.createElement("a")) + .appendChild(document.createTextNode("ELEMENT")) +}) + +test(function() { + assert_equals(script.text, " TEXT ") + assert_equals(script.textContent, " TEXT ELEMENT") +}, "Getter") + +test(function() { + script.text = " text " + assert_equals(script.text, " text ") + assert_equals(script.textContent, " text ") + assert_equals(script.firstChild.nodeType, Node.TEXT_NODE) + assert_equals(script.firstChild.data, " text ") + assert_equals(script.firstChild, script.lastChild) + assert_array_equals(script.childNodes, [script.firstChild]) +}, "Setter (non-empty string)") + +test(function() { + script.text = "" + assert_equals(script.text, "") + assert_equals(script.textContent, "") + assert_equals(script.firstChild, null) +}, "Setter (empty string)") + +test(function() { + script.text = null + assert_equals(script.text, "null") + assert_equals(script.textContent, "null") + assert_equals(script.firstChild.nodeType, Node.TEXT_NODE) + assert_equals(script.firstChild.data, "null") + assert_equals(script.firstChild, script.lastChild) +}, "Setter (null)") + +test(function() { + script.text = undefined + assert_equals(script.text, "undefined") + assert_equals(script.textContent, "undefined") + assert_equals(script.firstChild.nodeType, Node.TEXT_NODE) + assert_equals(script.firstChild.data, "undefined") + assert_equals(script.firstChild, script.lastChild) +}, "Setter (undefined)") + +test(function() { + var s = document.createElement("script"); + var text = document.createTextNode("one"); + s.appendChild(text); + + assert_equals(s.firstChild, text); + assert_equals(text.nodeValue, "one"); + + s.text = "two"; + assert_not_equals(s.firstChild, text); + assert_equals(text.nodeValue, "one"); + assert_equals(s.firstChild.nodeValue, "two"); +}, "Setter (text node reuse)") +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-empty.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-empty.html new file mode 100644 index 0000000000..6ce1b279f7 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-empty.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<title>Script @type and @language: empty strings</title> +<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<!-- Setup --> +<script> +window.run1 = window.run2 = window.run3 = window.run4 = false; +</script> + +<!-- Systems under test --> +<script type=""> +window.run1 = true; +</script> + +<script type="" language="foo"> +window.run2 = true; +</script> + +<script type="" language=""> +window.run3 = true; +</script> + +<script language=""> +window.run4 = true; +</script> + +<!-- Asserts --> +<script> +test(() => { + assert_true(window.run1); +}, "A script with empty type and no language should run"); + +test(() => { + assert_true(window.run2); +}, "A script with empty type and a random language should run"); + +test(() => { + assert_true(window.run3); +}, "A script with empty type and empty language should run"); + +test(() => { + assert_true(window.run4); +}, "A script with no type and empty language should run"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-js-svg.svg b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-js-svg.svg new file mode 100644 index 0000000000..2f31d4d75c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-js-svg.svg @@ -0,0 +1,37 @@ +<?xml version="1.0" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" + xmlns:h="http://www.w3.org/1999/xhtml"> +<metadata> + <h:link rel="help" href="https://html.spec.whatwg.org/multipage/#scriptingLanguages" /> + <h:link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script" /> +</metadata> +<h:script src="/resources/testharness.js"/> +<h:script src="/resources/testharnessreport.js"/> +<h:div id="script-placeholder"/> +<h:script src="resources/script-type-and-language-js.js"/> +<script>window.ran = false;</script> +<script type="javascript">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript');</script> +<script type="javascript1.0">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.0');</script> +<script type="javascript1.1">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.1');</script> +<script type="javascript1.2">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.2');</script> +<script type="javascript1.3">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.3');</script> +<script type="javascript1.4">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.4');</script> +<script type="javascript1.5">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.5');</script> +<script type="javascript1.6">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.6');</script> +<script type="javascript1.7">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.7');</script> +<script type="livescript">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=livescript');</script> +<script type="ecmascript">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=ecmascript');</script> +<script type="jscript">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=jscript');</script> +</svg> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-js-xhtml.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-js-xhtml.xhtml new file mode 100644 index 0000000000..0bfdfce3c4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-js-xhtml.xhtml @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="utf-8"?> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<title>Script @type and @language: JavaScript types</title> +<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com" /> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#scriptingLanguages" /> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="script-placeholder"/> +<script src="resources/script-type-and-language-js.js"></script> + +<script>ran = false;</script> +<script type="javascript">ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript');</script> +<script type="javascript1.0">ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.0');</script> +<script type="javascript1.1">ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.1');</script> +<script type="javascript1.2">ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.2');</script> +<script type="javascript1.3">ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.3');</script> +<script type="javascript1.4">ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.4');</script> +<script type="javascript1.5">ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.5');</script> +<script type="javascript1.6">ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.6');</script> +<script type="javascript1.7">ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.7');</script> +<script type="livescript">ran = true;</script> +<script>testParserInsertedDidNotRun('type=livescript');</script> +<script type="ecmascript">ran = true;</script> +<script>testParserInsertedDidNotRun('type=ecmascript');</script> +<script type="jscript">ran = true;</script> +<script>testParserInsertedDidNotRun('type=jscript');</script> + +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-js.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-js.html new file mode 100644 index 0000000000..009123de2b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-js.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<title>Script @type and @language: JavaScript types</title> +<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#scriptingLanguages"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id="script-placeholder"></div> +<script src="resources/script-type-and-language-js.js"></script> + +<script>window.ran = false;</script> +<script type="javascript">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript');</script> +<script type="javascript1.0">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.0');</script> +<script type="javascript1.1">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.1');</script> +<script type="javascript1.2">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.2');</script> +<script type="javascript1.3">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.3');</script> +<script type="javascript1.4">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.4');</script> +<script type="javascript1.5">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.5');</script> +<script type="javascript1.6">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.6');</script> +<script type="javascript1.7">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=javascript1.7');</script> +<script type="livescript">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=livescript');</script> +<script type="ecmascript">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=ecmascript');</script> +<script type="jscript">window.ran = true;</script> +<script>testParserInsertedDidNotRun('type=jscript');</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-with-params.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-with-params.html new file mode 100644 index 0000000000..977ee7d0a4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-and-language-with-params.html @@ -0,0 +1,41 @@ +<!DOCTYPE html> +<title>Script @type and @language: unknown type parameters</title> +<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com"> +<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#scriptingLanguages"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<!-- Setup --> +<script> +window.run1 = window.run2 = window.run3 = false; +</script> + +<!-- Systems under test --> +<script type="text/javascript;charset=UTF-8"> +window.run1 = true; +</script> + +<script type="text/javascript;x-test=abc"> +window.run2 = true; +</script> + +<script language="javascript" type="text/javascript;charset=UTF-8"> +window.run3 = true; +</script> + +<!-- Asserts --> +<script> +test(() => { + assert_false(window.run1); +}, "A script with a charset param in its type should not run"); + +test(() => { + assert_false(window.run2); +}, "A script with an x-test param in its type should not run"); + +test(() => { + assert_false(window.run3); +}, "A script with a charset param in its type should not run, even with language=javascript"); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-whitespace.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-whitespace.html new file mode 100644 index 0000000000..5e8acb1a17 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/script-type-whitespace.html @@ -0,0 +1,27 @@ +<!doctype html> +<title><script type> non-ASCII whitespace handling</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script> +function testParserInsertedDidNotRun(description) { + test(() => assert_false(window.ran), + "Script shouldn't run with " + description + " (parser-inserted)"); + window.ran = false; +} +</script> + +<script>window.ran = false;</script> +<script type="text/javascript">window.ran = true;</script> +<script>testParserInsertedDidNotRun("type=\"text/javascript\"");</script> + +<script type="text/javascript…">window.ran = true;</script> +<script>testParserInsertedDidNotRun("type=\"text/javascript…\"");</script> + +<script type="text/javascript ">window.ran = true;</script> +<script>testParserInsertedDidNotRun("type=\"text/javascript \"");</script> + +<script type="text/javascript ">window.ran = true;</script> +<script>testParserInsertedDidNotRun("type=\"text/javascript \"");</script> + +<script type="text/javascript ">window.ran = true;</script> +<script>testParserInsertedDidNotRun("type=\"text/javascript \"");</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/scripting-enabled.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/scripting-enabled.html new file mode 100644 index 0000000000..a2671a78f6 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/scripting-enabled.html @@ -0,0 +1,16 @@ +<!doctype html> +<meta charset="utf-8"> +<title>JS is disabled on documents created without a browsing context</title> +<link rel="help" href="https://html.spec.whatwg.org/multipage/webappapis.html#concept-n-script"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function(t) { + var doc = document.implementation.createHTMLDocument(); + window.fail_test = t.unreached_func('should not have been called'); + + var script = doc.createElement('script'); + script.textContent = 'fail_test();'; + doc.documentElement.appendChild(script); +}, 'script on document returned by createHTMLDocument should not execute'); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/serve-json-then-js.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/serve-json-then-js.py new file mode 100644 index 0000000000..9610734d44 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/serve-json-then-js.py @@ -0,0 +1,21 @@ +# Respond with valid JSON to the first request with the given key, +# and with valid JavaScript to the second. Used for testing scenarios where +# the same request URL results in different responses on subsequent requests. +def main(request, response): + try: + stash_key = request.GET.first(b"key") + + run_count = request.server.stash.take(stash_key) + if not run_count: + run_count = 0 + + if run_count == 0: + response.headers.set(b"Content-Type", b"text/json") + response.content = '{"hello": "world"}' + else: + response.headers.set(b"Content-Type", b"application/javascript") + response.content = "export default 'hello';" + + request.server.stash.put(stash_key, run_count + 1) + except: + response.set_error(400, u"Not enough parameters") diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/serve-with-content-type.py b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/serve-with-content-type.py new file mode 100644 index 0000000000..675b3fc3eb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/serve-with-content-type.py @@ -0,0 +1,17 @@ +import os + +from wptserve.utils import isomorphic_decode + +def main(request, response): + directory = os.path.dirname(isomorphic_decode(__file__)) + + try: + file_name = request.GET.first(b"fn") + content_type = request.GET.first(b"ct") + with open(os.path.join(directory, isomorphic_decode(file_name)), u"rb") as fh: + content = fh.read() + + response.headers.set(b"Content-Type", content_type) + response.content = content + except: + response.set_error(400, u"Not enough parameters or file not found") diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onerror-insertion-point-1-helper.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onerror-insertion-point-1-helper.html new file mode 100644 index 0000000000..d9b0c84ca4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onerror-insertion-point-1-helper.html @@ -0,0 +1,2 @@ +Some <script src="nosuchscripthere.js" + onerror="document.write('text'); parent.writeDone(document.documentElement.textContent)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onerror-insertion-point-2-helper.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onerror-insertion-point-2-helper.html new file mode 100644 index 0000000000..a9ee80026a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onerror-insertion-point-2-helper.html @@ -0,0 +1,2 @@ +Some <script src="http://this is not parseable:-80/" + onerror="document.write('text'); document.close(); parent.writeDone(document.documentElement.textContent)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onload-insertion-point-helper.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onload-insertion-point-helper.html new file mode 100644 index 0000000000..f0236b4fbb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onload-insertion-point-helper.html @@ -0,0 +1,2 @@ +Some <script src="script-onload-insertion-point-helper.js" + onload="document.write('xt'); parent.writeDone(document.documentElement.textContent)"></script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onload-insertion-point-helper.js b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onload-insertion-point-helper.js new file mode 100644 index 0000000000..8a96a0b783 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/support/script-onload-insertion-point-helper.js @@ -0,0 +1 @@ +document.write("te"); diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/node-document.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/node-document.html new file mode 100644 index 0000000000..8676319b20 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/node-document.html @@ -0,0 +1,150 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Parsing XHTML: Node's node document</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="Parsing XHTML: Node's node document must be set to that of the element to which it will be appended"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#parsing-xhtml-documents"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + + +test(function() { + var doc = newXHTMLDocument(); + doc.body = doc.createElement('body'); + doc.body.innerHTML = '<template id="tmpl"></template>'; + + var template = doc.querySelector('#tmpl'); + + assert_not_equals(template, null, 'Template element should not be null'); + assert_not_equals(template.content, undefined, + 'Content attribute of template element should not be undefined'); + assert_not_equals(template.content, null, + 'Content attribute of template element should not be null'); + + assert_equals(template.ownerDocument, doc.body.ownerDocument, + 'Wrong template node owner document'); + var ownerDoc = template.content.ownerDocument; + assert_not_equals(ownerDoc, doc, 'Wrong template content owner document'); + assert_not_equals(ownerDoc, document, 'Wrong template content owner document'); + assert_equals(ownerDoc.defaultView, null, + 'Template content owner document should not have a browsing context'); + +}, 'Parsing XHTML: Node\'s node document must be set to that of the element ' + + 'to which it will be appended. Test empty template'); + + + +test(function() { + var doc = newXHTMLDocument(); + + doc.body = doc.createElement('body'); + doc.body.innerHTML = '<template id="tmpl"><div>Div content</div></template>'; + + var template = doc.querySelector('#tmpl'); + + assert_equals(template.ownerDocument, doc.body.ownerDocument, + 'Wrong template node owner document'); + + assert_not_equals(template, null, 'Template element should not be null'); + assert_not_equals(template.content, undefined, + 'Content attribute of template element should not be undefined'); + assert_not_equals(template.content, null, + 'Content attribute of template element should not be null'); + + var div = template.content.querySelector('div'); + assert_equals(template.content.ownerDocument, div.ownerDocument, + 'Wrong DIV node owner document'); + +}, 'Parsing XHTML: Node\'s node document must be set to that of the element ' + + 'to which it will be appended. Test not empty template'); + + + +test(function() { + var doc = newXHTMLDocument(); + doc.body = doc.createElement('body'); + doc.body.innerHTML = '' + + '<template id="tmpl"><div>Div content</div> And some more text' + + '<template id="tmpl2"><div>Template content</div></template>' + + '</template>'; + + var template = doc.querySelector('#tmpl'); + assert_not_equals(template, null, 'Template element should not be null'); + assert_equals(template.ownerDocument, doc, 'Wrong template node owner document'); + assert_not_equals(template.content, undefined, + 'Content attribute of template element should not be undefined'); + assert_not_equals(template.content, null, + 'Content attribute of template element should not be null'); + + var nestedTemplate = template.content.querySelector('#tmpl2'); + assert_not_equals(nestedTemplate, null, 'Nested template element should not be null'); + assert_not_equals(nestedTemplate.content, undefined, + 'Content attribute of nested template element should not be undefined'); + assert_not_equals(nestedTemplate.content, null, + 'Content attribute of nested template element should not be null'); + + assert_equals(nestedTemplate.ownerDocument, template.content.ownerDocument, + 'Wrong nested template node owner document'); + + + var div = nestedTemplate.content.querySelector('div'); + assert_equals(nestedTemplate.content.ownerDocument, div.ownerDocument, + 'Wrong DIV node owner document'); + +}, 'Parsing XHTML: Node\'s node document must be set to that of the element ' + + 'to which it will be appended. Test nested templates'); + + + +testInIFrame('../resources/template-child-nodes-div.xhtml', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + assert_equals(template.ownerDocument, doc, 'Wrong template node owner document'); + + assert_not_equals(template.content, undefined, + 'Content attribute of template element should not be undefined'); + assert_not_equals(template.content, null, + 'Content attribute of template element should not be null'); + + var div = template.content.querySelector('div'); + assert_equals(template.content.ownerDocument, div.ownerDocument, + 'Wrong DIV node owner document'); + +}, 'Parsing XHTML: Node\'s node document must be set to that of the element ' + + 'to which it will be appended. Test loading XHTML document from a file'); + + + +testInIFrame('../resources/template-child-nodes-nested.xhtml', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + assert_equals(template.ownerDocument, doc, 'Wrong template node owner document'); + + var nestedTemplate = template.content.querySelector('template'); + + assert_equals(nestedTemplate.ownerDocument, template.content.ownerDocument, + 'Wrong template node owner document'); + + var div = nestedTemplate.content.querySelector('div'); + assert_equals(nestedTemplate.content.ownerDocument, div.ownerDocument, + 'Wrong DIV node owner document'); + +}, 'Parsing XHTML: Node\'s node document must be set to that of the element ' + + 'to which it will be appended. Test loading of XHTML document ' + + 'with nested templates from a file'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/tag-name.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/tag-name.xhtml new file mode 100644 index 0000000000..a1e293d1cb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/tag-name.xhtml @@ -0,0 +1,16 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>tagName in template</title> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<template><div></div></template> +<div id="log"></div> +<script><![CDATA[ +test(function() { + assert_equals(document.getElementsByTagName("template")[0].content.firstChild.tagName, 'div', "tagName case"); +}, "tagName case"); +]]></script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/template-child-nodes.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/template-child-nodes.html new file mode 100644 index 0000000000..40abda5684 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-parsing-xhtml-documents/template-child-nodes.html @@ -0,0 +1,102 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Child nodes of template element in XHTML documents</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru"> +<meta name="assert" content="Child nodes of template element in XHTML documents are always appended to the template content (instead of template itself)"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#parsing-xhtml-documents"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function() { + var doc = newXHTMLDocument(); + + doc.body = doc.createElement('body'); + doc.body.innerHTML = '<template id="tmpl1">' + + '<div id="div1">This is div inside template</div>' + + '<div id="div2">This is another div inside template</div>' + + '</template>'; + + var template = doc.querySelector('#tmpl1'); + + assert_equals(template.childNodes.length, 0, + 'Wrong number of template child nodes'); + assert_equals(template.content.childNodes.length, 2, + 'Wrong number of template content child nodes'); + +}, 'Child nodes of template element in XHTML documents must be appended to template content'); + + + +test(function() { + var doc = newXHTMLDocument(); + doc.body = doc.createElement('body'); + doc.body.innerHTML = '<template id="tmpl1">' + + '<div id="div1">This is div inside template</div>' + + '<div id="div2">This is another div inside template</div>' + + '<template id="tmpl2">' + + '<div id="div3">This is div inside nested template</div>' + + '<div id="div4">This is another div inside nested template</div>' + + '</template>' + '</template>'; + + var template = doc.querySelector('#tmpl1'); + + assert_equals(template.childNodes.length, 0, + 'Wrong number of template child nodes'); + assert_equals(template.content.childNodes.length, 3, + 'Wrong number of template content child nodes'); + + var nestedTemplate = template.content.querySelector('#tmpl2'); + + assert_equals(nestedTemplate.childNodes.length, 0, + 'Wrong number of template child nodes'); + assert_equals(nestedTemplate.content.childNodes.length, 2, + 'Wrong number of nested template content child nodes'); + +}, 'Child nodes of nested template element in XHTML documents must be appended to template content'); + + + +testInIFrame('../resources/template-child-nodes-div.xhtml', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + assert_equals(template.childNodes.length, 0, + 'Wrong number of template child nodes'); + assert_equals(template.content.querySelectorAll('div').length, 2, + 'Wrong number of template content child nodes'); + +}, 'Child nodes of template element in XHTML documents must be appended to template content. ' + + 'Test loading XHTML document from a file'); + + +testInIFrame('../resources/template-child-nodes-nested.xhtml', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + assert_equals(template.childNodes.length, 0, + 'Wrong number of template child nodes'); + + var nestedTemplate = template.content.querySelector('template'); + + assert_equals(nestedTemplate.childNodes.length, 0, + 'Wrong number of template child nodes'); + + assert_equals(nestedTemplate.content.querySelectorAll('div').length, 2, + 'Wrong number of template content child nodes'); + +}, 'Child nodes of nested template element in XHTML documents must be appended to template content. ' + + 'Test loading XHTML document from a file'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-serializing-xhtml-documents/outerhtml.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-serializing-xhtml-documents/outerhtml.html new file mode 100644 index 0000000000..416a3bc615 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-serializing-xhtml-documents/outerhtml.html @@ -0,0 +1,71 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: serialize template contents instead of template element</title> +<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru"> +<meta name="assert" content="Template contents should be serialized instead of template element if serializing template element in XHTML document"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#serializing-xhtml-documents"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +test(function () { + var doc = newXHTMLDocument(); + var template = doc.createElement('template'); + + var div = doc.createElement('div'); + div.setAttribute('id', 'div1'); + div.innerHTML = 'some text'; + template.content.appendChild(div); + + assert_equals(template.outerHTML, '<template xmlns="http://www.w3.org/1999/xhtml"><div id="div1">some text</div></template>', + 'template element is serialized incorrectly'); + +}, 'Template contents should be serialized instead of template element if serializing template element'); + + + +test(function () { + var doc = newXHTMLDocument(); + var template = doc.createElement('template'); + var nestedTemplate = doc.createElement('template'); + + template.content.appendChild(nestedTemplate); + + var div = doc.createElement('div'); + div.setAttribute('id', 'div1'); + div.innerHTML = 'some text'; + nestedTemplate.content.appendChild(div); + + assert_equals(template.outerHTML, '<template xmlns="http://www.w3.org/1999/xhtml"><template><div id="div1">some text</div></template></template>', + 'template element is serialized incorrectly'); + + +}, 'Template contents should be serialized instead of template element if serializing template element. ' + + 'Test nested template'); + + +test(function () { + var doc = newXHTMLDocument(); + var template = doc.createElement('template'); + + var div = doc.createElement('div'); + div.setAttribute('id', 'div1'); + div.innerHTML = 'some text'; + template.content.appendChild(div); + doc.body = doc.createElement('body'); + doc.body.appendChild(template); + + assert_equals(doc.documentElement.outerHTML, '<html xmlns="http://www.w3.org/1999/xhtml"><body><template><div id="div1">some text</div></template></body></html>', + 'template element is serialized incorrectly'); + +}, 'Template contents should be serialized instead of template element if serializing template element. ' + + 'Test serializing whole document'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001-ref.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001-ref.html new file mode 100644 index 0000000000..55c8b2e30c --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001-ref.html @@ -0,0 +1,6 @@ +<!DOCTYPE html> +<title>Template Reftest Reference</title> +<link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"/> +<body> + <p>Test passes if there's no anything below this line.</p> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html new file mode 100644 index 0000000000..fc310f47c8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-001.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> + <title>Template Test: check that template content is invisible by default</title> + <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> + <link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#css-additions"> + <meta name="assert" content="Test checks that the template contents are hidden implicitly"> + <link rel="match" href="css-user-agent-style-sheet-test-001-ref.html"> +<body> + <p>Test passes if there's no anything below this line.</p> + <template> + <span style="color:red">Test fails if you can see this text</span> + </template> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-002.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-002.html new file mode 100644 index 0000000000..92f3d81eac --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-002.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> + <title>Template Test: check that template content is invisible by default</title> + <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> + <link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#css-additions"> + <meta name="assert" content="The template element itself must be hidden by default"> + <link rel="match" href="css-user-agent-style-sheet-test-001-ref.html"> +<body> + <p>Test passes if there's no anything below this line.</p> + <template style="border: 1px solid; width: 100px; height: 100px"> + <span style="color:red">Test fails if you can see this text or border around it</span> + </template> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-003.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-003.html new file mode 100644 index 0000000000..4c477fde79 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-css-user-agent-style-sheet/css-user-agent-style-sheet-test-003.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> + <title>HTML Templates: template content is invisible by default</title> + <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> + <link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#css-additions"> + <meta name="assert" content="The template element itself must be hidden by default"> + <link rel="match" href="css-user-agent-style-sheet-test-001-ref.html"> + <style> + template { + border: 1px solid; + width: 100px; + height: 100px; + } + </style> +<body> + <p>Test passes if there's no anything below this line.</p> + <template> + <span style="color:red">Test fails if you can see this text or border around it</span> + </template> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/template-clone-children.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/template-clone-children.html new file mode 100644 index 0000000000..c668d90953 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/template-clone-children.html @@ -0,0 +1,82 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Clone template node: All the children of template content are copied if 'copy children flag' set to true</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="Clone template node: all the children of template content are copied if 'copy children flag' set to true"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#node-clone-additions"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="tmpl1">' + + '<div id="div1">This is div inside template</div>' + + '<div id="div2">This is another div inside template</div>' + + '</template>'; + + var template = doc.querySelector('#tmpl1'); + var copy = template.cloneNode(true); + + assert_not_equals(copy.content, undefined, 'Template clone content attribute should not be undefined'); + assert_not_equals(copy.content, null, 'Template clone content attribute should not be null'); + + assert_equals(copy.content.childNodes.length, 2, + 'Wrong number of template content\'s copy child nodes'); + assert_not_equals(copy.content.querySelector('#div1'), null, + 'Template child node should be copied'); + assert_not_equals(copy.content.querySelector('#div2'), null, + 'Template child node should be copied'); + +}, 'Clone template node. Test call to cloneNode(true)'); + + + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="tmpl1">' + + '<div id="div1">This is div inside template</div>' + + '<div id="div2">This is another div inside template</div>' + + '</template>'; + + var template = doc.querySelector('#tmpl1'); + var copy = template.cloneNode(); + + assert_not_equals(copy.content, undefined, 'Template clone content attribute should not be undefined'); + assert_not_equals(copy.content, null, 'Template clone content attribute should not be null'); + + assert_equals(copy.content.childNodes.length, 0, + 'Wrong number of template content\'s copy child nodes'); + +}, 'Clone template node. Test call to cloneNode() with the default parameter ' + + '(false by default)'); + + + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="tmpl1">' + + '<div id="div1">This is div inside template</div>' + + '<div id="div2">This is another div inside template</div>' + + '</template>'; + + var template = doc.querySelector('#tmpl1'); + var copy = template.cloneNode(false); + + assert_not_equals(copy.content, undefined, 'Template clone content attribute is undefined'); + assert_not_equals(copy.content, null, 'Template clone content attribute is null'); + + assert_equals(copy.content.childNodes.length, 0, + 'Wrong number of template content\'s copy child nodes'); + +}, 'Clone template node. Test call to cloneNode(false)'); + + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/templates-copy-document-owner.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/templates-copy-document-owner.html new file mode 100644 index 0000000000..a2afc23041 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/additions-to-the-steps-to-clone-a-node/templates-copy-document-owner.html @@ -0,0 +1,126 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: ownerDocument of cloned template content is set to template content owner</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru"> +<meta name="assert" content="ownerDocument of cloned template content is set to template content owner"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#node-clone-additions"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +function checkOwnerDocument(node, doc) { + if ((node !== null) && (node !== undefined)) { + assert_equals(node.ownerDocument, doc, + 'Wrong ownerDocument of the template copy\'s node ' + node.nodeName); + for (var i = 0; i < node.childNodes.length; i++) { + if (node.childNodes[i].nodeType === Node.ELEMENT_NODE) { + checkOwnerDocument(node.childNodes[i], doc); + if (node.childNodes[i].nodeName === 'TEMPLATE') { + checkOwnerDocument(node.childNodes[i].content, doc); + } + } + } + } +} + + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="tmpl1">' + + '<div id="div1">This is div inside template</div>' + + '<div id="div2">This is another div inside template</div>' + + '</template>'; + + var template = doc.querySelector('#tmpl1'); + var copy = template.cloneNode(true); + + assert_equals(copy.content.childNodes.length, 2, + 'Wrong number of template content\'s copy child nodes'); + checkOwnerDocument(copy.content, template.content.ownerDocument); + +}, 'ownerDocument of cloned template content is set to template content owner. ' + + 'Test cloning with children'); + + + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="tmpl1">' + + '<div id="div1">This is div inside template</div>' + + '<div id="div2">This is another div inside template</div>' + + '</template>'; + + var template = doc.querySelector('#tmpl1'); + var copy = template.cloneNode(false); + + assert_equals(copy.content.childNodes.length, 0, + 'Wrong number of template content\'s copy child nodes'); + checkOwnerDocument(copy.content, template.content.ownerDocument); + +}, 'ownerDocument of cloned template content is set to template content owner. ' + + 'Test cloning without children'); + + + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="tmpl1">' + + '<div id="div1">This is div inside template</div>' + + '<div id="div2">This is another div inside template</div>' + + '</template>'; + + var template = doc.querySelector('#tmpl1'); + var copy = template.cloneNode(); + + assert_equals(copy.content.childNodes.length, 0, + 'Wrong number of template content\'s copy child nodes'); + checkOwnerDocument(copy.content, template.content.ownerDocument); + +}, 'ownerDocument of cloned template content is set to template content owner. ' + + 'Test cloneNode() with no arguments (false by default)'); + + + +test(function () { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="tmpl1">' + + '<div id="div1">This is div inside template</div>' + + '<div id="div2">This is another div inside template</div>' + + '<template id="tmpl2">' + + '<div id="div3">This is div inside nested template</div>' + + '<div id="div4">This is another div inside nested template</div>' + + '</template>' + + '</template>'; + + var template = doc.querySelector('#tmpl1'); + var copy = template.cloneNode(true); + + assert_equals(copy.content.childNodes.length, 3, + 'Wrong number of template content\'s copy child nodes'); + checkOwnerDocument(copy.content, template.content.ownerDocument); + +}, 'ownerDocument of cloned template content is set to template content owner. ' + + 'Test cloning nested template'); + + + +testInIFrame('../resources/template-contents.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.body.querySelector('template'); + var copy = template.cloneNode(true); + + checkOwnerDocument(copy.content, template.content.ownerDocument); + +}, 'ownerDocument of cloned template content is set to template content owner. ' + + 'Test loading HTML document from file'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-document-type.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-document-type.html new file mode 100644 index 0000000000..d063acded9 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-document-type.html @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: The template contents owner document type is HTML document</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="The template contents owner document type is HTML document, if template is declared in HTML document"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#definitions"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +testInIFrame('../resources/template-contents.html', function(context) { + var doc = context.iframes[0].contentDocument; + var template = doc.querySelector('template'); + var content_owner = template.content.ownerDocument; + + assert_class_string(content_owner, 'Document', + 'Template content owner should be a document'); + assert_equals(content_owner.createElement('DIV').localName, 'div', + 'Template content owner should be an HTML document'); + +}, 'The template contents owner document type is HTML document ' + + '(case when document has browsing context and the template ' + + 'is created by HTML parser)'); + + +testInIFrame('../resources/template-contents.html', function(context) { + var doc = context.iframes[0].contentDocument; + var template = doc.createElement('template'); + var content_owner = template.content.ownerDocument; + var div = doc.createElement('DIV'); + template.appendChild(div); + + doc.body.appendChild(template); + + assert_class_string(content_owner, 'Document', + 'Template content owner should be a document'); + assert_equals(div.localName, 'div', + 'Template content owner should be an HTML document'); + +}, 'The template contents owner document type is HTML document ' + + '(case when document has browsing context and the template ' + + 'is created by createElement())'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + var content_owner = template.content.ownerDocument; + var div = doc.createElement('DIV'); + template.appendChild(div); + + doc.body.appendChild(template); + + assert_class_string(content_owner, 'Document', + 'Template content owner should be a document'); + assert_equals(div.localName, 'div', + 'Template content owner should be an HTML document'); + +}, 'The template contents owner document type is HTML document ' + + '(case when document has no browsing context and the template is created ' + + 'by createElement())'); + +test(function() { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template><div>Hello!</div></template>'; + var template = doc.querySelector('template'); + var content_owner = template.content.ownerDocument; + + assert_class_string(content_owner, 'Document', + 'Template content owner should be a document'); + assert_equals(content_owner.createElement('DIV').localName, 'div', + 'Template content owner should be an HTML document'); + +}, 'The template contents owner document type is HTML document ' + + '(case when document has no browsing context and the template is created via innerHTML)'); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-001.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-001.html new file mode 100644 index 0000000000..a087f788e5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-001.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: The template contents owner document (no browsing context)</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="Even if template's enclosing document has no browsing context, it gets its own template contents owner"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#definitions"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + doc.body.appendChild(template); + + assert_not_equals(template.content.ownerDocument, doc, 'Wrong template content owner'); + +}, 'Test the template contents owner document when enclosing document has ' + + 'no browsing content. Template element is created by createElement()'); + + + +test(function() { + var doc = newHTMLDocument(); + + doc.body.innerHTML = '<template><div>some text</div></template>'; + + var template = doc.querySelector('template'); + + assert_not_equals(template.content.ownerDocument, doc, 'Wrong template content owner'); + +}, 'Test the template contents owner document when enclosing document has ' + + 'no browsing content. Template element is created by innerHTML'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html new file mode 100644 index 0000000000..cf2e30b643 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents-owner-test-002.html @@ -0,0 +1,67 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: The template contents owner document (there's browsing context)</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="If template's enclosing document has browsing context, then templates content owner must be a new Document node without browsing context"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#definitions"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +testInIFrame(null, function(context) { + var doc = context.iframes[0].contentDocument; + var template = doc.createElement('template'); + + var div = doc.createElement('div'); + div.setAttribute('id', 'div1'); + + template.appendChild(div); + + doc.body.appendChild(template); + + // doc has browsing context. There should be another document as a template + // content owner + assert_not_equals(template.content.ownerDocument, doc, 'Wrong template owner document'); + +}, 'The template contents owner document must be different from template owner document,' + + ' which has browsing context. Template element is created by createElement()'); + + + +testInIFrame(null, function(context) { + var doc = context.iframes[0].contentDocument; + + doc.body.innerHTML = '<template><div>some text</div></template>'; + + var template = doc.querySelector('template'); + + // doc has browsing context. There should be another document as a template + // content owner + assert_not_equals(template.content.ownerDocument, doc, 'Wrong template owner document'); + +}, 'The template contents owner document must be different from template owner document,' + + ' which has browsing context. Template element is created via innerHTML'); + + + +testInIFrame('../resources/template-contents.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + // doc has browsing context. There should be another document as a template + // content owner + assert_not_equals(template.content.ownerDocument, doc, 'Wrong template owner document'); + +}, 'The template contents owner document must be different from template owner document,' + + ' which has browsing context. Template element is created by HTML parser'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents.html new file mode 100644 index 0000000000..4a61dc8d3b --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/definitions/template-contents.html @@ -0,0 +1,172 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: The template contents is a DocumentFragment</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="assert" content="The template contents must be a DocumentFragment"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#definitions"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + doc.body.appendChild(template); + + assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE, + 'Template content should be a DocumentFragment'); + + assert_class_string(template.content, 'DocumentFragment', + 'Template content class should be a DocumentFragment'); + +}, 'The template contents must be a DocumentFragment (empty template)'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<div>This is a div</div><span>This is a span</span>'; + + doc.body.appendChild(template); + + assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE, + 'Template content should be a DocumentFragment'); + + assert_class_string(template.content, 'DocumentFragment', + 'Template content class should be a DocumentFragment'); + +}, 'The template contents must be a DocumentFragment (non empty template)'); + + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<div>This is a div</div>'; + + doc.body.appendChild(template); + + assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE, + 'Template content should be a documentFragment'); + +}, 'The template contents must be a DocumentFragment (non empty template ' + + 'containing div which is an Element instance)'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = 'Some text'; + + doc.body.appendChild(template); + + assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE, + 'Template content should be a documentFragment'); + + assert_class_string(template.content, 'DocumentFragment', + 'Template content class should be a DocumentFragment'); + +}, 'The template contents must be a DocumentFragment (not empty template ' + + 'containing text node)'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + template.innerHTML = '<template id="t2">Some text</template>'; + + doc.body.appendChild(template); + + assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE, + 'Template content should be a documentFragment'); + assert_class_string(template.content, 'DocumentFragment', + 'Template content class should be a DocumentFragment'); + + var nestedTemplate = template.content.querySelector("#t2"); + assert_equals(nestedTemplate.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE, + 'Nested template content should be a documentFragment'); + + assert_class_string(nestedTemplate.content, 'DocumentFragment', + 'Nested template content class should be a DocumentFragment'); + + +}, 'The template contents must be a DocumentFragment (nested template ' + + 'containing a text node)'); + + +testInIFrame('../resources/template-contents-empty.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE, + 'Template content should be a documentFragment'); + assert_class_string(template.content, 'DocumentFragment', + 'Template content class should be a DocumentFragment'); + + +}, 'The template contents must be a DocumentFragment (the empty template tag ' + + 'inside HTML file loaded in iframe)'); + + +testInIFrame('../resources/template-contents.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE, + 'Template content should be a documentFragment'); + assert_class_string(template.content, 'DocumentFragment', + 'Template content class should be a DocumentFragment'); + +}, 'The template contents must be a DocumentFragment (non empty template ' + + 'tag inside HTML file loaded in iframe)'); + + +testInIFrame('../resources/template-contents-text.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE, + 'Template content should be a documentFragment'); + assert_class_string(template.content, 'DocumentFragment', + 'Template content class should be a DocumentFragment'); + +}, 'The template contents must be a DocumentFragment (the template tag ' + + 'with some text inside HTML file loaded in iframe)'); + + +testInIFrame('../resources/template-contents-nested.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + + assert_equals(template.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE, + 'Template content should be a documentFragment'); + assert_class_string(template.content, 'DocumentFragment', + 'Template content class should be a DocumentFragment'); + + var nestedTemplate = template.content.querySelector("template"); + + assert_equals(nestedTemplate.content.nodeType, Node.DOCUMENT_FRAGMENT_NODE, + 'Nested template content should be a documentFragment'); + assert_class_string(nestedTemplate.content, 'DocumentFragment', + 'Nested template content class should be a DocumentFragment'); + +}, 'The template contents must be a DocumentFragment (the template tag ' + + 'with nested template tag inside HTML file loaded in iframe)'); +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/innerhtml-on-templates/innerhtml.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/innerhtml-on-templates/innerhtml.html new file mode 100644 index 0000000000..0968b37f92 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/innerhtml-on-templates/innerhtml.html @@ -0,0 +1,105 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: innerHTML of template element replaces all referenced by the content attribute</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru"> +<meta name="assert" content="innerHTML of template element replaces all referenced by the content attribute"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#innerhtml-on-templates"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +test(function () { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + var div1 = doc.createElement('div'); + div1.setAttribute('id', 'div1'); + template.content.appendChild(div1); + + assert_not_equals(template.content.querySelector('#div1'), null, + 'Element should present in template content'); + + template.innerHTML = '<div id="div2"></div>'; + + assert_equals(template.content.querySelector('#div1'), null, + 'Template content should be replaced by innerHTML'); + assert_not_equals(template.content.querySelector('#div2'), null, + 'Element should present in template content'); + +}, 'innerHTML of template element replaces all referenced by the content attribute'); + + +test(function () { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + var div1 = doc.createElement('div'); + div1.setAttribute('id', 'div1'); + template.content.appendChild(div1); + + assert_not_equals(template.content.querySelector('#div1'), null, + 'Element should present in template content'); + + template.innerHTML = ''; + + assert_false(template.content.hasChildNodes(), + 'Template content should be removed by innerHTML'); + +}, 'innerHTML of template element replaces all referenced by the content attribute. ' + + 'Test empty HTML string'); + + +test(function () { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + var nestedTemplate = doc.createElement('template'); + + template.content.appendChild(nestedTemplate); + + var div1 = doc.createElement('div'); + div1.setAttribute('id', 'div1'); + nestedTemplate.content.appendChild(div1); + + assert_not_equals(nestedTemplate.content.querySelector('#div1'), null, + 'Element should present in template content'); + + nestedTemplate.innerHTML = '<div id="div2"></div>'; + + assert_equals(nestedTemplate.content.querySelector('#div1'), null, + 'Template content should be replaced by innerHTML'); + assert_not_equals(nestedTemplate.content.querySelector('#div2'), null, + 'Element should present in template content'); + +}, 'innerHTML of template element replaces all referenced by the content attribute. ' + + 'Test nested template'); + + +testInIFrame('../resources/template-contents.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.querySelector('template'); + assert_not_equals(template.content.querySelector('div'), null, + 'Div element should present in template content'); + + template.innerHTML = '<span>span internals</span>'; + + assert_equals(template.content.querySelector('div'), null, + 'div element should be replaced by span in template content'); + + assert_not_equals(template.content.querySelector('span'), null, + 'span element should present in template content'); + + +}, 'innerHTML of template element replaces all referenced by the content attribute. ' + + 'Test loading of HTML document from a file'); + + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-body.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-body.html new file mode 100644 index 0000000000..2cb149853f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-body.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <title>The file contains several </template> tag in HTML body without start one</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +</head> +<body> + </template> + <div>The file contains several </template> tag in HTML body without start one</div> + </template></template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-head.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-head.html new file mode 100644 index 0000000000..02d0c7be65 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/end-template-tag-in-head.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + </template> + <title>The file contains several </template> tag in HTML head without start one</title> + </template></template> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> + </template> +</head> +<body> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/frameset-end-tag.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/frameset-end-tag.html new file mode 100644 index 0000000000..b84d55595f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/frameset-end-tag.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <title>The file contains frameset with the template and frameset end tag in it</title> + <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +</head> +<frameset> + <template></frameset></template> +</frameset> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-div-no-end-tag.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-div-no-end-tag.html new file mode 100644 index 0000000000..e4e45bcea5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-div-no-end-tag.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <title>The file contains template element with open div tag, but without end div tag, in the head</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> + <template> + <div>Hello, template + </template> +</head> +<body> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-table-no-end-tag.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-table-no-end-tag.html new file mode 100644 index 0000000000..9db2b4af06 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/head-template-contents-table-no-end-tag.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<head> + <title>The file contains template element with open table, tr, td tags, but without end td, tr, table tags, in the head</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> + <template> + <table> + <tr> + <td>Hello, cell one! + </template> +</head> +<body> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/html-start-tag.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/html-start-tag.html new file mode 100644 index 0000000000..0de652cf36 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/html-start-tag.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html tabindex="5"> +<head> + <title>The file contains html root element with attributes and some in the body</title> + <link rel="author" title="Sergey G. Grekhovv" href="mailto:sgrekhov@unipro.ru"> +</head> +<body> +<template id="tmpl"><html class="htmlClass"></html></template><html id="htmlId" tabindex="5"> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-div.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-div.xhtml new file mode 100644 index 0000000000..14db5004dc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-div.xhtml @@ -0,0 +1,14 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Template tag with children div tags inside</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"/> +</head> +<body> + <p>Template tag with div tags inside</p> + <template> + <div>This is div inside template</div> + <div>This is another div inside template</div> + </template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-nested.xhtml b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-nested.xhtml new file mode 100644 index 0000000000..406fa6c3d4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-child-nodes-nested.xhtml @@ -0,0 +1,16 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>Template tag with children div tags inside another template tag</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"/> +</head> +<body> + <p>Template tag with children div tags inside another template tag</p> + <template> + <template> + <div>This is div inside template</div> + <div>This is another div inside template</div> + </template> + </template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-attribute.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-attribute.html new file mode 100644 index 0000000000..b9dd5f47a8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-attribute.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <title>Empty template tag with attribute content</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<head> +<body> + <template content='some text'></template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-body.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-body.html new file mode 100644 index 0000000000..a1f246fd63 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-body.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <title>BODY tag inside template</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<head> +<body> + <template><body></body></template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-div-no-end-tag.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-div-no-end-tag.html new file mode 100644 index 0000000000..304acf3025 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-div-no-end-tag.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <title>Div tag inside template tag</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +</head> +<body> + <template> + <div>Hello, template + </template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-empty.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-empty.html new file mode 100644 index 0000000000..f1a539cc08 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-empty.html @@ -0,0 +1,11 @@ +<!DOCTYPE html> +<html> +<head> + <title>Empty template tag</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<head> +<body> + <template> + </template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-frameset.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-frameset.html new file mode 100644 index 0000000000..4331367df3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-frameset.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <title>FRAMESET tag inside template</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<head> +<body> + <template><frameset></frameset></template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-head.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-head.html new file mode 100644 index 0000000000..1e3a337e8d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-head.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <title>HEAD tag inside template</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<head> +<body> + <template><head></head></template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-html.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-html.html new file mode 100644 index 0000000000..5dd3a28e6a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-html.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <title>HTML tag inside template</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<head> +<body> + <template><html></html></template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-nested.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-nested.html new file mode 100644 index 0000000000..dc2dc6f15f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-nested.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> + <title>Contains second template tag inside template tag</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<body> + <template> + <template> + <div>Inside nested template</div> + </template> + </template> +</body> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-table-no-end-tag.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-table-no-end-tag.html new file mode 100644 index 0000000000..4639b4dc8e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-table-no-end-tag.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<head> + <title>The file contains template element with open table, tr, td tags, without end td, tr, table tags</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +</head> +<body> + <template> + <table> + <tr> + <td>Hello, cell one! + </template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-text.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-text.html new file mode 100644 index 0000000000..a401848efc --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents-text.html @@ -0,0 +1,10 @@ +<!DOCTYPE html> +<html> +<head> + <title>Some text inside template tag</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +</head> +<body> + <template>Some text</template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents.html new file mode 100644 index 0000000000..07256c06a3 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-contents.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <title>Div tag inside template tag</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +</head> +<body> + <template> + <div>Hello, template</div> + </template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-body.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-body.html new file mode 100644 index 0000000000..d64848c8db --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-body.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <title>Div tag inside template tag</title> + <link rel="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +</head> +<body> + <template> + <div>Hello, template</div> + </template> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-frameset.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-frameset.html new file mode 100644 index 0000000000..4801178454 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-frameset.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<head> + <title>Template tag inside frameset</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +</head> +<frameset> + <template> + <div>Hello, template</div> + </template> +</frameset> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-head.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-head.html new file mode 100644 index 0000000000..6bab00ea99 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/template-descendant-head.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> +<head> + <title>Template tag inside head</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> + <template> + <div>Hello, template</div> + </template> +</head> +<body> + Nothing interesting here +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/two-templates.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/two-templates.html new file mode 100644 index 0000000000..f6e9ab58e8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/resources/two-templates.html @@ -0,0 +1,17 @@ +<!DOCTYPE html> +<html> +<head> + <title>The file contains two template elements</title> + <link rel="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +</head> +<body> + <template id="template1"> + <div>Hello, template</div> + </template> + + <template id="template2"> + <div>Hello, from second template</div> + </template> + +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/serializing-html-templates/outerhtml.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/serializing-html-templates/outerhtml.html new file mode 100644 index 0000000000..1539afbe1e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/serializing-html-templates/outerhtml.html @@ -0,0 +1,70 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: serialize template contents instead of template element</title> +<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru"> +<meta name="assert" content="template contents should be serialized instead of template element if serializing template element"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#serializing-html-templates"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +test(function () { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + var div = doc.createElement('div'); + div.setAttribute('id', 'div1'); + div.innerHTML = 'some text'; + template.content.appendChild(div); + + assert_equals(template.outerHTML, '<template><div id="div1">some text</div></template>', + 'template element is serialized incorrectly'); + +}, 'Template contents should be serialized instead of template element if serializing template element'); + + + +test(function () { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + var nestedTemplate = doc.createElement('template'); + + template.content.appendChild(nestedTemplate); + + var div = doc.createElement('div'); + div.setAttribute('id', 'div1'); + div.innerHTML = 'some text'; + nestedTemplate.content.appendChild(div); + + assert_equals(template.outerHTML, '<template><template><div id="div1">some text</div></template></template>', + 'template element is serialized incorrectly'); + + +}, 'Template contents should be serialized instead of template element if serializing template element. ' + + 'Test nested template'); + + +test(function () { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + var div = doc.createElement('div'); + div.setAttribute('id', 'div1'); + div.innerHTML = 'some text'; + template.content.appendChild(div); + doc.body.appendChild(template); + + assert_equals(doc.documentElement.outerHTML, '<html><head><title>Test Document</title></head><body><template><div id="div1">some text</div></template></body></html>', + 'template element is serialized incorrectly'); + +}, 'Template contents should be serialized instead of template element if serializing template element. ' + + 'Test serializing whole document'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/content-attribute.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/content-attribute.html new file mode 100644 index 0000000000..b4c11b841f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/content-attribute.html @@ -0,0 +1,114 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Content attribute of template element is read-only</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="Content attribute of template element is read-only"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + + assert_readonly(template, 'content', + 'Content attribute of template element should be read-only'); + +}, 'Content attribute of template element is read-only. ' + + 'Test empty template'); + + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + var el1 = doc.createElement('div'); + var el2 = doc.createElement('span'); + el1.appendChild(el2); + + template.content.appendChild(el1); + + assert_readonly(template, 'content', + 'Content attribute of template element should be read-only'); + +}, 'Content attribute of template element is read-only. ' + + 'Test not empty template populated by appendchild()'); + + +test(function() { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template>Text<div>DIV</div></template>'; + + var template = doc.querySelector('template'); + + assert_readonly(template, 'content', + 'Content attribute of template element should be read-only'); + +}, 'Content attribute of template element is read-only. ' + + 'Test not empty template populated by innerHTML'); + + +test(function() { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="template1" content="Some text as a content"></template>'; + + var template = doc.querySelector('#template1'); + + assert_readonly(template, 'content', + 'Content attribute of template element should be read-only'); + +}, 'Content attribute of template element is read-only. ' + + 'Test that custom content attribute named \'content\' doesn\'t ' + + 'make content IDL attribute writable'); + + +test(function() { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template id="template1" content="<div id=div1>Div content</div>"></template>'; + + var template = doc.querySelector('#template1'); + + assert_readonly(template, 'content', + 'Content attribute of template element should be read-only'); + + assert_equals(template.content.childNodes.length, 0, + 'Content attribute of template element should be read-only'); + +}, 'Content attribute of template element is read-only. ' + + 'Test that custom content attribute named \'content\' doesn\'t ' + + 'affect content IDL attribute'); + + +testInIFrame('../resources/template-contents-attribute.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.body.querySelector('template'); + + assert_readonly(template, 'content', + 'Content attribute of template element should be read-only'); + +}, 'Content attribute of template element is read-only. ' + + 'Text value of content attribute of template tag should be ignored, ' + + 'when loading document from a file'); + + +testInIFrame('../resources/template-contents.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template = doc.body.querySelector('template'); + + assert_readonly(template, 'content', + 'Content attribute of template element should be read-only'); + +}, 'Content attribute of template element is read-only. ' + + 'Test content attribute of a document loaded from a file'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/node-document-changes.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/node-document-changes.html new file mode 100644 index 0000000000..0c60c10738 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/node-document-changes.html @@ -0,0 +1,192 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: When node's document changes its owner document should be changed</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="When a template element's node document changes, the template element's content DocumentFragment must be adopted into the new node document's template contents owner document"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +test(function() { + var doc1 = newHTMLDocument(); + var template = doc1.createElement('template'); + + assert_equals(template.ownerDocument, doc1, 'Wrong template node owner document'); + assert_not_equals(template.content.ownerDocument, doc1, + 'Wrong template content owner document'); + + var doc2 = newHTMLDocument(); + var template2 = doc2.createElement('template'); + doc2.body.appendChild(template); + + assert_equals(template.ownerDocument, template2.ownerDocument, + 'Template node owner document should be changed'); + assert_equals(template.content.ownerDocument, template2.content.ownerDocument, + 'Template content owner document should be changed'); + +}, 'Changing of template element\'s node document. ' + + 'Test that ownerDocument of an empty template and its content changes'); + +test(function() { + var doc1 = newHTMLDocument(); + doc1.body.innerHTML = '<template id="tmpl"><div>Div content</div> And some more text</template>'; + + var template = doc1.querySelector('#tmpl'); + + assert_equals(template.ownerDocument, doc1, + 'Wrong template node owner document'); + assert_not_equals(template.content.ownerDocument, doc1, + 'Wrong template content owner document'); + + var doc2 = newHTMLDocument(); + var template2 = doc2.createElement('template'); + doc2.body.appendChild(template); + + assert_equals(template.ownerDocument, template2.ownerDocument, + 'Template node owner document should be changed'); + assert_equals(template.content.ownerDocument, template2.content.ownerDocument, + 'Template content owner document should be changed'); + + assert_equals(template.content.querySelector('div').ownerDocument, + template2.content.ownerDocument, + 'Template content descendants owner document should be changed'); + +}, 'Changing of template element\'s node document. ' + + 'Test that ownerDocument of a not empty template and its content changes'); + +test(function() { + var doc1 = newHTMLDocument(); + doc1.body.innerHTML = '' + + '<template id="tmpl"><div>Div content</div> And some more text' + + '<template id="tmpl2"><div>Template content</div></template>' + + '</template>'; + + var template = doc1.querySelector('#tmpl'); + + assert_equals(template.ownerDocument, doc1, 'Wrong template node owner document'); + assert_not_equals(template.content.ownerDocument, doc1, + 'Wrong template content owner document'); + + var nestedTemplate = template.content.querySelector('#tmpl2'); + + assert_equals(nestedTemplate.ownerDocument, template.content.ownerDocument, + 'Wrong nested template node owner document'); + assert_equals(nestedTemplate.content.ownerDocument, template.content.ownerDocument, + 'Wrong nested template content owner document'); + + var doc2 = newHTMLDocument(); + var template2 = doc2.createElement('template'); + doc2.body.appendChild(template); + + assert_equals(template.ownerDocument, template2.ownerDocument, + 'Template node owner document should be changed'); + assert_equals(template.content.ownerDocument, template2.content.ownerDocument, + 'Template content owner document should be changed'); + assert_equals(template.content.querySelector('div').ownerDocument, + template2.content.ownerDocument, + 'Template content descendants owner document should be changed'); + + assert_equals(nestedTemplate.ownerDocument, + template2.content.ownerDocument, + 'Nested template node owner document should be changed'); + assert_equals(nestedTemplate.content.ownerDocument, + template2.content.ownerDocument, + 'Nested template content owner document should be changed'); + assert_equals(nestedTemplate.content.querySelector('div').ownerDocument, + template2.content.ownerDocument, + 'Owner document of the nested template content descendants should be changed'); + +}, 'Changing of template element\'s node document. ' + + 'Test that ownerDocument of nested template and its content changes'); + +testInIFrame('../resources/template-contents.html', function(context) { + var doc1 = context.iframes[0].contentDocument; + + var template = doc1.body.querySelector('template'); + + var doc2 = newHTMLDocument(); + var template2 = doc2.createElement('template'); + doc2.body.appendChild(template); + + assert_equals(template.ownerDocument, template2.ownerDocument, + 'Template node owner document should be changed'); + assert_equals(template.content.ownerDocument, + template2.content.ownerDocument, + 'Template content owner document should be changed'); + assert_equals(template.content.querySelector('div').ownerDocument, + template2.content.ownerDocument, + 'Template content descendants owner document should be changed'); + +}, 'Changing of template element\'s node document. ' + + 'Test document loaded from a file'); + +testInIFrame('../resources/template-contents.html', function(context) { + var doc1 = context.iframes[0].contentDocument; + + var doc2 = newHTMLDocument(); + var template = doc2.createElement('template'); + var div = doc2.createElement('div'); + template.content.appendChild(div); + + doc1.body.appendChild(template); + + assert_not_equals(template.ownerDocument, doc2, + 'Template node owner document should be changed'); + assert_not_equals(template.content.ownerDocument, doc2, + 'Template content owner document should be changed'); + assert_not_equals(div.ownerDocument, doc2, + 'Template content descendants owner document should be changed'); + + assert_equals(template.ownerDocument, doc1, + 'Template node owner document should be changed'); + // doc1 has browsing context so it cannot be template.content.ownerDocument + assert_not_equals(template.content.ownerDocument, doc1, + 'Template content owner document should be a new document'); + assert_equals(div.ownerDocument, template.content.ownerDocument, + 'Template content descendants owner document should be ' + + 'template content document owner'); + +}, 'Changing of template element\'s node document. ' + + 'Adobt template element into a document that has a browsing context'); + +testInIFrame('../resources/template-contents.html', function(context) { + var doc1 = context.iframes[0].contentDocument; + + var template = doc1.querySelector('template'); + var div = template.content.querySelector('div'); + var templateContentOwner = template.content.ownerDocument; + + var doc2 = document; + + doc2.body.appendChild(template); + + assert_not_equals(template.ownerDocument, doc1, + 'Template node owner document should be changed'); + assert_not_equals(template.content.ownerDocument, templateContentOwner, + 'Template content owner document should be changed'); + assert_not_equals(div.ownerDocument, templateContentOwner, + 'Template content descendants owner document should be changed'); + + assert_equals(template.ownerDocument, doc2, + 'Template node owner document should be changed'); + // doc2 has browsing context, so it cannot be template.content.ownerDocument + assert_not_equals(template.content.ownerDocument, doc2, + 'Template content owner document should be a new document'); + assert_equals(div.ownerDocument, template.content.ownerDocument, + 'Template content descendants owner document should be ' + + 'template content document owner'); + +}, 'Changing of template element\'s node document. ' + + 'Test the case when both old and new owner documents of template element ' + + 'have browsing context'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant.html new file mode 100644 index 0000000000..caa1beab47 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-as-a-descendant.html @@ -0,0 +1,135 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Template element as a descendant of the body element.</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="Template element can be a descendant of the body element"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-template-element"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +function templateIsAChild(element) { + element.innerHTML = '<template>some text</template>'; + + assert_not_equals(element.querySelector('template'), null, + 'Template element should be a descendant of the ' + element.tagName + ' element'); +} + +function templateIsDisallowedAsAChild(element) { + element.innerHTML = '<template>some text</template>'; + + assert_equals(element.querySelector('template'), null, + 'Template element should not be allowed as a descendant of the ' + element.tagName + ' element'); +} + +function templateIsAnIndirectChild(element) { + element.innerHTML = '<div><template>some text</template></div>'; + + assert_not_equals(element.querySelector('template'), null, + 'Template element should be a descendant of the ' + element.tagName + ' element'); +} + +function templateIsDisallowedAsAnIndirectChild(element) { + element.innerHTML = '<div><template>some text</template></div>'; + + assert_equals(element.querySelector('template'), null, + 'Template element should not be allowed as indirect descendant of the ' + element.tagName + ' element'); +} + +function templateIsAnAppendedChild(doc, element) { + var template = doc.createElement('template'); + + element.appendChild(template); + + assert_not_equals(element.querySelector('template'), null, + 'Template element should be a descendant of the ' + element.tagName + ' element'); +} + +function templateIsAnAppendedIndirectChild(doc, element) { + var template = doc.createElement('template'); + var div = doc.createElement('div'); + div.appendChild(template); + + element.appendChild(div); + + assert_not_equals(element.querySelector('template'), null, + 'Template element should be a descendant of the ' + element.tagName + ' element'); +} + +var doc = newHTMLDocument(); +var frameset = doc.createElement('frameset'); + +var parameters = [['Template element as a descendant of the BODY element. ' + + 'Template element is created by innerHTML', + doc.body], + ['Template element as a descendant of the HEAD element. ' + + 'Template element is created by innerHTML', + doc.head], + ]; +// Template element as a descendant of the HEAD and BODY elements +generate_tests(templateIsAChild, parameters); + +parameters = [['Template element as a descendant of the FRAMESET element. ' + + 'Template element is created by innerHTML', + frameset], + ]; +// Template element should be disallowed as a descendant of the FRAMESET elements +generate_tests(templateIsDisallowedAsAChild, parameters); + + +parameters = [['Template element as an indirect descendant of the BODY element. ' + + 'Template element is created by innerHTML', + doc.body], + ['Template element as an indirect descendant of the HEAD element. ' + + 'Template element is created by innerHTML', + doc.head], + ]; +// Template element as an indirect descendant of the HEAD, BODY and FRAMESET elements +generate_tests(templateIsAnIndirectChild, parameters); + +parameters = [['Template element as an indirect descendant of the FRAMESET element. ' + + 'Template element is created by innerHTML', + frameset], + ]; +// Template element should be disallowed as an indirect descendant of the FRAMESET elements +generate_tests(templateIsDisallowedAsAnIndirectChild, parameters); + + + +parameters = [['Template element as a descendant of the BODY element. ' + + 'Template element is appended by appendChild()', + doc, doc.body], + ['Template element as a descendant of the HEAD element. ' + + 'Template element is appended by appendChild()', + doc, doc.head], + ['Template element as a descendant of the FRAMESET element. ' + + 'Template element is appended by appendChild()', + doc, frameset] + ]; +// Template element as a descendant of the HEAD, BODY and FRAMESET elements +generate_tests(templateIsAnAppendedChild, parameters); + + + +parameters = [['Template element as an indirect descendant of the BODY element. ' + + 'Template element is appended by appendChild()', + doc, doc.body], + ['Template element as an indirect descendant of the HEAD element. ' + + 'Template element is appended by appendChild()', + doc, doc.head], + ['Template element as an indirect descendant of the FRAMESET element. ' + + 'Template element is appended by appendChild()', + doc, frameset] + ]; +// Template element as a descendant of the HEAD, BODY and FRAMESET elements +generate_tests(templateIsAnAppendedIndirectChild, parameters); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-construction-in-inactive-document-crash.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-construction-in-inactive-document-crash.html new file mode 100644 index 0000000000..496a47b2c5 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-construction-in-inactive-document-crash.html @@ -0,0 +1,5 @@ +<iframe id="i"></iframe> +<script> +i.contentDocument.documentElement.appendChild(document.body); +</script> +<template><script></script></template> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy.html new file mode 100644 index 0000000000..823c0c830f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-hierarcy.html @@ -0,0 +1,81 @@ +<!DOCTYPE html> +<meta name="author" title="Takayoshi Kochi" href="mailto:kochi@chromium.org"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<div id=log></div> +<div id="parent"> + <template id="tmpl"><span>Happy Templating!</span></template> +</div> +<script> +test(() => { + var parent = document.getElementById('parent'); + var tmpl = document.getElementById('tmpl'); + + assert_equals(tmpl.innerHTML, '<span>Happy Templating!</span>'); + var span = tmpl.content.querySelector('span'); + + // Hierarchy checks at various combinations. + assert_throws_dom('HierarchyRequestError', () => { + tmpl.content.appendChild(parent); + }, 'Template content should throw if any of ancestor is being appended.'); + assert_throws_dom('HierarchyRequestError', () => { + tmpl.content.appendChild(tmpl); + }, 'Template content should throw if its host is being appended.'); + assert_throws_dom('HierarchyRequestError', () => { + span.appendChild(parent); + }, 'Template content child should throw if any of ancestor is being appended.'); + assert_throws_dom('HierarchyRequestError', () => { + span.appendChild(tmpl); + }, 'Template content child should throw template\'s host is being appended.'); +}, "Template content should throw when its ancestor is being appended."); + +test(() => { + var parent = document.getElementById('parent'); + var tmpl = document.getElementById('tmpl'); + + assert_equals(tmpl.innerHTML, '<span>Happy Templating!</span>'); + var span = tmpl.content.querySelector('span'); + + var tmpl_doc = tmpl.content.ownerDocument; + assert_equals(tmpl.ownerDocument, document); + assert_not_equals(tmpl_doc, document); + + var new_doc = document.implementation.createHTMLDocument(); + assert_not_equals(new_doc, document); + assert_not_equals(new_doc, tmpl_doc); + + // Try moving tmpl.content to new_doc and check the results. + const tmplContentNodeDocument = tmpl.content.ownerDocument; + const tmplContentAdoptResult = new_doc.adoptNode(tmpl.content); + assert_equals(tmpl.content, tmplContentAdoptResult); + assert_equals(tmpl.ownerDocument, document); + assert_equals(tmpl.content.ownerDocument, tmplContentNodeDocument); + + // Hierarchy checks at various combinations. + assert_throws_dom('HierarchyRequestError', () => { + tmpl.content.appendChild(parent); + }, 'Template content should throw if any of ancestor is being appended.'); + assert_throws_dom('HierarchyRequestError', () => { + tmpl.content.appendChild(tmpl); + }, 'Template content should throw if its host is being appended.'); + assert_throws_dom('HierarchyRequestError', () => { + span.appendChild(parent); + }, 'Template content child should throw if any of ancestor is being appended.'); + assert_throws_dom('HierarchyRequestError', () => { + span.appendChild(tmpl); + }, 'Template content child should throw template\'s host is being appended.'); + + // Sanity check: template.content before and after move. + var tmpl_content_reference = tmpl.content; + assert_equals(tmpl.content.firstChild, span, + '<span> should be kept until it is removed, even after ' + + 'adopted to another document.'); + new_doc.body.appendChild(tmpl.content); + assert_equals(tmpl.content.firstChild, null, + '<span> should be removed from template content.'); + assert_equals(tmpl_content_reference, tmpl.content, + 'template.content should be identical before and after ' + + 'moving its children.'); +}, 'Template content should throw exception when its ancestor in ' + + 'a different document but connected via host is being append.'); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-in-inactive-document-crash.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-in-inactive-document-crash.html new file mode 100644 index 0000000000..66c564c77a --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-in-inactive-document-crash.html @@ -0,0 +1,7 @@ +<iframe id="i"></iframe> +<script> +var t = i.contentDocument.createElement("template"); +i.contentDocument.documentElement.appendChild(t); +i.remove(); +t.content; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-move-to-inactive-document-crash.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-move-to-inactive-document-crash.html new file mode 100644 index 0000000000..89c56d1663 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-move-to-inactive-document-crash.html @@ -0,0 +1,7 @@ +<div id="d"> +<iframe id="i"></iframe> +<template id="t"> </template> +</div> +<script> +i.contentDocument.documentElement.appendChild(d); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-node-document.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-node-document.html new file mode 100644 index 0000000000..da76c6b04f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content-node-document.html @@ -0,0 +1,59 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Node document of the template content attribute must be template contents owner</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="Node document of the template content attribute must be template contents owner"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + var nestedTemplate = doc.createElement('template'); + template.appendChild(nestedTemplate); + + assert_equals(nestedTemplate.content.ownerDocument, template.content.ownerDocument, + 'Wrong node document of the template content attribute'); + +}, 'Node document of the template content attribute must be template contents owner. ' + + 'Nested template element created by createElement'); + + +test(function() { + var doc = newHTMLDocument(); + doc.body.innerHTML = '<template><template></template></template>'; + var template = doc.querySelector('template'); + var nestedTemplate = template.content.querySelector('template'); + + assert_equals(nestedTemplate.content.ownerDocument, template.content.ownerDocument, + 'Wrong node document of the template content attribute'); + +}, 'Node document of the template content attribute must be template contents owner. ' + + 'Nested template element created by innerHTML'); + +testInIFrame('../resources/two-templates.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var template1 = doc.querySelector('#template1'); + var template2 = doc.querySelector('#template2'); + + // when there is a browsing context, template contents owner is only accessible via template.content.ownerDocument + // because template contents owner is bounded to document + // verify that multiple templates share the same instance of template contents owner + + assert_equals(template1.content.ownerDocument, template2.content.ownerDocument, + 'Wrong node document of the template content attribute'); +}, 'Node document of the template content attribute must be template contents owner. ' + + 'Load HTML file with multiple template elements'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content.html new file mode 100644 index 0000000000..b9e790daf8 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-content.html @@ -0,0 +1,63 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: HTML elements in template content</title> +<meta name="author" title="Sergey G. Grekhov" href="mailto:sgrekhov@unipro.ru"> +<meta name="author" title="Aleksei Yu. Semenov" href="a.semenov@unipro.ru"> +<meta name="assert" content="Template may contain any element, except the html element, the head element, the body element, or the frameset element"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +HTML5_ELEMENTS.forEach(function(value) { + if (value !== 'body' && value !== 'html' && value !== 'head' && value !== 'frameset') { + + test(function() { + var doc = newHTMLDocument(); + var template = doc.createElement('template'); + var element = doc.createElement(value); + template.content.appendChild(element); + var valueToTest = template.content.querySelector(value); + + doc.body.appendChild(template); + + assert_not_equals(valueToTest, null); + }, 'Template may contain ' + value + ' element'); + + } +}); + + + +var parameters = []; + +HTML5_ELEMENTS.forEach(function(value) { + if (value !== 'body' && value !== 'html' && value !== 'head' && value !== 'frameset') { + + test(function() { + var doc = newHTMLDocument(); + + if (isVoidElement(value)) { + doc.body.innerHTML = '<template><' + value + '/></template>'; + } else { + doc.body.innerHTML = '<template><' + value + '></' + value + '></template>'; + } + + var template = doc.querySelector('template'); + var element = template.content.querySelector(value); + + assert_not_equals(element, null); + }, 'Template may contain ' + value + ' element. ' + + 'The template element and contents are added via body.innerHTML'); + + } +}); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-body.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-body.html new file mode 100644 index 0000000000..70028c5ecd --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-body.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Template element as a descendant of the body element.</title> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="Template element can be a descendant of the body element"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +testInIFrame('../resources/template-contents.html', function(ctx) { + var doc = ctx.iframes[0].contentDocument; + + assert_not_equals(doc.body.querySelector('template'), null, + 'Template element should be a descendant of the body element'); + +}, 'Template element as a descendant of the body element. Test loading from a file'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-frameset.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-frameset.html new file mode 100644 index 0000000000..ce20a7413e --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-frameset.html @@ -0,0 +1,62 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Template element as a descendant of the frameset element.</title> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="Template element can not be a descendant of the frameset element"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/#parsing-main-inframeset"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +testInIFrame('../resources/template-descendant-frameset.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var frameset = doc.querySelector('frameset'); + + assert_equals(frameset.querySelector('template'), null, + 'Template element should not be a descendant of the frameset element'); + +}, 'Template element as a descendant of the frameset element. Test loading from a file'); + + +testInIFrame('../resources/template-descendant-frameset.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var frameset = doc.querySelector('frameset'); + + frameset.innerHTML = ''; + assert_equals(doc.querySelector('template'), null, + 'Initial conditions are not satisfied'); + + frameset.innerHTML = '<template>some text</template>'; + + assert_equals(frameset.querySelector('template'), null, + 'Template element should not be a descendant of the frameset element'); + +}, 'Template element as a descendant of the frameset element. ' + + 'Test template element is assigned to frameset\'s innerHTML)'); + + +testInIFrame('../resources/template-descendant-frameset.html', function(context) { + var doc = context.iframes[0].contentDocument; + + var frameset = doc.querySelector('frameset'); + + var template = doc.createElement('template'); + frameset.appendChild(template); + + assert_equals(frameset.querySelectorAll('template').length, 1, + 'Template element should be a descendant of the frameset element'); + +}, 'Template element as a descendant of the frameset element. ' + + 'Test template element appended to frameset by appendChild()'); + + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-head.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-head.html new file mode 100644 index 0000000000..611ec50bb4 --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-descendant-head.html @@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> +<title>HTML Templates: Template element as a descendant of the head element.</title> +<meta name="author" title="Aleksei Yu. Semenov" href="mailto:a.semenov@unipro.ru"> +<meta name="assert" content="Template element can be a descendant of the head element"> +<link rel="help" href="http://www.w3.org/TR/2013/WD-html-templates-20130214/#template-element"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src='/html/resources/common.js'></script> +</head> +<body> +<div id="log"></div> +<script type="text/javascript"> + +testInIFrame('../resources/template-descendant-head.html', function(context) { + var doc = context.iframes[0].contentDocument; + + assert_not_equals(doc.head.querySelector('template'), null, + 'Template element should be a descendant of the head element'); + +}, 'Template element as a descendant of the head element. Test loading from a file'); + +</script> +</body> +</html> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-element-clone-into-inactive-document-crash.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-element-clone-into-inactive-document-crash.html new file mode 100644 index 0000000000..56b199d1eb --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-element-clone-into-inactive-document-crash.html @@ -0,0 +1,7 @@ +<template id="t"> </template> +<iframe id="i"></iframe> +<script> +var doc = i.contentDocument; +i.remove(); +doc.importNode(t, true); +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-set-inner-html-in-inactive-document-crash.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-set-inner-html-in-inactive-document-crash.html new file mode 100644 index 0000000000..79a76ee76f --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-element/template-set-inner-html-in-inactive-document-crash.html @@ -0,0 +1,6 @@ +<iframe id="i"></iframe> +<script> + var doc = i.contentDocument; + i.remove(); + doc.createElement("template").innerHTML = ""; +</script> diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-table-crash.html b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-table-crash.html new file mode 100644 index 0000000000..0f6a49874d --- /dev/null +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-template-element/template-table-crash.html @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<link rel="author" href="mailto:masonf@chromium.org"> +<link rel="help" href="https://crbug.com/1212619"> +<meta name="assert" content="The renderer should not crash."> + +<template id=tmpl></template> +<table id=tbl> + <script> + tmpl.appendChild(tbl); + </script> + Crash +</table> |