Repository navigation
fix(defer): lazy-load an imports entry written as forwardRef(() => X) - #640
Conversation
Resolve `@angular/core`'s `forwardRef` in `imports` before the implicit `@defer` deferral, like ngtsc's `forwardRefResolver`, so a component used only inside `@defer` is loaded with a dynamic `import()`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
# Conflicts: # crates/oxc_angular_compiler/src/component/decorator.rs # crates/oxc_angular_compiler/src/directive/mod.rs
The converter turns a `function` expression into raw source, so
`forwardRef(function () { return X; })` never matched and stayed eager,
while ngtsc lazy-loads it. Record the class of each `imports` element
from the decorator AST, where `try_unwrap_forward_ref` reads every form,
and match the converted entries by position. Other entries keep the old
rule: a plain name in the output stays eager (`X as any`, like ngtsc)
without blocking the rest.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
|
Codex Review: Something went wrong. Try again later by commenting “@codex review”. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Fixes #632.
Problem
A standalone component listed as
imports: [forwardRef(() => CmpA)]and used only inside@deferstayed eager: the implicit-deferral gate from #313 required everyimportsentry to be a bare identifier, and the identifier list it matched against skippedforwardRef(...)entries. The staticimport { CmpA }stayed andɵɵdefer(1, 0)got no dependency function. ngtsc resolves the entry throughforwardRefResolver(tryUnwrapForwardRefinpackages/compiler-cli/src/ngtsc/annotations/common/src/util.ts) beforeresolveAllDeferredDependenciesmatches selectors.Fix
decorator.rs: record the classes written asforwardRef(() => X)in theimportsarray (ComponentMetadata::forward_ref_imports), using the existingtry_unwrap_forward_ref, so only@angular/core'sforwardRefcounts.importsitself is unchanged (partial/Direct emit still reads it).transform.rs:import_entry_classmaps each rawimportsentry to its class (Xor a resolvedforwardRef(() => X), arrow orreturnbody). The gate, the candidate list and the removal from the eagerɵɵgetComponentDepsFactoryarray all use it.Output now matches ngc:
ɵɵdefer(1, 0, () => [import("./lazy").then(m => m.LazyCmp)]),ɵɵgetComponentDepsFactory(Parent, []), and no static import.Selectorless deps (
selectorless_spec.ts: "should defer selectorless symbols") are out of scope: OXC rejects selectorless components outright (pipeline/ingest.rs), so there is nothing to defer yet.Checks
tests/defer_implicit_imports_test.rs:forward_ref_import_used_only_inside_defer_is_lazy_loaded(port ofdefer_spec.ts"should lazy-load dependency referenced with a fowrardRef", arrow and block-body forms) andforward_ref_not_from_angular_core_stays_eager.cargo test -p oxc_angular_compiler --all-features: 3518 passed, 0 failed.cargo fmt;cargo clippy -p oxc_angular_compiler --all-featuresadds no warnings on the changed lines.🤖 Generated with Claude Code