@analogjs/angular-compiler 2.5.0-beta.1 → 2.5.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/COMPILER.md CHANGED
@@ -12,9 +12,9 @@ Peer dependencies: `@angular/compiler` >=19, `@angular/compiler-cli` >=19, `@ang
12
12
 
13
13
  ## Entry Point
14
14
 
15
- | Import | Exports | Use case |
16
- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
17
- | `@analogjs/angular-compiler` | `compile()`, `scanFile()`, `scanDtsFile()`, `scanPackageDts()`, `collectImportedPackages()`, `jitTransform()`, `inlineResourceUrls()`, `extractInlineStyles()` | Programmatic compiler API |
15
+ | Import | Exports | Use case |
16
+ | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
17
+ | `@analogjs/angular-compiler` | `compile()`, `scanFile()`, `scanDtsFile()`, `scanPackageDts()`, `collectImportedPackages()`, `jitTransform()`, `inlineResourceUrls()`, `extractInlineStyles()`, `generateHmrCode()` | Programmatic compiler API |
18
18
 
19
19
  The compiler is integrated into `@analogjs/vite-plugin-angular` via the `experimental.useAnalogCompiler` flag — there is no separate Vite plugin entry point.
20
20
 
@@ -121,28 +121,28 @@ The compiler is integrated into `@analogjs/vite-plugin-angular` as an alternativ
121
121
  2. Inlines external resources (`templateUrl`, `styleUrl`) via OXC AST rewriting before compilation
122
122
  3. Compiles each file on-demand with `compile()` during Vite's transform phase (runs with `enforce: 'pre'`)
123
123
  4. Strips TypeScript syntax from the output via `vite.transformWithOxc()` (handles `import type`, generics, interfaces, `implements`, etc.)
124
- 5. Appends HMR code for leaf components in dev mode
124
+ 5. Appends HMR code for Angular declarations in dev mode (components via `ɵɵreplaceMetadata`, directives/pipes via field-swap + invalidate)
125
125
  6. Injects synthetic imports for NgModule-exported classes
126
126
 
127
127
  The existing vite-plugin-angular plugins (build optimizer, router, vitest, etc.) continue to work alongside the analog compiler.
128
128
 
129
129
  ## Source Files
130
130
 
131
- | File | Purpose |
132
- | --------------------- | ---------------------------------------------------------------------------------------------- |
133
- | `compile.ts` | Single-file AOT compiler: Ivy codegen via `@angular/compiler` APIs |
134
- | `registry.ts` | OXC-based file scanner, extracts selectors, inputs, outputs |
135
- | `metadata.ts` | Decorator metadata extraction (`extractMetadata`, `detectSignals`, `detectFieldDecorators`) |
136
- | `js-emitter.ts` | Angular output AST → JavaScript string emitter (~4x faster than `ts.Printer`) |
137
- | `ast-translator.ts` | Angular output AST → TypeScript AST translator (for complex expressions) |
138
- | `resource-inliner.ts` | OXC-based `templateUrl`/`styleUrl` inlining and inline style extraction |
139
- | `dts-reader.ts` | OXC-based `.d.ts` scanner for pre-compiled Angular packages (selectors, inputs, outputs) |
140
- | `jit-transform.ts` | JIT mode: decorator metadata arrays + constructor DI + signal downleveling + decorator removal |
141
- | `jit-metadata.ts` | JIT metadata helpers (constructor parameters, property decorators) |
142
- | `defer.ts` | `@defer` dependency map builder |
143
- | `hmr.ts` | HMR code generation using `ɵɵreplaceMetadata` |
144
- | `styles.ts` | Style preprocessing via Vite's `preprocessCSS` (OXC-based extraction) |
145
- | `utils.ts` | Type-only import detection, class finder, `forwardRef` unwrapper |
131
+ | File | Purpose |
132
+ | --------------------- | ----------------------------------------------------------------------------------------------------- |
133
+ | `compile.ts` | Single-file AOT compiler: Ivy codegen via `@angular/compiler` APIs |
134
+ | `registry.ts` | OXC-based file scanner, extracts selectors, inputs, outputs |
135
+ | `metadata.ts` | Decorator metadata extraction (`extractMetadata`, `detectSignals`, `detectFieldDecorators`) |
136
+ | `js-emitter.ts` | Angular output AST → JavaScript string emitter (~4x faster than `ts.Printer`) |
137
+ | `ast-translator.ts` | Angular output AST → TypeScript AST translator (for complex expressions) |
138
+ | `resource-inliner.ts` | OXC-based `templateUrl`/`styleUrl` inlining and inline style extraction |
139
+ | `dts-reader.ts` | OXC-based `.d.ts` scanner for pre-compiled Angular packages (selectors, inputs, outputs) |
140
+ | `jit-transform.ts` | JIT mode: decorator metadata arrays + constructor DI + signal downleveling + decorator removal |
141
+ | `jit-metadata.ts` | JIT metadata helpers (constructor parameters, property decorators) |
142
+ | `defer.ts` | `@defer` dependency map builder |
143
+ | `hmr.ts` | HMR code generation: `ɵɵreplaceMetadata` for components, field-swap + invalidate for directives/pipes |
144
+ | `styles.ts` | Style preprocessing via Vite's `preprocessCSS` (OXC-based extraction) |
145
+ | `utils.ts` | Type-only import detection, class finder, `forwardRef` unwrapper |
146
146
 
147
147
  ## What's Supported
148
148
 
@@ -267,13 +267,21 @@ The existing vite-plugin-angular plugins (build optimizer, router, vitest, etc.)
267
267
 
268
268
  ## HMR (Hot Module Replacement)
269
269
 
270
- Leaf components support true HMR via Angular's `ɵɵreplaceMetadata`. When a component file changes in dev mode:
270
+ HMR code is generated by `generateHmrCode()` (exported from `@analogjs/angular-compiler`) and handles all Angular declaration types:
271
+
272
+ **Components** — true HMR via Angular's `ɵɵreplaceMetadata`:
271
273
 
272
274
  1. Vite hot-replaces the module
273
- 2. The `import.meta.hot.accept` callback calls `ɵɵreplaceMetadata` with the new component definition
274
- 3. Angular merges old/new definitions and recreates matching LViews without page reload
275
+ 2. The `ɵhmr_` callback dynamically copies all `ɵ`-prefixed static fields from the new class to the old
276
+ 3. `ɵɵreplaceMetadata` merges old/new definitions and recreates matching LViews without page reload
277
+ 4. File-local Angular class names are passed as local dependencies
278
+
279
+ **Directives and pipes** — field-swap + invalidation:
280
+
281
+ 1. The `ɵhmr_` callback copies all `ɵ`-prefixed fields (same dynamic approach)
282
+ 2. Since `ɵɵreplaceMetadata` only supports components, the module is invalidated to trigger a full reload
275
283
 
276
- Root components (e.g. `App`) fall back to page reload since they can't be hot-replaced without re-bootstrapping the application. Non-Angular files use Vite's default HMR.
284
+ **Root components** (e.g. `App`) fall back to page reload since they can't be hot-replaced without re-bootstrapping. Non-Angular files use Vite's default HMR.
277
285
 
278
286
  External template and style changes invalidate the parent `.ts` module, triggering re-compilation and HMR. Preprocessed styles are cached by mtime for fast re-compilation.
279
287
 
@@ -297,26 +305,26 @@ The `inlineStyleLanguage` option (default: `'scss'`) controls the file extension
297
305
 
298
306
  Both produce identical Ivy output because both call the same `@angular/compiler` APIs (`compileComponentFromMetadata`, `parseTemplate`, `compileFactoryFunction`, etc.). The template instructions are byte-for-byte equivalent.
299
307
 
300
- | | ngtsc | This compiler |
301
- | ------------------------------- | ---------------------------------------- | ------------------------------------------------------------ |
302
- | Size | ~200,000+ lines | ~2,000 lines |
303
- | Requires `ts.Program` | Yes (reads all files, resolves modules) | No |
304
- | Type checking | Full TS + template type checking | None (use Angular Language Service) |
305
- | Template compilation | Full Ivy instructions | Full Ivy instructions (same APIs) |
306
- | Output format | `ɵɵdefineComponent` (final) | `ɵɵdefineComponent` (final) |
307
- | Global analysis | Via type checker (full scope resolution) | Via tsconfig + OXC registry scan |
308
- | Constructor DI | Full (via type checker) | Full (via AST parameter analysis) |
309
- | `setClassMetadata` | Yes | Yes |
310
- | Source maps | Yes (via TS emitter) | Yes (via MagicString surgical edits + inline string emitter) |
311
- | HMR | Full (with tracking metadata) | Leaf components (root falls back to reload) |
312
- | `@defer` lazy loading | Yes | Yes |
313
- | SCSS preprocessing | Via `@angular/build` | Via Vite `preprocessCSS` + LmdbCacheStore |
314
- | i18n | Full ICU extraction + localization | Not supported |
315
- | Template type checking | Full (`strictTemplates`) | Not supported |
316
- | Incremental compilation | `ts.Program` reuse | Per-file (Vite handles caching) |
317
- | Diagnostic messages | Hundreds of template/binding errors | Unresolved selector warnings only |
318
- | Partial compilation (libraries) | `ɵɵngDeclareComponent` | Not in scope |
319
- | Declaration files (`.d.ts`) | Yes | Not in scope |
308
+ | | ngtsc | This compiler |
309
+ | ------------------------------- | ---------------------------------------- | --------------------------------------------------------------- |
310
+ | Size | ~200,000+ lines | ~2,000 lines |
311
+ | Requires `ts.Program` | Yes (reads all files, resolves modules) | No |
312
+ | Type checking | Full TS + template type checking | None (use Angular Language Service) |
313
+ | Template compilation | Full Ivy instructions | Full Ivy instructions (same APIs) |
314
+ | Output format | `ɵɵdefineComponent` (final) | `ɵɵdefineComponent` (final) |
315
+ | Global analysis | Via type checker (full scope resolution) | Via tsconfig + OXC registry scan |
316
+ | Constructor DI | Full (via type checker) | Full (via AST parameter analysis) |
317
+ | `setClassMetadata` | Yes | Yes |
318
+ | Source maps | Yes (via TS emitter) | Yes (via MagicString surgical edits + inline string emitter) |
319
+ | HMR | Full (with tracking metadata) | Components (full), directives/pipes (invalidate), root (reload) |
320
+ | `@defer` lazy loading | Yes | Yes |
321
+ | SCSS preprocessing | Via `@angular/build` | Via Vite `preprocessCSS` + LmdbCacheStore |
322
+ | i18n | Full ICU extraction + localization | Not supported |
323
+ | Template type checking | Full (`strictTemplates`) | Not supported |
324
+ | Incremental compilation | `ts.Program` reuse | Per-file (Vite handles caching) |
325
+ | Diagnostic messages | Hundreds of template/binding errors | Unresolved selector warnings only |
326
+ | Partial compilation (libraries) | `ɵɵngDeclareComponent` | Not in scope |
327
+ | Declaration files (`.d.ts`) | Yes | Not in scope |
320
328
 
321
329
  #### Performance
322
330
 
@@ -413,24 +421,24 @@ This compiler's architecture — single-file transforms using `@angular/compiler
413
421
 
