Automatic update from web-platform-tests Separate between HTML streaming and <template for> patching HTML streaming, as well as the new positional methods, receive a "NewHTMLSettingMethods" runtime flag, and move to domparsing/tentative, to separate them from the somewhat orthogonal <template for> patching. Bug: 491743369 Change-Id: Ic411e1af7c5644be3062564683d039d6847427b5 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7657845 Reviewed-by: Philip Jägenstedt <foolip@chromium.org> Commit-Queue: Noam Rosenthal <nrosenthal@google.com> Cr-Commit-Position: refs/heads/main@{#1598305} -- wpt-commits: f132f6179b468268083f40463abc93b3242b989e wpt-pr: 58450
217 lines
7.9 KiB
HTML
217 lines
7.9 KiB
HTML
<!doctype html>
|
|
<meta charset="utf-8" />
|
|
<title>HTML partial updates - streamHTML</title>
|
|
<link rel="help" href="https://github.com/WICG/declarative-partial-updates" />
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<style id="style"></style>
|
|
<p id="target"></p>
|
|
<div id="container"></div>
|
|
<script>
|
|
promise_test(async (t) => {
|
|
const placeholder = document.createElement("div");
|
|
placeholder.innerHTML = "A";
|
|
const writable = placeholder.streamHTML();
|
|
assert_true(
|
|
writable instanceof WritableStream,
|
|
"node.streamHTML() returns a writable stream",
|
|
);
|
|
const response = new Response("<span>B</span>", {
|
|
headers: { "Content-Type": "text/html" },
|
|
});
|
|
await response.body.pipeThrough(new TextDecoderStream()).pipeTo(writable);
|
|
assert_equals(placeholder.textContent, "B");
|
|
assert_true(response.bodyUsed);
|
|
}, "piping a response into streamHTML()");
|
|
|
|
promise_test(async (t) => {
|
|
const placeholder = document.createElement("div");
|
|
placeholder.innerHTML = "<span>A</span>";
|
|
const writable = placeholder.streamHTML();
|
|
assert_true(
|
|
writable instanceof WritableStream,
|
|
"node.streamHTML() returns a writable stream",
|
|
);
|
|
const writer = writable.getWriter();
|
|
await writer.write("B");
|
|
await writer.close();
|
|
assert_equals(placeholder.textContent, "B");
|
|
}, "writing a string to streamHTML()");
|
|
|
|
promise_test(async (t) => {
|
|
const placeholder = document.createElement("div");
|
|
placeholder.innerHTML = "<span>A</span>";
|
|
const writable = placeholder.streamHTML();
|
|
assert_true(
|
|
writable instanceof WritableStream,
|
|
"node.streamHTML() returns a writable stream",
|
|
);
|
|
assert_equals(placeholder.textContent, "");
|
|
const writer = writable.getWriter();
|
|
await writer.write("B");
|
|
await writer.close();
|
|
assert_equals(placeholder.textContent, "B");
|
|
}, "streamHTML() should remove existing content immediately");
|
|
|
|
promise_test(async (t) => {
|
|
const placeholder = document.createElement("div");
|
|
placeholder.innerHTML = "<span>A</span>";
|
|
const writable = placeholder.streamHTML();
|
|
assert_true(
|
|
writable instanceof WritableStream,
|
|
"node.streamHTML() returns a writable stream",
|
|
);
|
|
const writer = writable.getWriter();
|
|
await writer.write("<span>B</span>");
|
|
assert_equals(placeholder.textContent, "B");
|
|
await writer.close();
|
|
}, "streamHTML() does not buffer until close()");
|
|
|
|
promise_test(async (t) => {
|
|
const placeholder = document.createElement("div");
|
|
placeholder.innerHTML = "Before";
|
|
const writable = placeholder.streamHTML();
|
|
assert_true(
|
|
writable instanceof WritableStream,
|
|
"streamHTML() returns a writable stream",
|
|
);
|
|
const writer = writable.getWriter();
|
|
await promise_rejects_js(t, TypeError, writer.write(Symbol("sym")));
|
|
assert_equals(placeholder.textContent, "");
|
|
}, "writing a Symbol to streamHTML()");
|
|
|
|
promise_test(async (t) => {
|
|
const placeholder = document.createElement("div");
|
|
placeholder.innerHTML = "12";
|
|
const writable = placeholder.streamHTML();
|
|
assert_true(
|
|
writable instanceof WritableStream,
|
|
"node.streamHTML() returns a writable stream",
|
|
);
|
|
const writer = writable.getWriter();
|
|
await writer.write(345);
|
|
await writer.close();
|
|
assert_equals(placeholder.textContent, "345");
|
|
assert_equals(placeholder.childNodes.length, 1);
|
|
assert_equals(placeholder.firstChild.nodeType, Node.TEXT_NODE);
|
|
assert_equals(placeholder.firstChild.textContent, "345");
|
|
}, "writing numbers to streamHTML()");
|
|
|
|
promise_test(async (t) => {
|
|
const placeholder = document.createElement("div");
|
|
placeholder.innerHTML = "start ";
|
|
const writable = placeholder.streamHTML();
|
|
assert_true(
|
|
writable instanceof WritableStream,
|
|
"node.streamHTML() returns a writable stream",
|
|
);
|
|
const writer = writable.getWriter();
|
|
await writer.write(null);
|
|
await writer.write(" ");
|
|
await writer.write(undefined);
|
|
await writer.close();
|
|
assert_equals(placeholder.textContent, "null undefined");
|
|
}, "writing null or undefined to streamHTML()");
|
|
|
|
promise_test(async (t) => {
|
|
const style = document.querySelector("#style");
|
|
const writable = style.streamHTML();
|
|
assert_true(
|
|
writable instanceof WritableStream,
|
|
"node.streamHTML() returns a writable stream",
|
|
);
|
|
const writer = await writable.getWriter();
|
|
await writer.write("#target { color: rgba(100, 0, 100); }");
|
|
await writer.close();
|
|
assert_equals(
|
|
getComputedStyle(document.querySelector("#target")).color,
|
|
"rgb(100, 0, 100)",
|
|
);
|
|
}, "streamHTML() can stream into <style>");
|
|
|
|
promise_test(async (t) => {
|
|
const placeholder = document.createElement("div");
|
|
placeholder.innerHTML = "start ";
|
|
const writable = placeholder.streamHTML();
|
|
const writer = writable.getWriter();
|
|
await writer.write("ABC");
|
|
await writer.abort("abort-reason");
|
|
await writer.write("DEF").catch(() => {});
|
|
assert_equals(placeholder.textContent, "ABC");
|
|
}, "Aborting streamHTML()");
|
|
|
|
promise_test(async (t) => {
|
|
const placeholder = document.createElement("div");
|
|
placeholder.innerHTML = "before";
|
|
const writer1 = placeholder.streamHTML().getWriter();
|
|
const writer2 = placeholder.streamHTML().getWriter();
|
|
await writer1.write("<span>A</span>");
|
|
await writer2.write("<span>B</span>");
|
|
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
await writer1.write("C");
|
|
await writer1.close();
|
|
await writer2.close();
|
|
assert_equals(placeholder.textContent, "ABC");
|
|
}, "Interleaved streamHTML() writes");
|
|
|
|
promise_test(async (t) => {
|
|
const element = document.createElement("div");
|
|
document.body.append(element);
|
|
window.did_eval_script = false;
|
|
const writer = element.streamHTML({ runScripts: true }).getWriter();
|
|
assert_false(window.did_eval_script);
|
|
await writer.write("<script>window.did_eval_script = true;");
|
|
assert_false(window.did_eval_script);
|
|
await writer.write("<");
|
|
assert_false(window.did_eval_script);
|
|
await writer.write("/script>");
|
|
assert_false(window.did_eval_script);
|
|
}, "streamHTML should not execute scripts when connected");
|
|
|
|
promise_test(async (t) => {
|
|
const element = document.createElement("div");
|
|
element.innerHTML = "<p>before;</p>";
|
|
document.body.append(element);
|
|
const writer = element
|
|
.streamHTML({ sanitizer: { removeElements: ["p"] } })
|
|
.getWriter();
|
|
await writer.write("<p>forbidden</p>");
|
|
await writer.write("<span>allowed</span>");
|
|
await writer.close();
|
|
assert_equals(element.textContent, "allowed");
|
|
}, "streamHTML should pass sanitizer options");
|
|
|
|
promise_test(async (t) => {
|
|
const element = document.createElement("div");
|
|
document.body.append(element);
|
|
const writer = element.streamHTML().getWriter();
|
|
await writer.write("<script id=forbidden<" + "/script>");
|
|
await writer.close();
|
|
assert_equals(element.querySelector("script"), null);
|
|
}, "streamHTML uses safe sanitizer");
|
|
|
|
promise_test(async (t) => {
|
|
const element = document.createElement("div");
|
|
const shadow = element.attachShadow({mode: "open"});
|
|
shadow.innerHTML = "<p>before;</p>";
|
|
document.body.append(element);
|
|
const writer = shadow
|
|
.streamHTML({ sanitizer: { removeElements: ["p"] } })
|
|
.getWriter();
|
|
await writer.write("<p>forbidden</p>");
|
|
await writer.write("<span>allowed</span>");
|
|
await writer.close();
|
|
assert_equals(shadow.textContent, "allowed");
|
|
}, "streamHTML on ShadowRoot");
|
|
|
|
promise_test(async (t) => {
|
|
const element = document.createElement("div");
|
|
const shadow = element.attachShadow({mode: "open"});
|
|
document.body.append(element);
|
|
const writer = shadow.streamHTML().getWriter();
|
|
await writer.write("<script id=forbidden<" + "/script>");
|
|
await writer.close();
|
|
assert_equals(shadow.querySelector("script"), null);
|
|
}, "streamHTML on ShadowRoot uses safe sanitizer");
|
|
</script>
|