🐛 Bug Report
Template bindings may evaluate on a child element with no controller, crashing when a parent when directive tears down and recreates the child.
💻 Repro or Code Sample
https://stackblitz.com/edit/typescript-fuiufsk7?file=index.ts
Conditions required to reproduce:
- A parent component uses a
when directive to conditionally render a child custom element, with a property binding that pushes data onto the child:
${when(x => x.currentData, html`<my-child :data=${x => x.currentData}></my-child>`)}
- The parent's
when condition toggles — tearing down the child and then recreating it — while the property binding immediately pushes data onto the newly created child
- The child's template reads a property from the pushed data (e.g.
${x => x.data?.label})
When the when directive creates a new <my-child> element, the parent's :data binding sets .data on it at some point where the controller is undefined.
Steps to reproduce:
- Open the repro page
- Click Toggle (tears down
<my-child>, sets currentData = undefined)
- Click Toggle (rebuilds
<my-child>, sets currentData = { label: "A" })
- Click Cycle data (swaps
currentData to { label: "B" })
- Click Toggle — crash: the binding
x.data?.label evaluates with x as undefined
class MyChild extends FASTElement {
@observable data: { label: string } | undefined;
}
// Template reads from the pushed data
const childTemplate = html<MyChild>`
<div>
<p>Data: ${x => x.data?.label ?? "(none)"}</p>
</div>
`;
🤔 Expected Behavior
When the parent's when directive rebuilds the child element and the property binding pushes data, template bindings on the child should not evaluate until the Controller is available.
😯 Current Behavior
The parent's when directive creates a new child element and the :data binding immediately sets .data on it. The observable change notification causes the child's template bindings to evaluate before the controller is available. At that point the Controller is not connected, and the binding's source (x) is undefined, causing a crash.
Call sequence:
- Parent sets
currentData → when condition becomes truthy → new <my-child> element created
- Parent
:data binding sets .data on the new element (before it's connected to the DOM?)
data change fires an observable notification → child template bindings evaluate
- The binding
x => x.data?.label runs with x as undefined → crash
💁 Possible Solution
Framework-level fix: FAST's binding/observable system should defer template binding evaluation on a custom element until its Controller is connected.
🐛 Bug Report
Template bindings may evaluate on a child element with no controller, crashing when a parent
whendirective tears down and recreates the child.💻 Repro or Code Sample
https://stackblitz.com/edit/typescript-fuiufsk7?file=index.ts
Conditions required to reproduce:
whendirective to conditionally render a child custom element, with a property binding that pushes data onto the child:${when(x => x.currentData, html`<my-child :data=${x => x.currentData}></my-child>`)}whencondition toggles — tearing down the child and then recreating it — while the property binding immediately pushes data onto the newly created child${x => x.data?.label})When the
whendirective creates a new<my-child>element, the parent's:databinding sets.dataon it at some point where the controller is undefined.Steps to reproduce:
<my-child>, setscurrentData = undefined)<my-child>, setscurrentData = { label: "A" })currentDatato{ label: "B" })x.data?.labelevaluates withxasundefined🤔 Expected Behavior
When the parent's
whendirective rebuilds the child element and the property binding pushes data, template bindings on the child should not evaluate until the Controller is available.😯 Current Behavior
The parent's
whendirective creates a new child element and the:databinding immediately sets.dataon it. The observable change notification causes the child's template bindings to evaluate before the controller is available. At that point the Controller is not connected, and the binding's source (x) isundefined, causing a crash.Call sequence:
currentData→whencondition becomes truthy → new<my-child>element created:databinding sets.dataon the new element (before it's connected to the DOM?)datachange fires an observable notification → child template bindings evaluatex => x.data?.labelruns withxasundefined→ crash💁 Possible Solution
Framework-level fix: FAST's binding/observable system should defer template binding evaluation on a custom element until its Controller is connected.