414
422
  ## Test Suite
415
423
 
416
- | File | Tests | Coverage |
417
- | ------------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
418
- | `jit-transform.spec.ts` | 32 | Decorator conversion, member decorator removal (@Input, @Output, @ViewChild, @ContentChild), constructor parameter decorator removal (@Inject, @Optional), constructor DI, signal API downleveling, external resources, edge cases, ReflectionCapabilities integration |
419
- | `integration.spec.ts` | 50 | Registry input/output extraction, cross-component binding, constant pool ordering, assignment precedence, templateUrl inlining, content projection, pipe chaining, template refs, two-way binding, computed signals, safe navigation, @defer triggers, @if alias, multi-component files, duplicate i0 prevention, OXC resource inlining, arrow object literal wrapping, .d.ts extraction, signal field preservation, decorator stripping, collectImportedPackages, non-Angular passthrough, template `<style>` merging, NgModule export expansion, member decorator removal, self-referencing components, .d.ts NgModule scanning, TS syntax preservation, lazy dependency arrays, directive compilation, recursive NgModule expansion, circular NgModule handling |
420
- | `dts-reader.spec.ts` | 7 | Directive/component/pipe extraction from `.d.ts`, signal inputs, aliased inputs, multiple classes |
421
- | `component.spec.ts` | 48 | All @Component features, signals (including required variants), control flow, defer, pipes, content projection, external resources, resource dependencies, providers, source maps |
422
- | `ast-translator.spec.ts` | 43 | Every AST visitor method (expressions + statements), ngDevMode global |
423
- | `decorator-fields.spec.ts` | 15 | @Input, @Output, @ViewChild, @ContentChild, @HostBinding, @HostListener field decorators |
424
- | `constructor-di.spec.ts` | 8 | Constructor DI: @Inject, @Optional, inheritance, union types, multiple params |
425
- | `error-handling.spec.ts` | 7 | Unknown decorators, undecorated classes, selectorless components, forwardRef, invalid templates |
426
- | `registry.spec.ts` | 6 | All decorator types, multi-declaration, NgModule exports |
427
- | `cross-file-resolution.spec.ts` | 5 | Cross-file component, pipe, directive resolution |
428
- | `ngmodule.spec.ts` | 3 | Compilation, providers, export resolution |
429
- | `injectable.spec.ts` | 3 | `providedIn` variants |
430
- | `directive.spec.ts` | 2 | Host bindings, exportAs |
431
- | `pipe.spec.ts` | 2 | Pure and impure |
432
- | `compile.spec.ts` | 2 | Original smoke tests |
433
- | `conformance.spec.ts` | 161 | Angular compliance test suite (v17-v21, 87%+ Ivy instruction match) |
424
+ | File | Tests | Coverage |
425
+ | ------------------------------- | ----- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
426
+ | `jit-transform.spec.ts` | 32 | Decorator conversion, member decorator removal (@Input, @Output, @ViewChild, @ContentChild), constructor parameter decorator removal (@Inject, @Optional), constructor DI, signal API downleveling, external resources, edge cases, ReflectionCapabilities integration |
427
+ | `integration.spec.ts` | 57 | Registry input/output extraction, cross-component binding, constant pool ordering, assignment precedence, templateUrl inlining, content projection, pipe chaining, template refs, two-way binding, computed signals, safe navigation, @defer triggers, @if alias, multi-component files, duplicate i0 prevention, OXC resource inlining, arrow object literal wrapping, .d.ts extraction, signal field preservation, decorator stripping, collectImportedPackages, non-Angular passthrough, template `<style>` merging, NgModule export expansion, member decorator removal, self-referencing components, .d.ts NgModule scanning, TS syntax preservation, lazy dependency arrays, directive compilation, recursive NgModule expansion, circular NgModule handling, HMR code generation (dynamic field copying, component/directive/pipe handling, local deps) |
428
+ | `dts-reader.spec.ts` | 7 | Directive/component/pipe extraction from `.d.ts`, signal inputs, aliased inputs, multiple classes |
429
+ | `component.spec.ts` | 48 | All @Component features, signals (including required variants), control flow, defer, pipes, content projection, external resources, resource dependencies, providers, source maps |
430
+ | `ast-translator.spec.ts` | 43 | Every AST visitor method (expressions + statements), ngDevMode global |
431
+ | `decorator-fields.spec.ts` | 15 | @Input, @Output, @ViewChild, @ContentChild, @HostBinding, @HostListener field decorators |
432
+ | `constructor-di.spec.ts` | 8 | Constructor DI: @Inject, @Optional, inheritance, union types, multiple params |
433
+ | `error-handling.spec.ts` | 7 | Unknown decorators, undecorated classes, selectorless components, forwardRef, invalid templates |
434
+ | `registry.spec.ts` | 6 | All decorator types, multi-declaration, NgModule exports |
435
+ | `cross-file-resolution.spec.ts` | 5 | Cross-file component, pipe, directive resolution |
436
+ | `ngmodule.spec.ts` | 3 | Compilation, providers, export resolution |
437
+ | `injectable.spec.ts` | 3 | `providedIn` variants |
438
+ | `directive.spec.ts` | 2 | Host bindings, exportAs |
439
+ | `pipe.spec.ts` | 2 | Pure and impure |
440
+ | `compile.spec.ts` | 2 | Original smoke tests |
441
+ | `conformance.spec.ts` | 161 | Angular compliance test suite (v17-v21, 87%+ Ivy instruction match) |
434
442
 
