Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/dom/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ export const render = (where, what) => {
const d = hole.valueOf(false);
where.replaceChildren(d);
}
else known[1].update(hole);
else {
known[1].update(hole);
hole = known[1];
}
rendered.set(where, [scope, hole]);
}
else {
Expand Down
60 changes: 60 additions & 0 deletions test/render.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Repeated callback render regression</title>
</head>
<body>
<pre id="result">Running...</pre>
<script type="module">
const result = document.querySelector('#result');
try {
const { render, html } = await import(
location.search === '?prod' ? '../dist/prod/dom.js' : '../dist/dev/dom.js'
);
const assert = (condition, message) => {
if (!condition) throw new Error(message);
};

// #given — a callback with the same template across renders
const text = document.createElement('div');
document.body.append(text);
const message = value => html`<p>${value}</p>`;
render(text, () => message('first'));
const paragraph = text.firstChild;

// #when — more than two consecutive updates
render(text, () => message('second'));
render(text, () => message('third'));
render(text, () => message('fourth'));

// #then
assert(text.textContent === 'fourth', 'Repeated text renders must show the latest value');
assert(text.firstChild === paragraph, 'Repeated text renders must keep the DOM node');

// #given — an empty list followed by restored entries
const list = document.createElement('div');
document.body.append(list);
const entries = values => html`<ul>${values.map(value => html`<li>${value}</li>`)}</ul>`;
render(list, () => entries([]));
render(list, () => entries(['saved']));
const ul = list.firstChild;

// #when — a new entry arrives after the second render
render(list, () => entries(['pasted', 'saved']));

// #then
assert(
JSON.stringify(Array.from(list.querySelectorAll('li'), li => li.textContent)) === '["pasted","saved"]',
'The third list render must show both entries in order'
);
assert(list.firstChild === ul, 'Updating the list must keep its root node');
result.textContent = 'PASS: repeated text and list renders';
}
catch (error) {
result.textContent = `FAIL: ${error.message}`;
throw error;
}
</script>
</body>
</html>