playground streaming: appendChild(TextNode) instead of textContent +=

liveBlock.append was doing `pre.textContent += chunk` on every
streamed chunk. textContent's setter wipes all existing child
nodes and creates a single new text node from the concatenated
read+new value — perfectly correct semantically but under a fast
C-tier emit loop (one chunk per (newline) printf) the per-update
restringify was visibly dropping line breaks, rendering

  tick 0tick 10000tick 20000tick 30000…

horizontally instead of stacking vertically.

`pre.appendChild(document.createTextNode(chunk))` appends a new
text node alongside existing ones — no read-back, no restringify.
Browser renders the sequence of text nodes as concatenated text
inside the <pre> which already has `white-space: pre`, so every
embedded \n produces a real line break.

Pairs with the c-tier loader's `currentOnChunk(line + "\n")` fix:
loader adds the \n that Emscripten's Module.print convention
stripped, append preserves the \n end-to-end into the DOM.
This commit is contained in:
russell@unturf.com 2026-06-15 05:42:02 -04:00
parent cf7ff2219f
commit 32d38754f8
No known key found for this signature in database
2 changed files with 16 additions and 2 deletions

View file

@ -263,7 +263,14 @@ function startLiveBlock(tierName) {
outputEl.appendChild(block);
return {
append(chunk) {
pre.textContent += chunk;
// Append a TextNode rather than `pre.textContent += chunk`
// — the latter re-reads + restringifies + re-sets all
// existing children on every chunk, which under a fast
// C-tier loop (one chunk per (newline) printf) was
// dropping line breaks and rendering "tick 0tick 10000…"
// horizontally instead of stacking vertically. TextNode
// append preserves every byte verbatim.
pre.appendChild(document.createTextNode(chunk));
outputEl.scrollTop = outputEl.scrollHeight;
},
finalize(elapsedMs, kind, fullOutput) {

View file

@ -263,7 +263,14 @@ function startLiveBlock(tierName) {
outputEl.appendChild(block);
return {
append(chunk) {
pre.textContent += chunk;
// Append a TextNode rather than `pre.textContent += chunk`
// — the latter re-reads + restringifies + re-sets all
// existing children on every chunk, which under a fast
// C-tier loop (one chunk per (newline) printf) was
// dropping line breaks and rendering "tick 0tick 10000…"
// horizontally instead of stacking vertically. TextNode
// append preserves every byte verbatim.
pre.appendChild(document.createTextNode(chunk));
outputEl.scrollTop = outputEl.scrollHeight;
},
finalize(elapsedMs, kind, fullOutput) {