435
443
  ### Conformance Testing
436
444
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@analogjs/angular-compiler",
3
- "version": "2.5.0-beta.1",
3
+ "version": "2.5.0-beta.2",
4
4
  "description": "Lightweight compiler for Angular",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/index.d.ts CHANGED
@@ -2,4 +2,5 @@ export { compile, type CompileResult, type CompileOptions, } from './lib/compile
2
2
  export { scanFile, type RegistryEntry, type ComponentRegistry, } from './lib/registry.js';
3
3
  export { scanDtsFile, scanPackageDts, collectImportedPackages, } from './lib/dts-reader.js';
4
4
  export { jitTransform, type JitTransformResult } from './lib/jit-transform.js';
5
+ export { generateHmrCode } from './lib/hmr.js';
5
6
  export { inlineResourceUrls, extractInlineStyles, } from './lib/resource-inliner.js';
package/src/index.js CHANGED
@@ -2,5 +2,6 @@ export { compile, } from './lib/compile.js';
2
2
  export { scanFile, } from './lib/registry.js';
3
3
  export { scanDtsFile, scanPackageDts, collectImportedPackages, } from './lib/dts-reader.js';
4
4
  export { jitTransform } from './lib/jit-transform.js';
5
+ export { generateHmrCode } from './lib/hmr.js';
5
6
  export { inlineResourceUrls, extractInlineStyles, } from './lib/resource-inliner.js';
