🐛 Bug Report
Schema.addPath in fast-html replaces the entire $defs object instead of merging when a new dotted-property binding
(e.g. {{strings.selectAll}}) is encountered inside a repeat context. This destroys previously created repeat contexts and
causes a TypeError crash during template compilation/hydration.
💻 Repro or Code Sample
Minimal template that crashes:
<f-repeat value="{{item in displayedItems}}">
<span>{{strings.selectAll}}</span>
<f-repeat value="{{child in item.children}}">
<span>{{child.label}}</span>
</f-repeat>
</f-repeat>
Steps to reproduce:
1. Clone the repro and run npm install
2. Run npm test (Node.js direct test) — prints the crash trace
3. Or run npm start and open http://localhost:8787 — crash in browser console
Node.js test (test-crash.mjs) directly exercises Schema.addPath and Schema.addContext to trigger the crash without a browser.
🤔 Expected Behavior
Template compilation and hydration should complete without errors. Adding a new entry to $defs via addPath should preserve all
previously created repeat contexts.
😯 Current Behavior
TypeError: Cannot read properties of undefined (reading '$fast_parent_contexts')
at _Schema.getParentContexts (schema.ts:~160)
at _Schema.addContext (schema.ts:~140)
at _Schema.addPath (schema.ts:~120)
at bindingResolver
at _TemplateElement.resolveTemplateDirective
at _TemplateElement.resolveInnerHTML
In minified builds: TypeError: Cannot read properties of undefined (reading 'at').
The custom element never completes hydration. The page renders the pre-rendered HTML shell but is completely non-interactive
(no event handlers bound).
💁 Possible Solution
The bug is in packages/fast-html/src/components/schema.ts lines 143–147, in the "access" case of Schema.addPath:
// CURRENT (buggy) — replaces entire $defs
if (!schema[defsPropertyName]?.[splitPath[0]]) {
schema[defsPropertyName] = {
[splitPath[0]]: {} as any,
};
}
Fix — spread to preserve existing entries:
if (!schema[defsPropertyName]?.[splitPath[0]]) {
schema[defsPropertyName] = {
...schema[defsPropertyName],
[splitPath[0]]: {} as any,
};
}
Crash sequence:
1. Outer <f-repeat> → addContext creates $defs["item"] with $fast_parent_contexts
2. {{strings.selectAll}} → addPath(type="access") → $defs["strings"] doesn't exist → $defs replaced with { "strings": {} } →
$defs["item"] destroyed
3. Inner <f-repeat> → addContext("child", parentContext="item") → getParentContexts("item") → $defs["item"] is undefined → 💥
I'm happy to contribute the fix as a PR.
🔦 Context
This bug blocks the Microsoft Edge edge://history BTR (Build Time Rendering) conversion. The history page template uses
{{strings.selectEntry}} (localized string) inside a <for each="group in displayedGroups"> loop, which crashes when followed by
a nested <for each="entry in group.entries">.
Current workaround: flatten nested data into a single array with row-type discriminators, avoiding nested repeat loops
entirely. This significantly increases component complexity and loses semantic grouping.
🌍 Your Environment
- OS & Device: Windows 11 on PC
- Browser: Microsoft Edge
147.0.0.0 (developer build)
- @microsoft/fast-html:
1.0.0-alpha.36 (also verified on alpha.44 — not fixed)
- @microsoft/fast-element:
2.10.0
🐛 Bug Report
Schema.addPathinfast-htmlreplaces the entire$defsobject instead of merging when a new dotted-property binding(e.g.
{{strings.selectAll}}) is encountered inside a repeat context. This destroys previously created repeat contexts andcauses a
TypeErrorcrash during template compilation/hydration.💻 Repro or Code Sample
Minimal template that crashes: