diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/html/dom/render-blocking | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/html/dom/render-blocking')
54 files changed, 1696 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/dom/render-blocking/blocking-idl-attr.html b/testing/web-platform/tests/html/dom/render-blocking/blocking-idl-attr.html new file mode 100644 index 0000000000..c33b411eb4 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/blocking-idl-attr.html @@ -0,0 +1,44 @@ +<!DOCTYPE html> +<title>Tests the 'blocking' IDL attribute on link, script and style elements</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +// Tests that the 'blocking' attribute follows the IDL: +// [SameObject, PutForwards=value] readonly attribute DOMTokenList blocking; + +test(() => { + const link = document.createElement('link'); + assert_true(link.blocking.supports('render')); + assert_false(link.blocking.supports('asdf')); +}, "Supported tokens of the 'blocking' IDL attribute of the link element"); + +test(() => { + const link = document.createElement('link'); + link.blocking = 'asdf'; + assert_equals(link.blocking.value, 'asdf'); +}, "Setting the 'blocking' IDL attribute of the link element"); + +test(() => { + const script = document.createElement('script'); + assert_true(script.blocking.supports('render')); + assert_false(script.blocking.supports('asdf')); +}, "Supported tokens of the 'blocking' IDL attribute of the script element"); + +test(() => { + const script = document.createElement('script'); + script.blocking = 'asdf'; + assert_equals(script.blocking.value, 'asdf'); +}, "Setting the 'blocking' IDL attribute of the script element"); + +test(() => { + const style = document.createElement('style'); + assert_true(style.blocking.supports('render')); + assert_false(style.blocking.supports('asdf')); +}, "Supported tokens of the 'blocking' IDL attribute of the style element"); + +test(() => { + const style = document.createElement('style'); + style.blocking = 'asdf'; + assert_equals(style.blocking.value, 'asdf'); +}, "Setting the 'blocking' IDL attribute of the style element"); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-001.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-001.tentative.html new file mode 100644 index 0000000000..36567f9d54 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-001.tentative.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>`link rel=expect` defers frames until href element is parsed</title> + +<link rel=expect href="#last" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("last"))); + t.done(); + }); +}, "blocking defers frames until full parsing"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-002.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-002.tentative.html new file mode 100644 index 0000000000..3c907597f7 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-002.tentative.html @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Frames starts after href element is parsed before the end</title> + +<link rel=expect href="#third" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("third"))); + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "blocking defers until needed element is parsed"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="third"></div> + <script> + generateParserDelay(); + </script> + <div id="fourth"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-003.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-003.tentative.html new file mode 100644 index 0000000000..2858798a35 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-003.tentative.html @@ -0,0 +1,33 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Adding link in the head has an effect</title> + +<script> +let link = document.createElement("link"); +link.rel = "expect"; +link.href = "#last"; +link.blocking = "render"; +document.head.appendChild(link) + +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("last"))); + t.done(); + }); +}, "adding link in the head defers frames"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-004.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-004.tentative.html new file mode 100644 index 0000000000..f45f558720 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-004.tentative.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Removing link in the head has an effect</title> + +<link id=link rel=expect href="#last" blocking="render"> +<script> +link.remove(); + +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "removing link in the head makes it no longer blocking"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-005.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-005.tentative.html new file mode 100644 index 0000000000..098a3c5767 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-005.tentative.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Removing blocking attr in the head has an effect</title> + +<link id=link rel=expect href="#last" blocking="render"> +<script> +link.blocking = "" + +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "removing 'blocking' makes it no longer blocking"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-006.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-006.tentative.html new file mode 100644 index 0000000000..223e42109e --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-006.tentative.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Adding blocking attr in the head has an effect</title> + +<link id=link rel=expect href="#last"> +<script> +link.blocking = "render" + +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("last"))); + t.done(); + }); +}, "adding 'blocking=render' in the head makes it blocking"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-007.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-007.tentative.html new file mode 100644 index 0000000000..9aa0aeea79 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-007.tentative.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Media attribute that doesn't match makes the link not apply</title> + +<link rel=expect href="#last" blocking="render" media="(max-width: 10px)"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "link with non-matching media has no effect"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-008.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-008.tentative.html new file mode 100644 index 0000000000..e671dda19c --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-008.tentative.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Media attribute changes in the head to apply</title> + +<link id=link rel=expect href="#last" blocking="render" media="(max-width: 10px)"> +<script> +link.media = "(min-width: 10px)"; + +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("last"))); + t.done(); + }); +}, "changing media to matching causes link to have an effect"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-009.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-009.tentative.html new file mode 100644 index 0000000000..8498816ea5 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-009.tentative.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Media attribute changes in the head to not apply</title> + +<link id=link rel=expect href="#last" blocking="render" media="(min-width: 10px)"> +<script> +link.media = "(max-width: 10px)"; + +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "changing media to non-matching makes it non blocking"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-010.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-010.tentative.html new file mode 100644 index 0000000000..ef6f709012 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-010.tentative.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Rel attribute changes in the head to not apply</title> + +<link id=link rel=expect href="#last" blocking="render"> +<script> +link.rel = "stylesheet"; + +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "changing rel to non-expect makes it non blocking"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-011.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-011.tentative.html new file mode 100644 index 0000000000..dee82d8c59 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-011.tentative.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Rel attribute changes in the head to apply</title> + +<link id=link rel=stylesheet href="#last" blocking="render"> +<script> +link.rel = "expect"; + +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("last"))); + t.done(); + }); +}, "changing rel to expect in the head causes it to be blocking"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-012.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-012.tentative.html new file mode 100644 index 0000000000..4110e54c5f --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-012.tentative.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Href attribute changes in the head to apply</title> + +<link id=link rel=expect href="" blocking="render"> +<script> +link.href = "#last"; + +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("last"))); + t.done(); + }); +}, "adding href in the head makes it blocking"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-013.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-013.tentative.html new file mode 100644 index 0000000000..ecd97be86a --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-013.tentative.html @@ -0,0 +1,30 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Href attribute changes in the head to not apply</title> + +<link id=link rel=expect href="#last" blocking="render"> +<script> +link.href = ""; + +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "removing href makes it no longer blocking"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-014.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-014.tentative.html new file mode 100644 index 0000000000..ea8948de42 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-014.tentative.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Blocking link added in the body has no effect</title> + +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "link in the body has no effect"); +</script> +</head> +<body> +<link rel=expect href="#last" blocking="render"> +<script> +let link = document.createElement("link"); +link.rel = "rel"; +link.href = "#last"; +link.blocking = "render"; +document.head.appendChild(link); +</script> + + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-015.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-015.tentative.html new file mode 100644 index 0000000000..a775ee4174 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-015.tentative.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Blocking link removed in the body has an effect</title> + +<link id=link rel=expect href="#last" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "removing link the body makes it non blocking"); +</script> +</head> +<body> +<script> +link.remove(); +</script> + + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-016.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-016.tentative.html new file mode 100644 index 0000000000..8968c5dacd --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-016.tentative.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Removing blocking attr in the body has an effect</title> + +<link id=link rel=expect href="#last" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "removing 'blocking' in the body makes it non blocking"); +</script> +</head> +<body> +<script> +link.blocking = ""; +</script> + + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-017.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-017.tentative.html new file mode 100644 index 0000000000..2d3b574721 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-017.tentative.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Adding blocking attr in the body has no effect</title> + +<link id=link rel=expect href="#last"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "adding 'blocking=render' in the body has no effect"); +</script> +</head> +<body> +<script> +link.blocking = "render" +</script> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-018.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-018.tentative.html new file mode 100644 index 0000000000..76e6394b5b --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-018.tentative.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Media attribute changes in the body to apply, but has no effect</title> + +<link id=link rel=expect href="#last" blocking="render" media="(max-width: 10px)"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "changing media to matching in the body has no effect"); +</script> +</head> +<body> +<script> +link.media = "(min-width: 10px)"; +</script> + + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-019.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-019.tentative.html new file mode 100644 index 0000000000..80a7019edc --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-019.tentative.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Media attribute changes in the body to not apply</title> + +<link id=link rel=expect href="#last" blocking="render" media="(min-width: 10px)"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "changing media to non-matching in the body makes it non blocking"); +</script> +</head> +<body> +<script> +link.media = "(max-width: 10px)"; +</script> + + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-020.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-020.tentative.html new file mode 100644 index 0000000000..10019c943f --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-020.tentative.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Rel attribute changes in the body to not apply</title> + +<link id=link rel=expect href="#last" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "changing rel to non-expect in the body makes it non blocking"); +</script> +</head> +<body> +<script> +link.rel = "stylesheet"; +</script> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-021.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-021.tentative.html new file mode 100644 index 0000000000..1ca2114689 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-021.tentative.html @@ -0,0 +1,35 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Rel attribute changes in the body to apply, but has no effect</title> + +<link id=link rel=stylesheet href="#last" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "changing rel to expect in the body has no effect"); +</script> +</head> +<body> +<script> +link.rel = "expect"; +</script> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="third"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-022.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-022.tentative.html new file mode 100644 index 0000000000..5dfbcac30a --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-022.tentative.html @@ -0,0 +1,32 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Href attribute changes in the body to apply, but has no effect</title> + +<link id=link rel=expect href="" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "adding href in the body has no effect"); +</script> +</head> +<body> +<script> +link.href = "#last"; +</script> + + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-023.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-023.tentative.html new file mode 100644 index 0000000000..8fe8b6a8c8 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-023.tentative.html @@ -0,0 +1,31 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Href attribute changes in the body to not apply</title> + +<link id=link rel=expect href="#last" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "removing href in the body makes it non blocking"); +</script> +</head> +<body> +<script> +link.href = ""; +</script> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-024.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-024.tentative.html new file mode 100644 index 0000000000..19e4020fb7 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-024.tentative.html @@ -0,0 +1,36 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Unknown href causes the whole document to be blocked</title> + +<link rel=expect href="#unknown" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("last"))); + t.done(); + }); +}, "unknown href causes the whole document to be blocked"); +</script> +</head> +<body> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="third"></div> + <script> + generateParserDelay(); + </script> + <div id="fourth"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-025.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-025.tentative.html new file mode 100644 index 0000000000..689ae69f45 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-025.tentative.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Adding an id to parsed element satisfies render block</title> + +<link rel=expect href="#first" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("first"))); + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "adding an id in the body satisfies render block"); +</script> +</head> +<body> + <div id="willbefirst"></div> + <script> + willbefirst.id = "first"; + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="third"></div> + <script> + generateParserDelay(); + </script> + <div id="fourth"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-026.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-026.tentative.html new file mode 100644 index 0000000000..6abfc43b8b --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-026.tentative.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Removing id keeps render block satisfied</title> + +<link rel=expect href="#first" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("wasfirst"))); + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "removing id after it was renderer keeps render block satisfied"); +</script> +</head> +<body> + <div id="first"></div> + <script> + first.id = "wasfirst"; + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="third"></div> + <script> + generateParserDelay(); + </script> + <div id="fourth"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-027.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-027.tentative.html new file mode 100644 index 0000000000..56f88e0fc2 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-027.tentative.html @@ -0,0 +1,38 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Unknown href causes the whole document to be blocked</title> + +<link id=link rel=expect href="#unknown" blocking="render"> +<script> +link.href = "#stillunknown"; + +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("last"))); + t.done(); + }); +}, "unknown href causes the whole document to be blocked (with href changes!)"); +</script> +</head> +<body> + <div id="notfirst"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="third"></div> + <script> + generateParserDelay(); + </script> + <div id="fourth"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-028.tentative.html b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-028.tentative.html new file mode 100644 index 0000000000..a64d542c4a --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/element-render-blocking-028.tentative.html @@ -0,0 +1,48 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/utils.js"></script> +<title>Multiple links and all but one removed</title> + +<link rel=expect href="#third" blocking="render"> +<link id=one rel=expect href="#third" blocking="render"> +<link id=two rel=expect href="#third" blocking="render"> +<link id=three rel=expect href="#third" blocking="render"> +<link id=four rel=expect href="#third" blocking="render"> +<script> +async_test((t) => { + requestAnimationFrame(() => { + t.step(() => assert_true(!!document.getElementById("third"))); + t.step(() => assert_false(!!document.getElementById("last"))); + t.done(); + }); +}, "removing some links but not all keeps at least the matching link blocking"); + +one.remove(); +two.remove(); +</script> +</head> +<body> +<script> +three.remove(); +four.remove(); +</script> + <div id="first"></div> + <script> + generateParserDelay(); + </script> + <div id="second"></div> + <script> + generateParserDelay(); + </script> + <div id="third"></div> + <script> + generateParserDelay(); + </script> + <div id="fourth"></div> + <script> + generateParserDelay(); + </script> + <div id="last"></div> +</body> diff --git a/testing/web-platform/tests/html/dom/render-blocking/non-render-blocking-scripts.optional.html b/testing/web-platform/tests/html/dom/render-blocking/non-render-blocking-scripts.optional.html new file mode 100644 index 0000000000..a4c32ea037 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/non-render-blocking-scripts.optional.html @@ -0,0 +1,61 @@ +<!DOCTYPE html> +<title>Tests when script is not implicitly potentially render-blocking</title> +<link rel="help" href="https://github.com/whatwg/html/pull/7894"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<!-- + The test is marked "optional" because even when the document is not + render-blocked, the user agent is still free to take other factors, which are + not limited by the spec, into consideration and therefore decide not to + render. However, it is still more desirable if rendering starts + immediately/soon. +--> + +<script class="test" data="parser-inserted async script" async + src="support/dummy-1.js?pipe=trickle(d1)&async"></script> +<script class="test" data="parser-inserted defer script" defer + src="support/dummy-1.js?pipe=trickle(d1)&defer"></script> +<script class="test" data="parser-inserted module script" type="module" + src="support/dummy-1.mjs?pipe=trickle(d1)"></script> +<script class="test" data="parser-inserted async module script" type="module" + async src="support/dummy-1.mjs?pipe=trickle(d1)&async"></script> + +<script> +function addTestScriptElement(title, attributes) { + let element = document.createElement('script'); + element.className = 'test'; + element.setAttribute('data', title); + Object.assign(element, attributes); + document.head.appendChild(element); +} + +addTestScriptElement('script-inserted script', {src: 'support/dummy-1.js?pipe=trickle(d1)&dynamic'}); +addTestScriptElement('script-inserted sync script', {async: false, src: 'support/dummy-1.js?pipe=trickle(d1)&dynamicSync'}); +addTestScriptElement('script-inserted module script', {type: 'module', src: 'support/dummy-1.mjs?pipe=trickle(d1)&dynamic'}); +</script> + +<div id="dummy">Some text</div> + +<script> +const testElements = [...document.querySelectorAll('.test')]; +const loadObservers = testElements.map(element => new LoadObserver(element)); + +promise_setup(async () => { + // Test cases are run after rendering is unblocked. + await new Promise(resolve => requestAnimationFrame(resolve)); +}); + +for (let index = 0; index < testElements.length; ++index) { + promise_test( + async () => assert_false(loadObservers[index].finished), + testElements[index].getAttribute('data') + ' is not implicitly render-blocking'); +} + +for (let index = 0; index < testElements.length; ++index) { + promise_test( + () => loadObservers[index].load, + testElements[index].getAttribute('data') + ' should eventually be loaded and evaluated'); +} +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/parser-blocking-script.html b/testing/web-platform/tests/html/dom/render-blocking/parser-blocking-script.html new file mode 100644 index 0000000000..8d391144b2 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/parser-blocking-script.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<title>Parser-blocking script elements are implicitly render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<script> +// Add some renderable content before parser inserts body +document.documentElement.appendChild(document.createTextNode('text')); + +// Test must be setup before the parser-blocking script +test_render_blocking( + () => assert_equals(window.dummy, 1), + 'Parser-blocking script is evaluated'); +</script> + +<script src="support/dummy-1.js?pipe=trickle(d1)"></script> + +<div>Some more text</div> diff --git a/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-async-inline-module-with-import.html b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-async-inline-module-with-import.html new file mode 100644 index 0000000000..50a2add277 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-async-inline-module-with-import.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<head> +<title>Parser-inserted async inline module script elements with "blocking=render" are render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.did_execute_script = false; +</script> +<script type="module" blocking="render" async> + import "/loading/resources/dummy.js?pipe=trickle(d1)"; + window.did_execute_script = true; +</script> +</head> +<div id="dummy">some text</div> + +<script> + promise_test(async t => { + await new Promise(resolve => requestAnimationFrame(() => resolve())); + assert_true(window.did_execute_script, "Parser-inserted async render-blocking inline module script should execute before rAF callback"); + }); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-async-script.html b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-async-script.html new file mode 100644 index 0000000000..4b2216dfcb --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-async-script.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<title>Parser-inserted async script elements with "blocking=render" are render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<script id="async-script" async blocking="render" + src="support/dummy-1.js?pipe=trickle(d1)"> +</script> + +<div>Some text</div> + +<script> +const asyncScript = document.getElementById('async-script'); +test_render_blocking( + asyncScript, + () => assert_equals(window.dummy, 1), + 'Parser-inserted render-blocking async script is evaluated'); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-defer-script.html b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-defer-script.html new file mode 100644 index 0000000000..1ae8caf2ec --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-defer-script.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<title>Parser-inserted defer script elements with "blocking=render" are render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<script id="defer-script" defer blocking="render" + src="support/dummy-1.js?pipe=trickle(d1)"> +</script> + +<div>Some text</div> + +<script> +const deferScript = document.getElementById('defer-script'); +test_render_blocking( + deferScript, + () => assert_equals(window.dummy, 1), + 'Parser-inserted render-blocking defer script is evaluated'); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-inline-module-with-import.html b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-inline-module-with-import.html new file mode 100644 index 0000000000..af2ac46aaf --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-inline-module-with-import.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<head> +<title>Parser-inserted module script elements with "blocking=render" are render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.did_execute_script = false; +</script> +<script type="module" blocking="render"> + import "/loading/resources/dummy.js?pipe=trickle(d1)"; + window.did_execute_script = true; +</script> +</head> +<div id="dummy">some text</div> + +<script> + promise_test(async t => { + await new Promise(resolve => requestAnimationFrame(() => resolve())); + assert_true(window.did_execute_script, "Parser-inserted render-blocking inline module script should execute before rAF callback"); + }); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-module-script.html b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-module-script.html new file mode 100644 index 0000000000..2bca88e73c --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-module-script.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<title>Parser-inserted module script elements with "blocking=render" are render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<script id="module-script" type="module" blocking="render" + src="support/dummy-1.mjs?pipe=trickle(d1)"> +</script> + +<div id="dummy">some text</div> + +<script> +const moduleScript = document.getElementById('module-script'); +test_render_blocking( + moduleScript, + () => assert_equals(document.getElementById('dummy').textContent, '1'), + 'Parser-inserted render-blocking module script is evaluated'); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-style-element.html b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-style-element.html new file mode 100644 index 0000000000..9a358aa493 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-style-element.html @@ -0,0 +1,20 @@ +<!doctype html> +<title>Parser-inserted style elements are implicitly render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> +<script> +// Test case must be set up before the stylesheet, because the stylesheet is +// script-blocking, which means we can't set it up while the stylesheet is +// loading. +test_render_blocking(() => { + let color = getComputedStyle(document.querySelector('.target')).color; + assert_equals(color, 'rgb(255, 0, 0)'); +}, 'Render-blocking stylesheet is applied'); +</script> +<style> +@import url('support/target-red.css?pipe=trickle(d1)'); +</style> +<div class="target"> + This should be red +</div> diff --git a/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-stylesheet-link.html b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-stylesheet-link.html new file mode 100644 index 0000000000..0a771448fd --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/parser-inserted-stylesheet-link.html @@ -0,0 +1,18 @@ +<!doctype html> +<title>Parser-inserted stylesheet links are implicitly render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> +<script> +// Test case must be set up before the stylesheet, because the stylesheet is +// script-blocking, which means we can't set it up while the stylesheet is +// loading. +test_render_blocking(() => { + let color = getComputedStyle(document.querySelector('.target')).color; + assert_equals(color, 'rgb(255, 0, 0)'); +}, 'Render-blocking stylesheet is applied'); +</script> +<link rel="stylesheet" href="support/target-red.css?pipe=trickle(d1)"> +<div class="target"> + This should be red +</div> diff --git a/testing/web-platform/tests/html/dom/render-blocking/remove-attr-script-keeps-blocking.html b/testing/web-platform/tests/html/dom/render-blocking/remove-attr-script-keeps-blocking.html new file mode 100644 index 0000000000..451d2f3695 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/remove-attr-script-keeps-blocking.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<title>Synchronous script element still blocks rendering after removing `blocking=render`</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<script> +// Test script must be added before the synchronous script because the +// synchronous script is parser-blocking. + +promise_setup(async () => { + let script = await nodeInserted(document.head, node => node.id === 'script'); + script.blocking = ''; + + // Also inserts some contents for non-compliant UA to render + document.body = document.createElement('body'); + document.body.appendChild(document.createTextNode('Some text')); +}); + +test_render_blocking( + () => assert_equals(window.dummy, 1), + 'Render-blocking script is loaded and evaluated'); +</script> + +<script id="script" blocking="render" src="support/dummy-1.js?pipe=trickle(d1)"></script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/remove-attr-style-keeps-blocking.html b/testing/web-platform/tests/html/dom/render-blocking/remove-attr-style-keeps-blocking.html new file mode 100644 index 0000000000..31d4b56838 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/remove-attr-style-keeps-blocking.html @@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>Parser-inserted style element still blocks rendering after removing `blocking=render`</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<script> +// Test script must be added before the style element because the style +// element is script-blocking. + +promise_setup(async () => { + let sheet = await nodeInserted(document.head, node => node.id === 'sheet'); + sheet.blocking = ''; +}); + +test_render_blocking( + () => { + let color = getComputedStyle(document.querySelector('.target')).color; + assert_equals(color, 'rgb(255, 0, 0)'); + }, + 'Render-blocking stylesheet is applied'); +</script> + +<style id="sheet" blocking="render"> +@import url("support/target-red.css?pipe=trickle(d1)"); +</style> + +<div class="target">Some text</div> diff --git a/testing/web-platform/tests/html/dom/render-blocking/remove-attr-stylesheet-link-keeps-blocking.html b/testing/web-platform/tests/html/dom/render-blocking/remove-attr-stylesheet-link-keeps-blocking.html new file mode 100644 index 0000000000..1248b90b23 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/remove-attr-stylesheet-link-keeps-blocking.html @@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>Parser-inserted stylesheet link still blocks rendering after removing `blocking=render`</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<script> +// Test script must be added before the stylesheet link because the stylesheet +// link is script-blocking. + +promise_setup(async () => { + let sheet = await nodeInserted(document.head, node => node.id === 'sheet'); + sheet.blocking = ''; +}); + +test_render_blocking( + () => { + let color = getComputedStyle(document.querySelector('.target')).color; + assert_equals(color, 'rgb(255, 0, 0)'); + }, + 'Render-blocking stylesheet is applied'); +</script> + +<link id="sheet" rel="stylesheet" blocking="render" + href="support/target-red.css?pipe=trickle(d1)"> + +<div class="target">Some text</div> diff --git a/testing/web-platform/tests/html/dom/render-blocking/remove-attr-unblocks-rendering.optional.html b/testing/web-platform/tests/html/dom/render-blocking/remove-attr-unblocks-rendering.optional.html new file mode 100644 index 0000000000..c73e3c6452 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/remove-attr-unblocks-rendering.optional.html @@ -0,0 +1,86 @@ +<!DOCTYPE html> +<title>Removing `blocking=render` should unblock rendering</title> +<link rel="help" href="https://html.spec.whatwg.org/C/#blocking-attribute"> +<link rel="help" href="https://html.spec.whatwg.org/C/#rendering-opportunity"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<!-- + The test is marked "optional" because even when the document is no longer + render-blocked, the user agent is still free to take other factors, which are + not limited by the spec, into consideration and therefore decide not to + render. However, it is still more desirable if rendering starts + immediately/soon. +--> + +<script class="test" data="parser-inserted async script" async blocking="render" + src="support/dummy-1.js?pipe=trickle(d1)&async"></script> +<script class="test" data="parser-inserted defer script" defer blocking="render" + src="support/dummy-1.js?pipe=trickle(d1)&defer"></script> +<script class="test" data="parser-inserted module script" type="module" + blocking="render" src="support/dummy-1.mjs?pipe=trickle(d1)"></script> +<script class="test" data="parser-inserted async module script" type="module" + async blocking="render" src="support/dummy-1.mjs?pipe=trickle(d1)&async"></script> + +<!-- + No test for parser-inserted stylesheets and synchronous scripts because they + are render-blocking by default, so removing `blocking=render` does not unblock + rendering. +--> + +<script> +function addRenderBlockingElement(tag, title, attributes, optional_text) { + let element = document.createElement(tag); + element.className = 'test'; + element.setAttribute('data', title); + element.blocking = 'render'; + Object.assign(element, attributes); + if (optional_text) + element.textContent = optional_text; + document.head.appendChild(element); +} + +addRenderBlockingElement( + 'link', 'script-inserted stylesheet link', + {rel: 'stylesheet', blocking: 'render', href: 'support/target-red.css?pipe=trickle(d1)&dynamic'}); + +addRenderBlockingElement( + 'script', 'script-inserted script', + {src: 'support/dummy-1.js?pipe=trickle(d1)&dynamic'}); +addRenderBlockingElement( + 'script', 'script-inserted module script', + {type: 'module', src: 'support/dummy-1.mjs?pipe=trickle(d1)&dynamic'}); + +addRenderBlockingElement( + 'style', 'script-inserted inline style', {}, + '@import url("support/target-red.css?pipe=trickle(d1)&imported&dynamic")'); +</script> + +<div id="dummy">Some text</div> + +<script> +const testElements = [...document.querySelectorAll('.test')]; +const loadObservers = testElements.map(element => new LoadObserver(element)); + +promise_setup(async () => { + for (let element of testElements) + element.blocking = ''; + + // Test cases are run after rendering is unblocked. + await new Promise(resolve => requestAnimationFrame(resolve)); +}); + +for (let index = 0; index < testElements.length; ++index) { + promise_test( + async () => assert_false(loadObservers[index].finished), + 'Render-blocking on ' + testElements[index].getAttribute('data') + ' is cancellable'); +} + +for (let index = 0; index < testElements.length; ++index) { + promise_test( + () => loadObservers[index].load, + 'Loading of ' + testElements[index].getAttribute('data') + ' should eventually succeed'); +} +</script> + diff --git a/testing/web-platform/tests/html/dom/render-blocking/remove-element-unblocks-rendering.optional.html b/testing/web-platform/tests/html/dom/render-blocking/remove-element-unblocks-rendering.optional.html new file mode 100644 index 0000000000..ad49c48c2e --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/remove-element-unblocks-rendering.optional.html @@ -0,0 +1,83 @@ +<!DOCTYPE html> +<title>Removing render-blocking element should unblock rendering</title> +<link rel="help" href="https://html.spec.whatwg.org/C/#blocking-attribute"> +<link rel="help" href="https://html.spec.whatwg.org/C/#rendering-opportunity"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<!-- + The test is marked "optional" because even when the document is no longer + render-blocked, the user agent is still free to take other factors, which are + not limited by the spec, into consideration and therefore decide not to + render. However, it is still more desirable if rendering starts + immediately/soon. +--> + +<script class="test" data="parser-inserted async script" async blocking="render" + src="support/dummy-1.js?pipe=trickle(d1)&async"></script> +<script class="test" data="parser-inserted defer script" defer blocking="render" + src="support/dummy-1.js?pipe=trickle(d1)&defer"></script> +<script class="test" data="parser-inserted module script" type="module" + blocking="render" src="support/dummy-1.mjs?pipe=trickle(d1)"></script> +<script class="test" data="parser-inserted async module script" type="module" + async blocking="render" src="support/dummy-1.mjs?pipe=trickle(d1)&async"></script> + +<!-- + No test for parser-inserted stylesheets and synchronous scripts because + they are script-blocking or even parser-blocking, and they do not have new + behaviors to test about. +--> + +<script> +function addRenderBlockingElement(tag, title, attributes, optional_text) { + let element = document.createElement(tag); + element.className = 'test'; + element.setAttribute('data', title); + element.blocking = 'render'; + Object.assign(element, attributes); + if (optional_text) + element.textContent = optional_text; + document.head.appendChild(element); +} + +addRenderBlockingElement( + 'link', 'script-inserted stylesheet link', + {rel: 'stylesheet', blocking: 'render', href: 'support/target-red.css?pipe=trickle(d1)&dynamic'}); + +addRenderBlockingElement( + 'script', 'script-inserted script', + {src: 'support/dummy-1.js?pipe=trickle(d1)&dynamic'}); +addRenderBlockingElement( + 'script', 'script-inserted module script', + {type: 'module', src: 'support/dummy-1.mjs?pipe=trickle(d1)&dynamic'}); + +addRenderBlockingElement( + 'style', 'script-inserted inline style', {}, + '@import url("support/target-red.css?pipe=trickle(d1)&imported&dynamic")'); +</script> + +<div id="dummy">Some text</div> + +<script> +const testElements = [...document.querySelectorAll('.test')]; +const loadObservers = testElements.map(element => new LoadObserver(element)); + +promise_setup(async () => { + for (let element of testElements) + element.remove(); + + // Test cases are run after rendering is unblocked. + await new Promise(resolve => requestAnimationFrame(resolve)); +}); + +for (let index = 0; index < testElements.length; ++index) { + promise_test( + async () => assert_false(loadObservers[index].finished), + 'Render-blocking on ' + testElements[index].getAttribute('data') + ' is cancellable'); + + // The loading can either continue or cancel. This test does not assert it. + loadObservers[index].load.catch(() => {}); +} +</script> + diff --git a/testing/web-platform/tests/html/dom/render-blocking/remove-pending-async-render-blocking-script.html b/testing/web-platform/tests/html/dom/render-blocking/remove-pending-async-render-blocking-script.html new file mode 100644 index 0000000000..5f6e8b34d1 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/remove-pending-async-render-blocking-script.html @@ -0,0 +1,19 @@ +<!DOCTYPE html> +<title>Removed render-blocking script should not indefinitely block rendering</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script id="target" async blocking="render" + src="support/dummy-1.js?pipe=trickle(d1)"></script> +<script> +promise_test(async () => { + const target = document.getElementById('target'); + const newDoc = document.implementation.createHTMLDocument('new document'); + newDoc.documentElement.appendChild(target); + + await new Promise(resolve => requestAnimationFrame(resolve)); + + // reqeustAnimationFrame() should be eventually run, but the script removed + // while pending should not be run. + assert_equals(window.dummy, undefined); +}); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/script-inserted-inline-module-with-import.html b/testing/web-platform/tests/html/dom/render-blocking/script-inserted-inline-module-with-import.html new file mode 100644 index 0000000000..576c0b321a --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/script-inserted-inline-module-with-import.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<head> +<title>Script-inserted module script elements with "blocking=render" are render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> + window.did_execute_script = false; + const script = document.createElement("script"); + script.type = "module"; + script.blocking = "render"; + script.textContent = ` + import "/loading/resources/dummy.js?pipe=trickle(d1)"; + window.did_execute_script = true; + `; + document.head.append(script); +</script> +</head> +<div id="dummy">some text</div> + +<script> + promise_test(async t => { + await new Promise(resolve => requestAnimationFrame(() => resolve())); + assert_true(window.did_execute_script, "Script-inserted render-blocking inline module script should execute before rAF callback"); + }); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/script-inserted-module-script.html b/testing/web-platform/tests/html/dom/render-blocking/script-inserted-module-script.html new file mode 100644 index 0000000000..73f0d3cdf4 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/script-inserted-module-script.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<title>Script-inserted module script elements with "blocking=render" are render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<script> +const moduleScript = document.createElement('script'); +moduleScript.type = 'module'; +moduleScript.blocking = 'render'; +moduleScript.src = 'support/dummy-1.mjs?pipe=trickle(d1)'; +document.head.appendChild(moduleScript); +</script> + +<div id="dummy">some text</div> + +<script> +test_render_blocking( + moduleScript, + () => assert_equals(document.getElementById('dummy').textContent, '1'), + 'Script-inserted render-blocking module script is evaluated'); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/script-inserted-script.html b/testing/web-platform/tests/html/dom/render-blocking/script-inserted-script.html new file mode 100644 index 0000000000..faf346b4dd --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/script-inserted-script.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<title>Script-inserted script elements with "blocking=render" are render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<script> +const script = document.createElement('script'); +script.src = 'support/dummy-1.js?pipe=trickle(d1)'; +script.blocking = 'render'; +document.head.appendChild(script); +</script> + +<div>Some text</div> + +<script> +test_render_blocking( + script, + () => assert_equals(window.dummy, 1), + 'Script-inserted render-blocking script is evaluated'); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/script-inserted-style-element.html b/testing/web-platform/tests/html/dom/render-blocking/script-inserted-style-element.html new file mode 100644 index 0000000000..683706af50 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/script-inserted-style-element.html @@ -0,0 +1,26 @@ +<!doctype html> +<title>Script-inserted style elements with "blocking=render" are render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<script> +const style = document.createElement('style'); +style.blocking = 'render'; +style.textContent = "@import url('support/target-red.css?pipe=trickle(d1)');"; +document.head.appendChild(style); +</script> + +<div class="target"> + This should be red +</div> + +<script> +test_render_blocking( + style, + () => { + let color = getComputedStyle(document.querySelector('.target')).color; + assert_equals(color, 'rgb(255, 0, 0)'); + }, + 'Render-blocking stylesheet is applied'); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/script-inserted-stylesheet-link.html b/testing/web-platform/tests/html/dom/render-blocking/script-inserted-stylesheet-link.html new file mode 100644 index 0000000000..46755387d7 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/script-inserted-stylesheet-link.html @@ -0,0 +1,27 @@ +<!doctype html> +<title>Script-inserted stylesheet links with "blocking=render" are render-blocking</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="support/test-render-blocking.js"></script> + +<script> +const stylesheet = document.createElement('link'); +stylesheet.rel = 'stylesheet'; +stylesheet.href = 'support/target-red.css?pipe=trickle(d1)'; +stylesheet.blocking = 'render'; +document.head.appendChild(stylesheet); +</script> + +<div class="target"> + This should be red +</div> + +<script> +test_render_blocking( + stylesheet, + () => { + let color = getComputedStyle(document.querySelector('.target')).color; + assert_equals(color, 'rgb(255, 0, 0)'); + }, + 'Render-blocking stylesheet is applied'); +</script> diff --git a/testing/web-platform/tests/html/dom/render-blocking/support/dummy-1.js b/testing/web-platform/tests/html/dom/render-blocking/support/dummy-1.js new file mode 100644 index 0000000000..597772cf64 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/support/dummy-1.js @@ -0,0 +1 @@ +window.dummy = 1; diff --git a/testing/web-platform/tests/html/dom/render-blocking/support/dummy-1.mjs b/testing/web-platform/tests/html/dom/render-blocking/support/dummy-1.mjs new file mode 100644 index 0000000000..9b85a21033 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/support/dummy-1.mjs @@ -0,0 +1 @@ +document.getElementById('dummy').textContent = 1; diff --git a/testing/web-platform/tests/html/dom/render-blocking/support/target-red.css b/testing/web-platform/tests/html/dom/render-blocking/support/target-red.css new file mode 100644 index 0000000000..a387acd4ec --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/support/target-red.css @@ -0,0 +1,3 @@ +.target { + color: red; +} diff --git a/testing/web-platform/tests/html/dom/render-blocking/support/test-render-blocking.js b/testing/web-platform/tests/html/dom/render-blocking/support/test-render-blocking.js new file mode 100644 index 0000000000..71d0d68096 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/support/test-render-blocking.js @@ -0,0 +1,118 @@ +// Observes the `load` event of an EventTarget, or the finishing of a resource +// given its url. Requires `/preload/resources/preload_helper.js` for the latter +// usage. +class LoadObserver { + constructor(target) { + this.finishTime = null; + this.load = new Promise((resolve, reject) => { + if (target.addEventListener) { + target.addEventListener('load', ev => { + this.finishTime = ev.timeStamp; + resolve(ev); + }); + target.addEventListener('error', reject); + } else if (typeof target === 'string') { + const observer = new PerformanceObserver(() => { + if (numberOfResourceTimingEntries(target)) { + this.finishTime = performance.now(); + resolve(); + } + }); + observer.observe({type: 'resource', buffered: true}); + } else { + reject('Unsupported target for LoadObserver'); + } + }); + } + + get finished() { + return this.finishTime !== null; + } +} + +// Observes the insertion of a script/parser-blocking element into DOM via +// MutationObserver, so that we can access the element before it's loaded. +function nodeInserted(parentNode, predicate) { + return new Promise(resolve => { + function callback(mutationList) { + for (let mutation of mutationList) { + for (let node of mutation.addedNodes) { + if (predicate(node)) + resolve(node); + } + } + } + new MutationObserver(callback).observe(parentNode, {childList: true}); + }); +} + +function createAutofocusTarget() { + const autofocusTarget = document.createElement('textarea'); + autofocusTarget.setAttribute('autofocus', ''); + // We may not have a body element at this point if we are testing a + // script-blocking stylesheet. Hence, the new element is added to + // documentElement. + document.documentElement.appendChild(autofocusTarget); + return autofocusTarget; +} + +function createScrollTarget() { + const scrollTarget = document.createElement('div'); + scrollTarget.style.overflow = 'scroll'; + scrollTarget.style.height = '100px'; + const scrollContent = document.createElement('div'); + scrollContent.style.height = '200px'; + scrollTarget.appendChild(scrollContent); + document.documentElement.appendChild(scrollTarget); + return scrollTarget; +} + +function createAnimationTarget() { + const style = document.createElement('style'); + style.textContent = ` + @keyframes anim { + from { height: 100px; } + to { height: 200px; } + } + `; + const animationTarget = document.createElement('div'); + animationTarget.style.backgroundColor = 'green'; + animationTarget.style.height = '50px'; + animationTarget.style.animation = 'anim 100ms'; + document.documentElement.appendChild(style); + document.documentElement.appendChild(animationTarget); + return animationTarget; +} + +// Error margin for comparing timestamps of paint and load events, in case they +// are reported by different threads. +const epsilon = 50; + +function test_render_blocking(optionalElementOrUrl, finalTest, finalTestTitle) { + // Ideally, we should observe the 'load' event on the specific render-blocking + // elements. However, this is not possible for script-blocking stylesheets, so + // we have to observe the 'load' event on 'window' instead. + if (!(optionalElementOrUrl instanceof HTMLElement) && + typeof optionalElementOrUrl !== 'string') { + finalTestTitle = finalTest; + finalTest = optionalElementOrUrl; + optionalElementOrUrl = undefined; + } + const loadObserver = new LoadObserver(optionalElementOrUrl || window); + + promise_test(async test => { + assert_implements(window.PerformancePaintTiming); + + await test.step_wait(() => performance.getEntriesByType('paint').length); + + assert_true(loadObserver.finished); + for (let entry of performance.getEntriesByType('paint')) { + assert_greater_than(entry.startTime, loadObserver.finishTime - epsilon, + `${entry.name} should occur after loading render-blocking resources`); + } + }, 'Rendering is blocked before render-blocking resources are loaded'); + + promise_test(test => { + return loadObserver.load.then(() => finalTest(test)); + }, finalTestTitle); +} diff --git a/testing/web-platform/tests/html/dom/render-blocking/support/utils.js b/testing/web-platform/tests/html/dom/render-blocking/support/utils.js new file mode 100644 index 0000000000..8a9a537e96 --- /dev/null +++ b/testing/web-platform/tests/html/dom/render-blocking/support/utils.js @@ -0,0 +1,5 @@ +function generateParserDelay(seconds = 1) { + document.write(` + <script src="/loading/resources/dummy.js?pipe=trickle(d${seconds})"></script> + `); +} |