6
7
  //# sourceMappingURL=index.js.map
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/angular-compiler/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,GAGR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,QAAQ,GAGT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EACX,cAAc,EACd,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAA2B,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/angular-compiler/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,GAGR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,QAAQ,GAGT,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,WAAW,EACX,cAAc,EACd,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAA2B,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,2BAA2B,CAAC"}
package/src/lib/hmr.d.ts CHANGED
@@ -1,12 +1,16 @@
1
1
  import type { RegistryEntry } from './registry.js';
2
2
  /**
3
- * Generate HMR code using Angular's ɵɵreplaceMetadata.
3
+ * Generate HMR code using Angular's ɵɵreplaceMetadata for components,
4
+ * and simple field-swap + invalidation for directives/pipes.
4
5
  *
5
- * The applyMetadata callback re-defines ɵcmp and ɵfac on the old class
6
- * by copying from the newly compiled class in the hot-updated module.
7
- * ɵɵreplaceMetadata then merges the old/new definitions and recreates
8
- * matching LViews in the component tree.
6
+ * The applyMetadata callback dynamically copies all ɵ-prefixed static
7
+ * fields (ɵcmp, ɵfac, ɵdir, ɵpipe, etc.) from the newly compiled class
8
+ * to the old class reference that Angular's runtime is tracking.
9
9
  *
10
- * Falls back to page reload if ɵɵreplaceMetadata throws.
10
+ * For components, ɵɵreplaceMetadata then merges the old/new definitions
11
+ * and recreates matching LViews in the component tree.
12
+ *
13
+ * For directives and pipes, ɵɵreplaceMetadata does not support them, so
14
+ * we fall back to a full page reload via import.meta.hot.invalidate().
11
15
  */
