Repository navigation
fix(linker): use the file's @angular/core namespace in generated templates - #526
Merged
Brooooooklyn merged 1 commit intoOct 3, 2026
Conversation
…lates Minifiers rename the `import * as i0 from "@angular/core"` namespace (e.g. to `e`). The linker already used that name in its own output, but the template and host-binding pipeline hardcodes `i0`, so linked components and directives referenced an unbound `i0` and threw `ReferenceError: i0 is not defined`. The emitter can now print the file's namespace in place of `i0`, and the linker sets it for template and host-binding output, matching Angular's Babel linker.
Brooooooklyn
approved these changes
Oct 3, 2026
Brooooooklyn
left a comment
Member
There was a problem hiding this comment.
Deep review on the PR branch, verified locally:
- Every
i0in generated code flows throughReadVarExpr— theReadVaremit site is the single, correct seam for the namespace rename. Consts, initializers, ngContentSelectors, declarations, and the main template fn all emit through the namespaced emitter. - User identifiers can't collide: tested
@for (i0 of items),@let i0,{{ i0 }}, andlet-i0template vars end to end — the pipeline renames user vars toi0_r1-style or reads them viactx, soReadVar("i0")only ever means the core namespace. WrappedNode/External/DynamicImporteither error out or aren't on the linker path, so noi0bypasses the rename.- Reverting just the emitter change makes
test_link_component_uses_minified_namespacefail (strayi0refs); restoring passes. All 81 linker tests green. - Mergeable against current main with PR 527's linker changes in flight — no conflicts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Minifiers such as esbuild rename a library's
@angular/corenamespace import, e.g.import * as e from "@angular/core". The linker links theɵɵngDeclare*calls, but the template and host-binding functions it generates still referencei0(i0.ɵɵelementStart(...),i0.ɵɵclassProp(...)).i0isn't defined in that file, so those functions throwReferenceError: i0 is not defined. Components and directives (host bindings) are both affected.The linker's own output already used the file's namespace. The template pipeline hardcodes
i0in about 20 places, and that namespace was never passed to it.Fix
JsEmitter::with_core_namespace(ns)printsnsin place of anyi0variable read.JsEmitter::new()is unchanged, so no other output changes.compile_template_for_linkerandcompile_host_bindings_for_linkertake the namespace. The linker passes it for both components and directives.This matches Angular's Babel linker, which emits the file's namespace.
Verification
New unit test
test_link_component_uses_minified_namespacecovers a directive with host bindings, and a component with a listener, a pipe,@if, i18n and@defer. It fails before the fix and passes after.End to end: a library compiled with
ngcin partial mode, minified with esbuild (--minify --charset=utf8), linked, imported in Node, then its generated functions called.i0refsReferenceError: i0 is not definedAfter the fix, oxc and Angular both reference
e.ɵɵ…16 times.Local CI steps:
cargo test,cargo fmt --check, conformance (1252/1252, snapshot unchanged): pass.pnpm test(106),pnpm check: pass.Follow-up (not in this PR)
esbuild's default
--minify(--charset=ascii) writesɵasɵ. The linker doesn't link such a file at all, so the library falls back to JIT. That will be fixed separately.