feat(html): adoption-style hydration with mismatch reporting
hydrate(oldNode, newNode) normalizes the client tree to parser text-node granularity, walks both trees to report the first server/client markup disagreement (node, text, attribute, or child count, with a path), then morphs — matching nodes are adopted in place, the client render wins. choo.mount() now hydrates and console.warns on mismatch. Building this surfaced two real isomorphism divergences, both fixed: adjacent text nodes from template holes vs the parser's merged runs (folded via Node.normalize), and the server serializing onclick="" where the browser sets a property — event handlers now leave no trace in server markup at all. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014NgfSjHE11oFpoSnLVKLXd
This commit is contained in:
co-authored by
Claude Fable 5
parent
37bd8adf81
commit
13155a3469
@@ -45,9 +45,14 @@ test('boolean attributes render when truthy and drop when falsy', () => {
|
||||
assert.strictEqual(off.toString(), '<input />'.replace(' ', ' '))
|
||||
})
|
||||
|
||||
test('event handler functions are stripped', () => {
|
||||
test('event handler functions leave no trace in markup', () => {
|
||||
const res = html`<button onclick=${() => {}}>go</button>`
|
||||
assert.strictEqual(res.toString(), '<button onclick="">go</button>')
|
||||
assert.strictEqual(res.toString(), '<button >go</button>')
|
||||
})
|
||||
|
||||
test('handler-shaped attributes with non-function values still render', () => {
|
||||
const res = html`<a onclick=${'confirm()'}>x</a>`
|
||||
assert.strictEqual(res.toString(), '<a onclick="confirm()">x</a>')
|
||||
})
|
||||
|
||||
test('spread-style object interpolation renders attributes', () => {
|
||||
|
||||
Reference in New Issue
Block a user