Files
ladybird/Tests/LibWeb/Text/input/HTML/parser-streams-external-script.html
Aliaksandr Kalenik 4762c4fa5c LibWeb: Add incremental HTML parsing
Introduce IncrementalDocumentParser, which streams the response body
through a TextCodec::StreamingDecoder into the HTMLTokenizer one chunk
at a time. The tokenizer pauses when it runs out of input and resumes
once the next chunk is appended; when the body closes we close the
tokenizer's input stream so it can finish the parse.

DocumentLoading routes HTML responses through the new parser instead of
buffering the full body before handing it to HTMLParser.
2026-04-29 04:12:44 +02:00

48 lines
2.2 KiB
HTML

<!DOCTYPE html>
<script src="../include.js"></script>
<script>
asyncTest(async (done) => {
internals.setTestTimeout(5000);
const httpServer = httpTestServer();
const scriptURL = await httpServer.createEcho("GET", "/parser-streams-external-script.js", {
status: 200,
headers: {
"Content-Type": "text/javascript",
},
body: `document.getElementById("target").textContent = "script ran";`,
});
const delayedScriptURL = await httpServer.createEcho("GET", "/parser-streams-delayed-external-script.js", {
status: 200,
headers: {
"Content-Type": "text/javascript",
},
body: `document.getElementById("delayed-target").textContent = "delayed script ran";`,
});
const delayedScriptURLWithSlowResponse = `${delayedScriptURL}?chunks=1&chunk_delay_ms=300`;
const externalScriptStartTag = `<scr` + `ipt src="${scriptURL}">`;
const delayedExternalScriptStartTag = `<scr` + `ipt src="${delayedScriptURLWithSlowResponse}">`;
const scriptEndTag = `</scr` + `ipt>`;
const inlineScriptStartTag = `<scr` + `ipt>`;
const prefix = `<!DOCTYPE html><body>${" ".repeat(1500)}<div id="target">before</div>${externalScriptStartTag}${scriptEndTag}`;
const delayedPrefix = `${prefix}<div id="delayed-target">delayed before</div>${delayedExternalScriptStartTag}${scriptEndTag}<div id="same-chunk">same chunk</div>`;
const body = `${delayedPrefix}<div id="second-chunk">second chunk</div>${inlineScriptStartTag}window.onload = () => parent.postMessage(document.body.innerText.replace(/\\s+/g, " ").trim(), "*");${scriptEndTag}`;
const url = await httpServer.createEcho("GET", "/parser-streams-external-script", {
status: 200,
headers: {
"Content-Type": "text/html",
},
body,
});
const frame = document.createElement("iframe");
window.addEventListener("message", event => {
println(event.data);
done();
}, { once: true });
frame.src = `${url}?chunks=${delayedPrefix.length}&chunk_delay_ms=50`;
document.body.appendChild(frame);
});
</script>