12
- export declare function generateHmrCode(components: RegistryEntry[]): string;
16
+ export declare function generateHmrCode(declarations: RegistryEntry[], localDepClassNames?: string[]): string;
package/src/lib/hmr.js CHANGED
@@ -1,22 +1,33 @@
1
1
  /**
2
- * Generate HMR code using Angular's ɵɵreplaceMetadata.
2
+ * Generate HMR code using Angular's ɵɵreplaceMetadata for components,
3
+ * and simple field-swap + invalidation for directives/pipes.
3
4
  *
4
- * The applyMetadata callback re-defines ɵcmp and ɵfac on the old class
5
- * by copying from the newly compiled class in the hot-updated module.
6
- * ɵɵreplaceMetadata then merges the old/new definitions and recreates
7
- * matching LViews in the component tree.
5
+ * The applyMetadata callback dynamically copies all ɵ-prefixed static
6
+ * fields (ɵcmp, ɵfac, ɵdir, ɵpipe, etc.) from the newly compiled class
7
+ * to the old class reference that Angular's runtime is tracking.
8
8
  *
9
- * Falls back to page reload if ɵɵreplaceMetadata throws.
9
+ * For components, ɵɵreplaceMetadata then merges the old/new definitions
10
+ * and recreates matching LViews in the component tree.
11
+ *
12
+ * For directives and pipes, ɵɵreplaceMetadata does not support them, so
13
+ * we fall back to a full page reload via import.meta.hot.invalidate().
10
14
  */
