🐛 Bug Report
The createView method in the template compiler triggers lazy target node locators via bare property access (targets[id]), which JavaScript minifiers like Terser remove as dead code when pure_getters is enabled.
💻 Repro or Code Sample
- Build
@microsoft/fast-element with a bundler that uses Terser with pure_getters: true (or "strict").
- Inspect the minified output of
CompilationContext.createView.
- The
for (const id of this.nodeIds) { targets[id]; } loop body is removed entirely.
// Source (compiler.ts – createView)
for (const id of this.nodeIds) {
targets[id]; // trigger locator — DROPPED by Terser
}
The getter on each target ID lazily resolves and caches a DOM node reference via childNodes[targetIndex]. When the access is removed, target nodes are never resolved and view behavior factories receive undefined targets at runtime.
🤔 Expected Behavior
The bare property access should execute at runtime so that all target descriptors are eagerly resolved and cached before the view is returned. Templates should render correctly regardless of minifier settings.
😯 Current Behavior
When the consuming application's bundler enables Terser's pure_getters optimization (common in production builds), the getter-triggering loop is eliminated as a side-effect-free statement. This causes view factories to receive undefined target nodes, leading to runtime errors or silently broken template bindings.
Using void targets[id] does not help — Terser also drops void expressions when the inner expression is classified as pure.
💁 Possible Solution
Replace the bare property access with Reflect.get(targets, id). Terser treats function calls as side-effectful by default (unless annotated with /*#__PURE__*/), so Reflect.get survives minification while producing the identical getter invocation:
for (const id of this.nodeIds) {
Reflect.get(targets, id); // trigger locator
}
A fix for this has already been implemented and tests pass.
🔦 Context
Any consumer bundling @microsoft/fast-element with Terser (directly or via Webpack/Vite/Rollup with the terser plugin) and enabling pure_getters will hit this issue in production builds. Development builds are unaffected because minification is typically disabled. This makes the bug particularly insidious — templates work in dev but silently break in production.
🌍 Your Environment
- OS & Device: All platforms
- Browser: All browsers
- Version:
@microsoft/fast-element v2.x (current main branch)
🐛 Bug Report
The
createViewmethod in the template compiler triggers lazy target node locators via bare property access (targets[id]), which JavaScript minifiers like Terser remove as dead code whenpure_gettersis enabled.💻 Repro or Code Sample
@microsoft/fast-elementwith a bundler that uses Terser withpure_getters: true(or"strict").CompilationContext.createView.for (const id of this.nodeIds) { targets[id]; }loop body is removed entirely.The getter on each target ID lazily resolves and caches a DOM node reference via
childNodes[targetIndex]. When the access is removed, target nodes are never resolved and view behavior factories receiveundefinedtargets at runtime.🤔 Expected Behavior
The bare property access should execute at runtime so that all target descriptors are eagerly resolved and cached before the view is returned. Templates should render correctly regardless of minifier settings.
😯 Current Behavior
When the consuming application's bundler enables Terser's
pure_gettersoptimization (common in production builds), the getter-triggering loop is eliminated as a side-effect-free statement. This causes view factories to receiveundefinedtarget nodes, leading to runtime errors or silently broken template bindings.Using
void targets[id]does not help — Terser also dropsvoidexpressions when the inner expression is classified as pure.💁 Possible Solution
Replace the bare property access with
Reflect.get(targets, id). Terser treats function calls as side-effectful by default (unless annotated with/*#__PURE__*/), soReflect.getsurvives minification while producing the identical getter invocation:A fix for this has already been implemented and tests pass.
🔦 Context
Any consumer bundling
@microsoft/fast-elementwith Terser (directly or via Webpack/Vite/Rollup with the terser plugin) and enablingpure_getterswill hit this issue in production builds. Development builds are unaffected because minification is typically disabled. This makes the bug particularly insidious — templates work in dev but silently break in production.🌍 Your Environment
@microsoft/fast-elementv2.x (currentmainbranch)