Skip to content

emitter: a child that fails to construct reports its own error, not the reconciler's - #407

Merged
shreeve merged 1 commit into
mainfrom
runtime/keyed-for-error
Sep 22, 2026
Merged

shreeve merged 1 commit into
mainfrom
runtime/keyed-for-error

Conversation

@shreeve

@shreeve shreeve commented Sep 22, 2026

Copy link
Copy Markdown
Owner

A child component that fails to construct is caught, reported, and left as null, but the setups for what it holds — a keyed for, an if, a text binding — still ran. They ran against an anchor that was never placed, and __reconcile's TypeError: undefined is not an object (evaluating 'anchor.parentNode') replaced the real error. The first error a newcomer meets, a misspelled name in a prop, came out as that.

Box contentOffsetY: nosuchname      # an undefined name
  for item, n in @items
    Text key: n, "#{item}"

On main this throws the TypeError; here it throws ReferenceError: nosuchname is not defined with the stack at the prop.

Cause and fix (src/emitter.js, renderChildComponent). The setups that belong to a child's projected content now run inside if (child) { … }. A child component made inside that content keeps its own setup step, which already checks itself, so it never sticks mid-mount. __reconcile refuses, by its own message, a list whose anchor was never placed; it does not fire here.

The DOM had the same masking. It appears only when the name is a prop of a child component that holds the list: on a plain div the throw aborts the whole mount before any list code runs.

Tests (all fail on main): in test/ui/components.test.js, two broken children kept to their placeholders, each reported as its own ReferenceError, with later state changes and unmount clean, plus an onError boundary around a child that holds a keyed for; in packages/tui/test.rip, the example above makes renderToString throw the ReferenceError and print nothing.

Corpus unchanged (0 written). dist/ regenerated. bun run test:all: 29 lanes, 12,668 tests.

…s setups, so its own error is the one reported; its projected children still settle, and the reconciler refuses a list whose anchor was never placed
@shreeve
shreeve merged commit 1cef3d1 into main Sep 22, 2026
2 checks passed
@shreeve
shreeve deleted the runtime/keyed-for-error branch September 22, 2026 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant