| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
…erredImports Wire `@Component.deferredImports` through to a per-component deferrable-deps resolver (`() => [import(...).then(m => m.X)]`) threaded into every `ɵɵdefer(...)` call, and emit `ɵsetClassMetadataAsync` so TestBed metadata is built lazily inside the same dynamic-import callback. Matches Angular's local-compilation behavior: - The resolver uses the *original* exported name (`getExportedName` semantics) so aliased and default imports resolve to `m.HeavyWidget` / `m.default` rather than the local binding. - `setClassMetadataAsync` and the resolver are only emitted when the template actually contains an `@defer` block — declaring `deferredImports` without a block leaves the eager `setClassMetadata` path untouched and emits no dead `import(...)` calls. - Reject overlap between `imports` and `deferredImports` with a diagnostic, mirroring `validateNoImportOverlap`. - Symbols listed only in `imports` are NOT auto-detected as deferrable; cross-file selector resolution isn't available in local mode, so users must opt in via `deferredImports`. Closes #289. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`build_defer_per_component_deps` previously set `symbol_name = "default"`
for default imports, which becomes the `setClassMetadataAsync` callback
parameter name (via `compile_component_class_metadata`) and emits
`(default) => { … }` — a JavaScript `SyntaxError` because `default` is a
reserved word.
Mirror Angular's `getExportedName`: for default imports the function
returns `originalId.text` (the local binding), not the literal `"default"`.
Use the local binding as `symbol_name`; `m.default` in the resolver is
already covered by the `is_default_import` branch in
`compile_component_metadata_async_resolver`.
Add an assertion to the existing default-import test that the callback
parameter is the local binding (`(LazyCmp) =>`) and not the reserved word.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ed imports
Angular collapses both the `setClassMetadataAsync` callback parameter name
and the dynamic-import `m.X` property name into a single `symbolName` field
set to the exported name. For aliased imports (`import { Foo as Bar }`) that
leaves the static import pinned: the callback parameter is `Foo` but the
metadata body still references `Bar`, which resolves to the outer scope.
Split `R3DeferPerComponentDependency` into two distinct fields:
- `param_name` — the local binding from the source file. Used as the
callback parameter on `setClassMetadataAsync` so the body's identifier
references shadow the static import.
- `export_name` — the exported name in the source module. Used as the
resolver's `m.<export_name>` property read.
This produces `(Heavy) => { setClassMetadata(...deferredImports: [Heavy]...) }`
instead of `(HeavyWidget) => { ...[Heavy]... }` — the only `Heavy` reference
in the file is now inside the shadowing callback, letting bundlers drop the
eager `import { HeavyWidget as Heavy } from './widget'`. Plain and default
imports are unaffected (local == exported).
Adds an assertion to `test_defer_dependency_resolver_uses_original_export_name_for_aliases`
that the callback parameter is `(Heavy)` and not `(HeavyWidget)`.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…d metadata async
`build_defer_resolver_expression` (used for `ɵɵdefer`'s resolver argument)
and `compile_component_metadata_async_resolver` (used for
`ɵsetClassMetadataAsync`) emitted byte-equivalent `() => [import('./x').then((m) => m.X)]`
shapes via two independent builders. Consolidate by:
- Moving `build_defer_per_component_deps` from `component/transform.rs` into
`component/defer_resolver.rs` (the natural home — it's a resolver concern,
and transform.rs already depends on defer_resolver, not vice versa).
- Reducing `build_defer_resolver_expression` to a thin wrapper that builds
the deps slice and delegates to `compile_component_metadata_async_resolver`.
- Dropping the now-unused `build_import_then_expression` helper.
No emit changes — both call sites already produced identical output for
every input shape (default, aliased, plain named, namespace, type-only).
Net `-104` lines across the two files.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 65e6c38. Configure here.
Sorry, something went wrong.
…_name_to_str The `module_export_name_to_str` helper was inserted between `build_import_map`'s doc comment block and its definition with no blank line separating them. Rust attaches a contiguous `///` block to the next item, so the whole comment (~25 lines describing the import map) was binding to the small helper, leaving `build_import_map` undocumented in rustdoc. Move the helper after `build_import_map` so each function keeps its own doc comment. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
| Back | FazBrowse Home | New Git URL |
Summary
Closes #289.
Test plan
🤖 Generated with Claude Code
Note
Medium Risk
Touches component transform, template ingest, and dev metadata emission paths; behavior is gated on @defer presence but incorrect resolver wiring could break lazy loading or bundler tree-shaking.
Overview
Adds local-compilation @defer support driven by @Component.deferredImports: the compiler parses that decorator field, builds a shared per-component resolver (() => [import(...).then(m => m.X)]), passes it into template ingest as ɵɵdefer’s third argument, and switches defer-deps emit mode to PerComponent when a resolver exists.
Import map now records imported_name (export vs local binding) so dynamic imports use the real export (m.HeavyWidget, m.default) while setClassMetadataAsync callback params use the local name (Heavy)—splitting param_name / export_name on R3DeferPerComponentDependency so aliased defer imports can tree-shake better than Angular’s single symbolName.
Gating & validation: resolver and async metadata run only if the template actually contains @defer; overlap between imports and deferredImports is a compile error; symbols listed only in imports are not auto-deferred. Integration tests cover resolver wiring, aliases, defaults, and diagnostics (#289).
Reviewed by Cursor Bugbot for commit 3fd17d9. Bugbot is set up for automated code reviews on this repo. Configure here.