summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/semantics/document-metadata/the-link-element
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /testing/web-platform/tests/html/semantics/document-metadata/the-link-element
parentInitial commit. (diff)
downloadfirefox-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/semantics/document-metadata/the-link-element')
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/all3
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/all.headers1
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html35
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-error-fired-before-scripting-unblocked.html25
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.html6
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.https.html6
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-event.html17
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-fired-before-scripting-unblocked.html24
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-multiple-error-events.html21
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-multiple-load-events.html21
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute-ascii-case-insensitive-notref.html5
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute-ascii-case-insensitive.html22
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute.html44
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rellist.html25
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html37
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-limited-quirks.html7
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-quirks.html7
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-type-attribute-ref.html3
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-type-attribute.html9
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/bad.css4
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/css.py7
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/empty-href.css3
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/good.css3
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-load-error-events.sub.js192
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-rel-attribute.css3
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-style-error.js47
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/neutral.css3
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet.css3
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/style.css3
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-change-href-ref.html8
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-change-href.html13
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-empty-href-ref.html9
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-empty-href.html12
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-media-ref.html9
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-media.html17
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-not-removed-until-next-stylesheet-loads.html22
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-with-base-ref.html11
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-with-base.html11
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet.css3
-rw-r--r--testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet.py9
40 files changed, 710 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/all b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/all
new file mode 100644
index 0000000000..60f1eab971
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/all
@@ -0,0 +1,3 @@
+body {
+ color: red;
+}
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/all.headers b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/all.headers
new file mode 100644
index 0000000000..74e07a14e7
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/all.headers
@@ -0,0 +1 @@
+Content-Type: text/css
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html
new file mode 100644
index 0000000000..127b253f59
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/document-without-browsing-context.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Documents without browsing contexts should not load stylesheets</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<body>
+<script>
+ function count(id, t) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', 'stylesheet.py?count=1&id=' + id);
+ xhr.onload = t.step_func_done(function() {
+ assert_equals(xhr.responseText, "1");
+ });
+ xhr.onerror = t.unreached_func();
+ xhr.send();
+ }
+
+ async_test(function(t) {
+ var id = token();
+ var doc = (new DOMParser()).parseFromString('<link rel="stylesheet" href="stylesheet.py?id=' + id + '"></link>', 'text/html');
+ var link = doc.querySelector('link');
+ document.head.appendChild(link);
+ t.step_timeout(function() { count(id, t) }, 500);
+ }, 'Create a document, adopt the node');
+
+ async_test(function(t) {
+ var id = token();
+ var d = document.createElement('div');
+ document.body.appendChild(d);
+ d.innerHTML = '<link rel="stylesheet" href="stylesheet.py?id=' + id + '"></link>';
+ t.step_timeout(function() { count(id, t) }, 500);
+ }, 'Create a stylesheet in innerHTML document');
+</script>
+</body>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-error-fired-before-scripting-unblocked.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-error-fired-before-scripting-unblocked.html
new file mode 100644
index 0000000000..188e4ba5ab
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-error-fired-before-scripting-unblocked.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<link rel="author" title="Dom Farolino" href="mailto:dom@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+var saw_link_onerror = false;
+var t = async_test("Check if the stylesheet's error event is fired before the " +
+ "pending parsing-blocking script is unblocked");
+</script>
+<link href="nonexistent.css" rel="stylesheet" id="style_test"
+ onload="t.unreached_func('Sheet should fail to load')"
+ onerror="t.step(function() { saw_link_onerror = true; })">
+<script>
+ t.step(function() {
+ assert_true(saw_link_onerror, "The pending parsing-blocking script should " +
+ "only run after the last element that " +
+ "contributes a script-blocking style " +
+ "sheet's error event is fired if the sheet " +
+ "fails to load.");
+ });
+ t.done();
+</script>
+</head>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.html
new file mode 100644
index 0000000000..e4f617d458
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="resources/link-load-error-events.sub.js"></script>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.https.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.https.html
new file mode 100644
index 0000000000..e4f617d458
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-error-events.https.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="resources/link-load-error-events.sub.js"></script>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-event.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-event.html
new file mode 100644
index 0000000000..e95fff7988
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-event.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<link rel="author" title="Josh Matthews" href="mailto:josh@joshmatthews.net">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-link-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+var saw_link_onload = false;
+var t = async_test("Check if the stylesheet's load event blocks the document load event");
+window.addEventListener('load', t.step_func_done(function() {
+ assert_true(saw_link_onload);
+}));
+</script>
+<link href="style.css?pipe=trickle(d3)" rel="stylesheet" id="style_test"
+ onload="t.step(function() { saw_link_onload = true; })"
+ onerror="t.unreached_func('Sheet should load OK')">
+</head>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-fired-before-scripting-unblocked.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-fired-before-scripting-unblocked.html
new file mode 100644
index 0000000000..a809cc44b1
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-load-fired-before-scripting-unblocked.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<link rel="author" title="Dom Farolino" href="mailto:dom@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+var saw_link_onload = false;
+var t = async_test("Check if the stylesheet's load event is fired before the " +
+ "pending parsing-blocking script is unblocked");
+</script>
+<link href="style.css?pipe=trickle(d3)" rel="stylesheet" id="style_test"
+ onload="t.step(function() { saw_link_onload = true; })"
+ onerror="t.unreached_func('Sheet should load OK')">
+<script>
+ t.step(function() {
+ assert_true(saw_link_onload, "The pending parsing-blocking script should " +
+ "only run after the last element that " +
+ "contributes a script-blocking style " +
+ "sheet's load event is fired.");
+ });
+ t.done();
+</script>
+</head>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-multiple-error-events.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-multiple-error-events.html
new file mode 100644
index 0000000000..9d112e88d1
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-multiple-error-events.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<link rel="author" title="Dom Farolino" href="mailto:dom@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-link-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link id=style_link rel=stylesheet>
+<script>
+ async_test(t => {
+ const link = document.querySelector('#style_link');
+ link.onload = t.unreached_func('Sheet should fail to load');
+ link.onerror = t.step_func(() => {
+ link.onerror = t.step_func_done(() => {});
+ link.href = 'nonexistent.css?second';
+ });
+
+ link.href = 'nonexistent.css?first';
+ }, "Check if the <link>'s error event fires for each stylesheet it fails to load");
+
+ </script>
+</head>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-multiple-load-events.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-multiple-load-events.html
new file mode 100644
index 0000000000..b5550bb382
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-multiple-load-events.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<link rel="author" title="Dom Farolino" href="mailto:dom@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-link-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link id=style_link rel=stylesheet>
+<script>
+ async_test(t => {
+ const link = document.querySelector('#style_link');
+ link.onerror = t.unreached_func('Sheet should load successfully');
+ link.onload = t.step_func(() => {
+ link.onload = t.step_func_done(() => {});
+ link.href = 'style.css?second';
+ });
+
+ link.href = 'style.css?first';
+
+ }, "Check if the <link>'s load event fires for each stylesheet it loads");
+ </script>
+</head>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute-ascii-case-insensitive-notref.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute-ascii-case-insensitive-notref.html
new file mode 100644
index 0000000000..04e3a7cb02
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute-ascii-case-insensitive-notref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>link element rel is ASCII case-insensitive (mismatch reference)</title>
+<link rel="stylesheet" href="stylesheet.css">
+<p>Test passes if background is not red.</p>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute-ascii-case-insensitive.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute-ascii-case-insensitive.html
new file mode 100644
index 0000000000..5ee55f7d2e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute-ascii-case-insensitive.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>link element rel is ASCII case-insensitive</title>
+<link rel="help" href="https://html.spec.whatwg.org/#the-link-element">
+<link rel="help" href="https://html.spec.whatwg.org/#attr-link-rel">
+<link rel="help" href="https://html.spec.whatwg.org/#linkTypes">
+<meta name="assert" content="link element's rel attribute is ASCII case-insensitive.">
+<link rel="mismatch" href="link-rel-attribute-ascii-case-insensitive-notref.html">
+
+<!-- Load sheet with a red background (rel attribute value is case-sensitive
+ equal to "stylesheet") -->
+<link rel="stylesheet" href="stylesheet.css">
+
+<!-- Load sheet with white background (rel attribute value is ASCII
+ case-insensitive equal to "stylesheet") -->
+<link rel="StyLeShEeT" href="style.css">
+
+<!-- Do not load sheet with a red background (rel attribute value is
+ case-insensitive equal to "stylesheet") -->
+<link rel="ſtyleſheet" href="stylesheet.css">
+
+<p>Test passes if background is not red.</p>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute.html
new file mode 100644
index 0000000000..14d06227ac
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rel-attribute.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<script src = "/resources/testharness.js"></script>
+<script src = "/resources/testharnessreport.js"></script>
+
+<link id="light-link" rel="stylesheet" href="resources/link-rel-attribute.css">
+<div id="light-div" class="green">I"m green when light DOM link is on</div>
+
+<div id="host">
+ I"m green when Shadow DOM link is on
+ <template id="shadow-dom">
+ <link id="shadow-link" rel="stylesheet" href="resources/link-rel-attribute.css">
+ <div id="shadow-div" class="green">
+ <slot></slot>
+ </div>
+ </template>
+</div>
+
+<script>
+
+function testLinkRelModification(testDiv, testLink) {
+ assert_equals(getComputedStyle(testDiv).color, "rgb(0, 128, 0)");
+ testLink.setAttribute("rel", "no-stylesheet");
+ assert_equals(getComputedStyle(testDiv).color, "rgb(0, 0, 0)");
+ testLink.setAttribute("rel", "stylesheet");
+ assert_equals(getComputedStyle(testDiv).color, "rgb(0, 128, 0)");
+ testLink.removeAttribute("rel");
+ assert_equals(getComputedStyle(testDiv).color, "rgb(0, 0, 0)");
+}
+
+test (() => {
+ testLinkRelModification(document.querySelector("#light-div"),
+ document.querySelector("#light-link"));
+}, "Removing stylesheet from link rel attribute should remove the stylesheet for light DOM");
+
+test (() => {
+ var host = document.querySelector("#host");
+ var shadow = host.attachShadow({ mode: "open" });
+ var tmpl = document.querySelector("template#shadow-dom");
+ var clone = document.importNode(tmpl.content, true);
+ shadow.appendChild(clone);
+ testLinkRelModification(shadow.querySelector("#shadow-div"),
+ shadow.querySelector("#shadow-link"));
+}, "Removing stylesheet from link rel attribute should remove the stylesheet for shadow DOM");
+</script>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rellist.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rellist.html
new file mode 100644
index 0000000000..8647426755
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-rellist.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>link.relList: non-string contains</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-link-element">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#domtokenlist">
+<link rel="help" href="https://webidl.spec.whatwg.org/#ecmascript-binding">
+<link rel="help" href="http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf#page=57">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link id="link" rel="undefined null 0 NaN Infinity">
+<div id="log"></div>
+<script>
+test(function() {
+ var list = document.getElementById("link").relList;
+ assert_equals(list.contains(undefined), true); //"undefined"
+ assert_equals(list.contains(null), true); //"null"
+ assert_equals(list.contains(-0), true); //"0"
+ assert_equals(list.contains(+0), true); //"0"
+ assert_equals(list.contains(NaN), true); //"NaN"
+ assert_equals(list.contains(+Infinity), true); //"Infinity"
+ assert_equals(list.contains(-Infinity), false); //"-Infinity"
+ assert_equals(list.supports("stylesheet"), true);
+ assert_equals(list.supports("nosuchrelvalueever"), false);
+});
+</script>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html
new file mode 100644
index 0000000000..575324d761
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-01.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>link: error events</title>
+<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-link-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=/common/get-host-info.sub.js></script>
+<div id="log"></div>
+<div id="test">
+<script>
+var t404 = async_test("Should get an error event for a 404 error.")
+t404.step(function() {
+ var elt = document.createElement("link");
+ elt.onerror = t404.step_func(function() {
+ assert_true(true, "Got error event for 404 error.")
+ t404.step_timeout(function() { t404.done() }, 0);
+ })
+ elt.onload = t404.unreached_func("load event should not be fired");
+ elt.rel = "stylesheet";
+ elt.href = "nonexistent_stylesheet.css";
+ document.getElementsByTagName("head")[0].appendChild(elt);
+})
+
+var tUnsupported = async_test("Should get an error event for an unsupported URL.")
+tUnsupported.step(function() {
+ var elt = document.createElement("link");
+ elt.onerror = tUnsupported.step_func(function() {
+ assert_true(true, "Got error event for unsupported URL.")
+ tUnsupported.step_timeout(function() { tUnsupported.done() }, 0);
+ })
+ elt.onload = tUnsupported.unreached_func("load event should not be fired");
+ elt.rel = "stylesheet";
+ elt.href = "nonexistent:stylesheet.css";
+ document.getElementsByTagName("head")[0].appendChild(elt);
+});
+</script>
+<script src=resources/link-style-error.js></script>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-limited-quirks.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-limited-quirks.html
new file mode 100644
index 0000000000..d3c520ba75
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-limited-quirks.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//" "">
+<title>link: error events in limited quirks mode</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=/common/get-host-info.sub.js></script>
+<div id="log"></div>
+<script src=resources/link-style-error.js></script>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-quirks.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-quirks.html
new file mode 100644
index 0000000000..ae2efa415e
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-style-error-quirks.html
@@ -0,0 +1,7 @@
+<!DOCTYPE HTML PUBLIC "-//Sun Microsystems Corp.//DTD HotJava Strict HTML//" "">
+<title>link: error events in quirks mode</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src=/common/get-host-info.sub.js></script>
+<div id="log"></div>
+<script src=resources/link-style-error.js></script>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-type-attribute-ref.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-type-attribute-ref.html
new file mode 100644
index 0000000000..f32472105d
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-type-attribute-ref.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<p>You should see a green rectangle below</p>
+<div style="width:100px;height:100px;background-color:green"></div>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-type-attribute.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-type-attribute.html
new file mode 100644
index 0000000000..80acb9f3dc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/link-type-attribute.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<link rel=match href=link-type-attribute-ref.html>
+<link rel="stylesheet" type="application/javascript" href="data:text/css,div { background-color: red !important; }">
+<link rel="stylesheet" type="ABCtext/css" href="data:text/css,div { background-color: red !important; }">
+<link rel="stylesheet" type="text/cssDEF" href="data:text/css,div { background-color: red !important; }">
+<link rel="stylesheet" type="text/invalid" href="data:text/css,div { background-color: red !important; }">
+<link rel="stylesheet" type="invalid" href="data:text/css,div { background-color: red !important; }">
+<p>You should see a green rectangle below</p>
+<div style="width:100px;height:100px;background-color:green"></div>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/bad.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/bad.css
new file mode 100644
index 0000000000..4e1fe36165
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/bad.css
@@ -0,0 +1,4 @@
+p {
+ background-color: red;
+ color: black;
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/css.py b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/css.py
new file mode 100644
index 0000000000..1a11c1d5b3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/css.py
@@ -0,0 +1,7 @@
+def main(request, response):
+ response.add_required_headers = False
+ if b"content_type" in request.GET:
+ response.writer.write_header(b"Content-Type", request.GET.first(b"content_type"))
+ if b"nosniff" in request.GET:
+ response.writer.write_header(b"x-content-type-options", b"nosniff")
+ response.writer.write_content(u"body { background:red }")
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/empty-href.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/empty-href.css
new file mode 100644
index 0000000000..60f1eab971
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/empty-href.css
@@ -0,0 +1,3 @@
+body {
+ color: red;
+}
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/good.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/good.css
new file mode 100644
index 0000000000..1da5e2b8cf
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/good.css
@@ -0,0 +1,3 @@
+p {
+ color: green;
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-load-error-events.sub.js b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-load-error-events.sub.js
new file mode 100644
index 0000000000..33c8709579
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-load-error-events.sub.js
@@ -0,0 +1,192 @@
+/**
+ * This is the guts of the load/error event tests for <link rel="stylesheet">.
+ *
+ * We have a list of tests each of which is an object containing: href value,
+ * expected load success boolean, test description. Href values are set up in
+ * such a way that we guarantee that all stylesheet URLs are unique. This
+ * avoids issues around caching of sheets based on URL.
+ */
+
+// Our URLs are random, so we don't use them in error messages by
+// default, but enable doing it if someone wants to debug things.
+const DEBUG_URLS = false;
+
+var isHttps = location.protocol == "https:";
+
+var tests = [
+ // Basic tests
+ {
+ href: existingSheet(),
+ success: true,
+ description: "Basic load of stylesheet",
+ },
+ {
+ href: nonexistentSheet(),
+ success: false,
+ description: "Attempted load of nonexistent stylesheet",
+ },
+ {
+ href: `data:text/css,@import url("${existingSheet()}")`,
+ success: true,
+ description: "Import of stylesheet",
+ },
+ {
+ href: `data:text/css,@import url("${nonexistentSheet()}")`,
+ success: false,
+ description: "Import of nonexistent stylesheet",
+ },
+ {
+ href: `data:text/css,@import url("data:text/css,@import url('${existingSheet()}')")`,
+ success: true,
+ description: "Import of import of stylesheet",
+ },
+ {
+ href: `data:text/css,@import url("data:text/css,@import url('${nonexistentSheet()}')")`,
+ success: false,
+ description: "Import of import of nonexistent stylesheet",
+ },
+
+ // Non-CSS-response tests.
+ {
+ href: makeUnique(""),
+ success: false,
+ description: "Load of non-CSS stylesheet",
+ },
+ {
+ href: `data:text/css,@import url("${makeUnique("")}")`,
+ success: false,
+ description: "Import of non-CSS stylesheet",
+ },
+ {
+ href: `data:text/css,@import url("data:text/css,@import url('${makeUnique("")}')")`,
+ success: false,
+ description: "Import of import of non-CSS stylesheet",
+ },
+
+ // http:// tests, to test what happens with mixed content blocking.
+ {
+ href: httpSheet(),
+ success: !isHttps,
+ description: "Load of http:// stylesheet",
+ },
+ {
+ href: `data:text/css,@import url("${httpSheet()}")`,
+ success: !isHttps,
+ description: "Import of http:// stylesheet",
+ },
+ {
+ href: `data:text/css,@import url("data:text/css,@import url('${httpSheet()}')")`,
+ success: !isHttps,
+ description: "Import of import of http:// stylesheet",
+ },
+
+ // https:// tests just as a control
+ {
+ href: httpsSheet(),
+ success: true,
+ description: "Load of https:// stylesheet",
+ },
+ {
+ href: `data:text/css,@import url("${httpsSheet()}")`,
+ success: true,
+ description: "Import of https:// stylesheet",
+ },
+ {
+ href: `data:text/css,@import url("data:text/css,@import url('${httpsSheet()}')")`,
+ success: true,
+ description: "Import of import of https:// stylesheet",
+ },
+
+ // Tests with multiple imports some of which are slow and some are fast.
+ {
+ href: `data:text/css,@import url("${slowResponse(existingSheet())}"); @import url("${nonexistentSheet()}");`,
+ success: false,
+ description: "Slow successful import, fast failing import",
+ },
+ {
+ href: `data:text/css,@import url("${existingSheet()}"); @import url("${slowResponse(nonexistentSheet())}");`,
+ success: false,
+ description: "Fast successful import, slow failing import",
+ }
+];
+
+// Note: Here we really do need to use "let" at least for the href,
+// because we lazily evaluate it in the unreached cases.
+for (var test of tests) {
+ let {href, success, description} = test;
+ var t = async_test(description);
+ var link = document.createElement("link");
+ link.rel = "stylesheet";
+ hrefString = DEBUG_URLS ? `: ${href}` : "";
+ if (success) {
+ link.onload = t.step_func_done(() => {});
+ link.onerror = t.step_func_done(() => assert_unreached(`error fired when load expected${hrefString}`) );
+ } else {
+ link.onerror = t.step_func_done(() => {});
+ link.onload = t.step_func_done(() => assert_unreached(`load fired when error expected${hrefString}`) );
+ }
+ link.href = href;
+ document.head.appendChild(link);
+}
+
+/* Utility function */
+function makeUnique(url) {
+ // Make sure we copy here, even if the thing coming in is a URL, so we don't
+ // mutate our caller's data.
+ url = new URL(url, location.href);
+ // We want to generate a unique URI to avoid the various caches browsers have
+ // for stylesheets. We don't want to just use a counter, because that would
+ // not be robust to the test being reloaded or othewise run multiple times
+ // without a browser restart. We don't want to use timstamps, because those
+ // are not likely to be unique across calls to this function, especially given
+ // the degraded timer resolution browsers have due to Spectre.
+ //
+ // So just fall back on Math.random() and assume it can't duplicate values.
+ url.searchParams.append("r", Math.random());
+ return url;
+}
+
+function existingSheet() {
+ return makeUnique("resources/good.css");
+}
+
+/**
+ * Function the add values to the "pipe" search param. See
+ * http://wptserve.readthedocs.io/en/latest/pipes.html for why one would do
+ * this. Because this param uses a weird '|'-separated syntax instead of just
+ * using multiple params with the same name, we need some manual code to munge
+ * the value properly.
+ */
+function addPipe(url, pipeVal) {
+ url = new URL(url, location.href);
+ var params = url.searchParams;
+ var oldVal = params.get("pipe");
+ if (oldVal) {
+ params.set("pipe", oldVal + "|" + pipeVal);
+ } else {
+ params.set("pipe", pipeVal);
+ }
+ return url;
+}
+
+function nonexistentSheet() {
+ return addPipe(existingSheet(), "status(404)");
+}
+
+function httpSheet() {
+ var url = existingSheet();
+ url.protocol = "http";
+ url.port = {{ports[http][0]}};
+ return url;
+}
+
+function httpsSheet() {
+ var url = existingSheet();
+ url.protocol = "https";
+ url.port = {{ports[https][0]}};
+ return url;
+}
+
+function slowResponse(url) {
+ return addPipe(url, "trickle(d1)");
+}
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-rel-attribute.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-rel-attribute.css
new file mode 100644
index 0000000000..fa95e11ba9
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-rel-attribute.css
@@ -0,0 +1,3 @@
+.green {
+ color: green;
+}
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-style-error.js b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-style-error.js
new file mode 100644
index 0000000000..d1fa5ac2d6
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/link-style-error.js
@@ -0,0 +1,47 @@
+["<link>", "@import"].forEach(linkType => {
+ [
+ ["same-origin", "resources/css.py"],
+ ["cross-origin", get_host_info().HTTP_REMOTE_ORIGIN + "/html/semantics/document-metadata/the-link-element/resources/css.py"]
+ ].forEach(originType => {
+ ["no Content-Type", "wrong Content-Type", "broken Content-Type"].forEach(contentType => {
+ ["no nosniff", "nosniff"].forEach(nosniff => {
+ async_test(t => {
+ const l = document.createElement("link");
+ t.add_cleanup(() => l.remove());
+ if (nosniff === "nosniff" || contentType === "wrong Content-Type" && (document.compatMode === "CSS1Compat" || originType[0] === "cross-origin")) {
+ l.onerror = t.step_func_done();
+ l.onload = t.unreached_func("error event should have fired");
+ } else {
+ l.onload = t.step_func_done();
+ l.onerror = t.unreached_func("load event should have fired");
+ }
+ l.rel = "stylesheet";
+ let query = [];
+ if (contentType === "broken Content-Type") {
+ query.push("content_type=oops");
+ } else if (contentType === "wrong Content-Type") {
+ query.push("content_type=text/plain")
+ }
+ if (nosniff === "nosniff") {
+ query.push("nosniff");
+ }
+ let stringQuery = "";
+ query.forEach(val => {
+ if (stringQuery === "") {
+ stringQuery += "?" + val;
+ } else {
+ stringQuery += "&" + val;
+ }
+ });
+ const link = new URL(originType[1] + stringQuery, location).href;
+ if (linkType === "<link>") {
+ l.href = link;
+ } else {
+ l.href = "data:text/css,@import url(" + link + ");";
+ }
+ document.head.appendChild(l);
+ }, "Stylesheet loading using " + linkType + " with " + contentType + ", " + originType[0] + ", and " + nosniff);
+ });
+ });
+ });
+});
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/neutral.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/neutral.css
new file mode 100644
index 0000000000..796c55c42f
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/neutral.css
@@ -0,0 +1,3 @@
+body {
+ background-color: gray;
+}
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet.css
new file mode 100644
index 0000000000..e1b2552ffe
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/resources/stylesheet.css
@@ -0,0 +1,3 @@
+body {
+ background-color: green;
+}
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/style.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/style.css
new file mode 100644
index 0000000000..d48115e565
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/style.css
@@ -0,0 +1,3 @@
+body {
+ background-color: white;
+} \ No newline at end of file
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-change-href-ref.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-change-href-ref.html
new file mode 100644
index 0000000000..9ae6e36655
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-change-href-ref.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<meta charset="utf-8">
+<style>
+ p {
+ color: green;
+ }
+</style>
+<p>This text should be green on a white background
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-change-href.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-change-href.html
new file mode 100644
index 0000000000..6a3f18de98
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-change-href.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Obtaining a new stylesheet removes styles from the previous stylesheet.</title>
+<link rel=match href=stylesheet-change-href-ref.html>
+<script>
+ function changeHref() {
+ var elem = document.getElementById('stylesheet');
+ elem.href = 'resources/good.css';
+ elem.onload = null;
+ }
+</script>
+<link id=stylesheet rel=stylesheet href="resources/bad.css" onload="changeHref()">
+<p>This text should be green on a white background
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-empty-href-ref.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-empty-href-ref.html
new file mode 100644
index 0000000000..63b75d0ae2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-empty-href-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test</title>
+<style>
+body {
+ color: green;
+}
+</style>
+<p>This text should be green.
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-empty-href.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-empty-href.html
new file mode 100644
index 0000000000..16b14efacc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-empty-href.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test</title>
+<link rel=match href=stylesheet-empty-href-ref.html>
+<style>
+body {
+ color: green;
+}
+</style>
+<base href=resources/empty-href.css>
+<link rel=stylesheet href>
+<p>This text should be green.
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-media-ref.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-media-ref.html
new file mode 100644
index 0000000000..63b75d0ae2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-media-ref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test</title>
+<style>
+body {
+ color: green;
+}
+</style>
+<p>This text should be green.
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-media.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-media.html
new file mode 100644
index 0000000000..9a72924cf4
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-media.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test</title>
+<link rel=match href=stylesheet-media-ref.html>
+<style>
+body {
+ color: green;
+}
+</style>
+<link rel=stylesheet id=link>
+<script>
+// This tests for a bug in Servo, where it would treat the media attribute as
+// if it was the href attribute.
+var link = document.getElementById("link");
+link.setAttribute("media", "all")
+</script>
+<p>This text should be green.
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-not-removed-until-next-stylesheet-loads.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-not-removed-until-next-stylesheet-loads.html
new file mode 100644
index 0000000000..ab8ee727f2
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-not-removed-until-next-stylesheet-loads.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<link rel="author" title="Dom Farolino" href="mailto:dom@chromium.org">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/links.html#link-type-stylesheet">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link href="style.css" rel="stylesheet" id="style_test">
+<script>
+ test(function() {
+ assert_true(document.styleSheets.length === 1 &&
+ document.styleSheets[0].href.includes("style.css"),
+ "The style sheet 'style.css' must be available to scripts");
+
+ style_test.href = "resources/neutral.css?pipe=trickle(d1)";
+
+ assert_true(document.styleSheets.length === 1 &&
+ document.styleSheets[0].href.includes("style.css"),
+ "The style sheet 'style.css' must remain accessible to " +
+ "scripts until its replacement has finished loading");
+ }, "Check that a style sheet loaded by a <link> is available until its successor is loaded");
+</script>
+</head>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-with-base-ref.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-with-base-ref.html
new file mode 100644
index 0000000000..83f0d06772
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-with-base-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Stylesheet Without Base Tag</title>
+ <style>
+ body { background-color: green; }
+ </style>
+</head>
+<body>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-with-base.html b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-with-base.html
new file mode 100644
index 0000000000..a9f2a8bce0
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet-with-base.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Stylesheet With Base Tag</title>
+ <link rel="match" href="stylesheet-with-base-ref.html">
+ <base href="resources/">
+ <link rel="stylesheet" href="stylesheet.css">
+</head>
+<body>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet.css b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet.css
new file mode 100644
index 0000000000..e8f24f94a3
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet.css
@@ -0,0 +1,3 @@
+body {
+ background-color: red;
+}
diff --git a/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet.py b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet.py
new file mode 100644
index 0000000000..1a4dec2724
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/document-metadata/the-link-element/stylesheet.py
@@ -0,0 +1,9 @@
+def main(request, response):
+ try:
+ count = int(request.server.stash.take(request.GET[b"id"]))
+ except:
+ count = 0
+ if b"count" in request.GET:
+ return str(count)
+ request.server.stash.put(request.GET[b"id"], str(count + 1))
+ return u'body { color: red }'