fix(vite-plugin-angular): emit fastCompile JIT metadata in nested class scope#2361
Conversation
Components defined directly inside a test spec file - e.g. a host component declared within a describe()/it() callback to test a directive - threw 'ReferenceError: <Class> is not defined' under fastCompile. In test mode fastCompile uses the JIT path. jitTransform recursively finds nested classes but collected every class's generated metadata statements (<Class>.decorators = ..., _jitCompileComponent(...), etc.) and appended them all at the end of the file (module scope). A class declared inside a function/callback scope is not in scope there, so the appended statement referenced an undefined name. Emit each class's metadata statements directly after its class body via ms.appendLeft(node.end, ...) so they run in the class's own lexical scope - module scope for top-level classes (unchanged behavior), the enclosing callback scope for nested ones. Adds an evaluating regression test (the prior nested-class tests only asserted the output string, never executing it). Closes #2360 https://claude.ai/code/session_01DEPPXW9VMWVXNYmYDM2Y6A
✅ Deploy Preview for analog-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
PR Checklist
Components defined directly inside a test spec file — e.g. a host component declared within a
describe()/it()/beforeEach()callback to test a directive — threwReferenceError: <Class> is not definedunderfastCompile.Closes #2360
Affected scope
vite-plugin-angularRecommended merge strategy for maintainer [optional]
What is the new behavior?
In test mode
fastCompileuses the JIT path (angular-vite-plugin.tssetsjittoisTestwhen not explicitly provided), sojitTransform()runs rather than the AOT registry path.jitTransformcallsfindAllClasses(), which walks the AST recursively and therefore finds classes nested inside function/callback scopes — including a host@Componentdeclared inside adescribe(...)/it(...)block, the common "host component to test a directive" pattern. For every such class it collected the generated metadata statements (<Class>.decorators = [...],_jitCompileComponent(<Class>, ...),<Class>.ctorParameters = ...,<Class>.propDecorators = ...) into a single array and appended them all at the end of the file (module scope). A class declared inside a callback is not in scope there, so the appended statement referenced an undefined name and threwReferenceError: <Class> is not definedwhen the spec module was evaluated.This was missed because the existing nested-class tests only asserted the emitted string contained
<Class>.decorators— they never evaluated the code.The fix emits each class's metadata statements directly after its class body via
ms.appendLeft(node.end, ...), so they run in the class's own lexical scope:node.endis the position just past the class's closing brace (decorators were already stripped beforenode.start), so the statements land as the next statement(s) in the same block. A separate accumulator string preserves the existing post-loop detection of missing field-decorator imports. Angular'sɵcompileComponentinstalls a lazyɵcmp, so emitting a top-level component's_jitCompileComponent(...)right after its own declaration (instead of after every class) is safe.Before / after for a component declared inside a function:
Test plan
nx format:check(touched files)nx build vite-plugin-angularnx test vite-plugin-angular— 620 passed, 3 skippedAdds an evaluating regression test (
jit-transform.spec.ts) that runs the emitted JS throughnew Functionwith stubbed@angular/coreexports — it would throwReferenceErrorunder the old file-end emit and passes with the fix.Does this PR introduce a breaking change?
fastCompileis opt-in, and top-level class emit is unchanged — only the out-of-scope placement for nested classes is corrected.Other information
Scoped to the JIT path, which is the path test mode uses, directly resolving the reported error. The AOT registry's
.spec.tshandling infast-compile-plugin.tsis not on the test path and is out of scope for this issue.https://claude.ai/code/session_01DEPPXW9VMWVXNYmYDM2Y6A
Generated by Claude Code