11
- export function generateHmrCode(components) {
12
- // Export applyMetadata functions so the accept callback can access them
13
- const applyFns = components
15
+ export function generateHmrCode(declarations, localDepClassNames = []) {
16
+ const components = declarations.filter((d) => d.kind === 'component');
17
+ const nonComponents = declarations.filter((d) => d.kind !== 'component');
18
+ // Export applyMetadata functions so the accept callback can access them.
19
+ // Dynamically copy all ɵ-prefixed static fields to handle ɵcmp, ɵfac,
20
+ // ɵdir, ɵpipe, ɵmod, ɵinj, ɵprov, and any future Ivy fields.
21
+ const applyFns = declarations
14
22
  .map((c) => `
15
- export function ɵhmr_${c.className}(type, namespaces) {
16
- type.ɵcmp = ${c.className}.ɵcmp;
17
- type.ɵfac = ${c.className}.ɵfac;
23
+ export function ɵhmr_${c.className}(type) {
24
+ for (const key of Object.getOwnPropertyNames(${c.className})) {
25
+ if (key.startsWith('ɵ')) type[key] = ${c.className}[key];
26
+ }
18
27
  }`)
19
28
  .join('\n');
29
+ // Components: use ɵɵreplaceMetadata for full LView recreation
30
+ const localDepsArray = localDepClassNames.length > 0 ? `[${localDepClassNames.join(', ')}]` : '[]';
20
31
  const replaceBlocks = components
21
32
  .map((c) => `
22
33
  try {
@@ -24,7 +35,7 @@ export function ɵhmr_${c.className}(type, namespaces) {
24
35
  ${c.className},
25
36
  newModule.ɵhmr_${c.className},
26
37
  { i0 },
27
- [],
38
+ ${localDepsArray},
28
39
  import.meta,
29
40
  "${c.className}"
30
41
  );
@@ -33,16 +44,36 @@ export function ɵhmr_${c.className}(type, namespaces) {
33
44
  // ɵɵreplaceMetadata failed — will fall back to page reload
34
45
  }`)
35
46
  .join('\n');
36
- return `\n${applyFns}
37
- if (import.meta.hot) {
38
- import.meta.hot.accept((newModule) => {
39
- if (!newModule) return;
47
+ // Directives/pipes: swap static fields and invalidate
48
+ const swapBlocks = nonComponents
49
+ .map((c) => `
50
+ try {
51
+ newModule.ɵhmr_${c.className}(${c.className});
52
+ swapped = true;
53
+ } catch(e) {}`)
54
+ .join('\n');
55
+ let acceptBody = `
56
+ if (!newModule) return;`;
57
+ if (components.length > 0) {
58
+ acceptBody += `
40
59
  let replaced = false;${replaceBlocks}
41
60
  if (!replaced) {
42
- // Fallback: if no component was successfully replaced (e.g. root component),
43
- // trigger a full page reload
44
61
  import.meta.hot.invalidate('Component HMR failed, reloading');
62
+ return;
63
+ }`;
64
+ }
65
+ if (nonComponents.length > 0) {
66
+ acceptBody += `
67
+ let swapped = false;${swapBlocks}
68
+ if (swapped) {
69
+ // Directive/pipe definitions updated — full reload needed for Angular
70
+ // to pick up the new behavior since ɵɵreplaceMetadata only supports components.
71
+ import.meta.hot.invalidate('Directive/pipe changed, reloading');
72
+ }`;
45
73
  }
74
+ return `\n${applyFns}
75
+ if (import.meta.hot) {
76
+ import.meta.hot.accept((newModule) => {${acceptBody}
46
77
  });
47
78
  }`;
48
79
  }
@@ -1 +1 @@
1
- {"version":3,"file":"hmr.js","sourceRoot":"","sources":["../../../../../packages/angular-compiler/src/lib/hmr.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,UAA2B;IACzD,wEAAwE;IACxE,MAAM,QAAQ,GAAG,UAAU;SACxB,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;uBACU,CAAC,CAAC,SAAS;gBAClB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,SAAS;EACzB,CACG;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,MAAM,aAAa,GAAG,UAAU;SAC7B,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;;;YAGD,CAAC,CAAC,SAAS;2BACI,CAAC,CAAC,SAAS;;;;aAIzB,CAAC,CAAC,SAAS;;;;;QAKhB,CACH;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,KAAK,QAAQ;;;;2BAIK,aAAa;;;;;;;EAOtC,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"hmr.js","sourceRoot":"","sources":["../../../../../packages/angular-compiler/src/lib/hmr.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAC7B,YAA6B,EAC7B,qBAA+B,EAAE;IAEjC,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;IACtE,MAAM,aAAa,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;IAEzE,yEAAyE;IACzE,sEAAsE;IACtE,6DAA6D;IAC7D,MAAM,QAAQ,GAAG,YAAY;SAC1B,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;uBACU,CAAC,CAAC,SAAS;iDACe,CAAC,CAAC,SAAS;2CACjB,CAAC,CAAC,SAAS;;EAEpD,CACG;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,8DAA8D;IAC9D,MAAM,cAAc,GAClB,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IAE9E,MAAM,aAAa,GAAG,UAAU;SAC7B,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;;;YAGD,CAAC,CAAC,SAAS;2BACI,CAAC,CAAC,SAAS;;YAE1B,cAAc;;aAEb,CAAC,CAAC,SAAS;;;;;QAKhB,CACH;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,sDAAsD;IACtD,MAAM,UAAU,GAAG,aAAa;SAC7B,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;;yBAEY,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,SAAS;;oBAE/B,CACf;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,IAAI,UAAU,GAAG;4BACS,CAAC;IAE3B,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,UAAU,IAAI;2BACS,aAAa;;;;MAIlC,CAAC;IACL,CAAC;IAED,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,UAAU,IAAI;0BACQ,UAAU;;;;;MAK9B,CAAC;IACL,CAAC;IAED,OAAO,KAAK,QAAQ;;2CAEqB,UAAU;;EAEnD,CAAC;AACH,CAAC"}