@analogjs/vite-plugin-angular 3.0.0-alpha.59 → 3.0.0-alpha.60

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.
Files changed (48) hide show
  1. package/package.json +1 -1
  2. package/src/lib/angular-vite-plugin.js +9 -3
  3. package/src/lib/angular-vite-plugin.js.map +1 -1
  4. package/src/lib/compiler/compile.d.ts +6 -0
  5. package/src/lib/compiler/compile.js +68 -9
  6. package/src/lib/compiler/compile.js.map +1 -1
  7. package/src/lib/compiler/constants.d.ts +6 -0
  8. package/src/lib/compiler/constants.js +7 -1
  9. package/src/lib/compiler/constants.js.map +1 -1
  10. package/src/lib/compiler/defer.js +1 -1
  11. package/src/lib/compiler/dts-reader.d.ts +13 -3
  12. package/src/lib/compiler/dts-reader.js +38 -8
  13. package/src/lib/compiler/dts-reader.js.map +1 -1
  14. package/src/lib/compiler/index.d.ts +2 -1
  15. package/src/lib/compiler/index.js +1 -0
  16. package/src/lib/compiler/jit-transform.js +1 -1
  17. package/src/lib/compiler/jit-transform.js.map +1 -1
  18. package/src/lib/compiler/js-emitter.js +2 -2
  19. package/src/lib/compiler/js-emitter.js.map +1 -1
  20. package/src/lib/compiler/metadata.d.ts +0 -9
  21. package/src/lib/compiler/metadata.js +67 -6
  22. package/src/lib/compiler/metadata.js.map +1 -1
  23. package/src/lib/compiler/registry.d.ts +8 -1
  24. package/src/lib/compiler/registry.js +15 -3
  25. package/src/lib/compiler/registry.js.map +1 -1
  26. package/src/lib/compiler/resource-inliner.d.ts +27 -5
  27. package/src/lib/compiler/resource-inliner.js +138 -60
  28. package/src/lib/compiler/resource-inliner.js.map +1 -1
  29. package/src/lib/compiler/style-ast.d.ts +2 -1
  30. package/src/lib/compiler/style-ast.js +2 -2
  31. package/src/lib/compiler/style-ast.js.map +1 -1
  32. package/src/lib/compiler/type-elision.d.ts +5 -3
  33. package/src/lib/compiler/type-elision.js +8 -8
  34. package/src/lib/compiler/type-elision.js.map +1 -1
  35. package/src/lib/compiler-plugin.d.ts +3 -2
  36. package/src/lib/compiler-plugin.js +4 -4
  37. package/src/lib/compiler-plugin.js.map +1 -1
  38. package/src/lib/component-resolvers.js +4 -5
  39. package/src/lib/component-resolvers.js.map +1 -1
  40. package/src/lib/fast-compile-plugin.js +136 -23
  41. package/src/lib/fast-compile-plugin.js.map +1 -1
  42. package/src/lib/router-plugin.js +13 -1
  43. package/src/lib/router-plugin.js.map +1 -1
  44. package/src/lib/utils/plugin-config.js +6 -3
  45. package/src/lib/utils/plugin-config.js.map +1 -1
  46. package/src/lib/utils/transform-cache.d.ts +43 -0
  47. package/src/lib/utils/transform-cache.js +97 -0
  48. package/src/lib/utils/transform-cache.js.map +1 -0
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","names":[],"sources":["../../../../src/lib/compiler/constants.ts"],"sourcesContent":["/**\n * Shared Angular name constants for the fast-compile path.\n *\n * Centralised here to prevent drift when decorator sets are referenced\n * across multiple source files (compile, registry, JIT, metadata).\n */\n\n/** All six Angular class decorators. */\nexport const ANGULAR_DECORATORS = new Set([\n 'Component',\n 'Directive',\n 'Pipe',\n 'Injectable',\n 'Service',\n 'NgModule',\n]);\n\n/**\n * Angular decorators that produce compilable declarations (selector, template,\n * pipe name, or module exports). Excludes `@Injectable` and `@Service`, which\n * self-register via ɵprov and don't need Ivy compilation.\n */\nexport const COMPILABLE_DECORATORS = new Set([\n 'Component',\n 'Directive',\n 'Pipe',\n 'NgModule',\n]);\n\n/** Decorator names used on class fields and host bindings. */\nexport const FIELD_DECORATORS = new Set([\n 'Input',\n 'Output',\n 'ViewChild',\n 'ViewChildren',\n 'ContentChild',\n 'ContentChildren',\n 'HostBinding',\n 'HostListener',\n]);\n\n/** Signal-based reactive APIs that need downleveling or metadata extraction. */\nexport const SIGNAL_APIS = new Set([\n 'input',\n 'model',\n 'output',\n 'outputFromObservable',\n 'viewChild',\n 'viewChildren',\n 'contentChild',\n 'contentChildren',\n]);\n"],"mappings":";;;;;;;;AAQA,IAAa,qBAAqB,IAAI,IAAI;CACxC;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;AAOF,IAAa,wBAAwB,IAAI,IAAI;CAC3C;CACA;CACA;CACA;CACD,CAAC;;AAGF,IAAa,mBAAmB,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;AAGF,IAAa,cAAc,IAAI,IAAI;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC"}
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../../../../src/lib/compiler/constants.ts"],"sourcesContent":["/**\n * Shared Angular name constants for the fast-compile path.\n *\n * Centralised here to prevent drift when decorator sets are referenced\n * across multiple source files (compile, registry, JIT, metadata).\n */\n\n/** All six Angular class decorators. */\nexport const ANGULAR_DECORATORS = new Set([\n 'Component',\n 'Directive',\n 'Pipe',\n 'Injectable',\n 'Service',\n 'NgModule',\n]);\n\n/**\n * Matches a call to any Angular class decorator (e.g. `Component(` or `Service(`).\n * Derived from {@link ANGULAR_DECORATORS} so the fast-path \"is this an Angular file?\"\n * checks stay in sync with the canonical decorator set and don't drift.\n */\nexport const ANGULAR_DECORATOR_CALL_RE = new RegExp(\n `@(${[...ANGULAR_DECORATORS].join('|')})\\\\(`,\n);\n\n/**\n * Angular decorators that produce compilable declarations (selector, template,\n * pipe name, or module exports). Excludes `@Injectable` and `@Service`, which\n * self-register via ɵprov and don't need Ivy compilation.\n */\nexport const COMPILABLE_DECORATORS = new Set([\n 'Component',\n 'Directive',\n 'Pipe',\n 'NgModule',\n]);\n\n/** Decorator names used on class fields and host bindings. */\nexport const FIELD_DECORATORS = new Set([\n 'Input',\n 'Output',\n 'ViewChild',\n 'ViewChildren',\n 'ContentChild',\n 'ContentChildren',\n 'HostBinding',\n 'HostListener',\n]);\n\n/** Signal-based reactive APIs that need downleveling or metadata extraction. */\nexport const SIGNAL_APIS = new Set([\n 'input',\n 'model',\n 'output',\n 'outputFromObservable',\n 'viewChild',\n 'viewChildren',\n 'contentChild',\n 'contentChildren',\n]);\n"],"mappings":";;;;;;;;AAQA,IAAa,qBAAqB,IAAI,IAAI;CACxC;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;;;;;AAOF,IAAa,4BAA4B,IAAI,OAC3C,KAAK,CAAC,GAAG,mBAAmB,CAAC,KAAK,IAAI,CAAC,MACxC;;;;;;AAOD,IAAa,wBAAwB,IAAI,IAAI;CAC3C;CACA;CACA;CACA;CACD,CAAC;;AAGF,IAAa,mBAAmB,IAAI,IAAI;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;;AAGF,IAAa,cAAc,IAAI,IAAI;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC"}
@@ -1,5 +1,5 @@
1
- import * as ts from "typescript";
2
1
  import * as o from "@angular/compiler";
2
+ import * as ts from "typescript";
3
3
  //#region packages/vite-plugin-angular/src/lib/compiler/defer.ts
4
4
  /** Recursively collect all DeferredBlock nodes from a template AST. */
5
5
  function collectDeferBlocks(nodes) {
@@ -1,3 +1,4 @@
1
+ import { parseSync } from "oxc-parser";
1
2
  import { RegistryEntry } from "./registry.js";
2
3
  /**
3
4
  * Scan a single .d.ts file and extract Angular directive/component/pipe
@@ -16,13 +17,13 @@ export declare function scanDtsFile(code: string, fileName: string): RegistryEnt
16
17
  * @param packageName e.g. "@angular/router"
17
18
  * @param basePath project root (where node_modules lives)
18
19
  */
19
- export declare function scanPackageDts(packageName: string, basePath: string): RegistryEntry[];
20
+ export declare function scanPackageDts(packageName: string, basePath: string, visited?: Set<string>): RegistryEntry[];
20
21
  /**
21
22
  * Parse a source file with OXC and return the set of bare-specifier package
22
23
  * names it imports (e.g. "@angular/router", "rxjs"). Relative imports are
23
24
  * skipped.
24
25
  */
25
- export declare function collectImportedPackages(code: string, fileName: string): Set<string>;
26
+ export declare function collectImportedPackages(code: string, fileName: string, program?: ReturnType<typeof parseSync>["program"]): Set<string>;
26
27
  /**
27
28
  * Parse a source file with OXC and return the relative-path specifiers it
28
29
  * re-exports via `export * from './x'`, `export * as Ns from './x'`, or
@@ -32,4 +33,13 @@ export declare function collectImportedPackages(code: string, fileName: string):
32
33
  * (e.g. `helm/select/src/index.ts` → `./lib/hlm-select`) so the underlying
33
34
  * directive classes land in the registry before any consumer is compiled.
34
35
  */
35
- export declare function collectRelativeReExports(code: string, fileName: string): string[];
36
+ export declare function collectRelativeReExports(code: string, fileName: string, program?: ReturnType<typeof parseSync>["program"]): string[];
37
+ /**
38
+ * Parse a source file with OXC and return every module specifier it imports or
39
+ * re-exports from (relative AND bare), including `import`, `export * from`, and
40
+ * `export { … } from`. Used to walk the transitive import graph at startup so
41
+ * the registry contains components/directives/pipes/modules from files not
42
+ * directly listed in tsconfig `files`/`include` (transitively-imported app
43
+ * sources) or behind wildcard `paths` (workspace libraries).
44
+ */
45
+ export declare function collectAllImports(code: string, fileName: string, program?: ReturnType<typeof parseSync>["program"]): string[];
@@ -25,7 +25,7 @@ function scanDtsFile(code, fileName) {
25
25
  * @param packageName e.g. "@angular/router"
26
26
  * @param basePath project root (where node_modules lives)
27
27
  */
28
- function scanPackageDts(packageName, basePath) {
28
+ function scanPackageDts(packageName, basePath, visited) {
29
29
  let pkgDir = "";
30
30
  let searchBase = basePath;
31
31
  while (searchBase !== path$1.dirname(searchBase)) {
@@ -41,11 +41,21 @@ function scanPackageDts(packageName, basePath) {
41
41
  const typesDir = path$1.join(pkgDir, "types");
42
42
  const dtsFiles = collectDtsFiles(fs.existsSync(typesDir) ? typesDir : pkgDir);
43
43
  const entries = [];
44
+ const referencedPackages = /* @__PURE__ */ new Set();
44
45
  for (const file of dtsFiles) try {
45
- const fileEntries = scanDtsFile(fs.readFileSync(file, "utf-8"), file);
46
+ const code = fs.readFileSync(file, "utf-8");
47
+ const fileEntries = scanDtsFile(code, file);
46
48
  for (const entry of fileEntries) entry.sourcePackage = classToImportPath.get(entry.className) || subEntryFromFilePath(packageName, pkgDir, file) || packageName;
47
49
  entries.push(...fileEntries);
50
+ if (visited && fileEntries.some((e) => e.kind === "ngmodule")) for (const p of collectImportedPackages(code, file)) referencedPackages.add(p);
48
51
  } catch {}
52
+ if (visited) for (const p of referencedPackages) {
53
+ if (p === packageName || visited.has(p)) continue;
54
+ visited.add(p);
55
+ try {
56
+ entries.push(...scanPackageDts(p, basePath, visited));
57
+ } catch {}
58
+ }
49
59
  return entries;
50
60
  }
51
61
  /**
@@ -160,9 +170,9 @@ function subEntryFromFilePath(packageName, pkgDir, filePath) {
160
170
  * names it imports (e.g. "@angular/router", "rxjs"). Relative imports are
161
171
  * skipped.
162
172
  */
163
- function collectImportedPackages(code, fileName) {
173
+ function collectImportedPackages(code, fileName, program) {
164
174
  const packages = /* @__PURE__ */ new Set();
165
- const { program } = parseSync(fileName, code);
175
+ program ??= parseSync(fileName, code).program;
166
176
  for (const stmt of program.body) {
167
177
  if (stmt.type !== "ImportDeclaration") continue;
168
178
  const specifier = stmt.source?.value;
@@ -181,9 +191,8 @@ function collectImportedPackages(code, fileName) {
181
191
  * (e.g. `helm/select/src/index.ts` → `./lib/hlm-select`) so the underlying
182
192
  * directive classes land in the registry before any consumer is compiled.
183
193
  */
184
- function collectRelativeReExports(code, fileName) {
185
- let program;
186
- try {
194
+ function collectRelativeReExports(code, fileName, program) {
195
+ if (!program) try {
187
196
  program = parseSync(fileName, code).program;
188
197
  } catch {
189
198
  return [];
@@ -197,6 +206,27 @@ function collectRelativeReExports(code, fileName) {
197
206
  }
198
207
  return result;
199
208
  }
209
+ /**
210
+ * Parse a source file with OXC and return every module specifier it imports or
211
+ * re-exports from (relative AND bare), including `import`, `export * from`, and
212
+ * `export { … } from`. Used to walk the transitive import graph at startup so
213
+ * the registry contains components/directives/pipes/modules from files not
214
+ * directly listed in tsconfig `files`/`include` (transitively-imported app
215
+ * sources) or behind wildcard `paths` (workspace libraries).
216
+ */
217
+ function collectAllImports(code, fileName, program) {
218
+ if (!program) try {
219
+ program = parseSync(fileName, code).program;
220
+ } catch {
221
+ return [];
222
+ }
223
+ const result = [];
224
+ for (const stmt of program.body || []) if (stmt.type === "ImportDeclaration" || stmt.type === "ExportAllDeclaration" || stmt.type === "ExportNamedDeclaration") {
225
+ const specifier = stmt.source?.value;
226
+ if (specifier) result.push(specifier);
227
+ }
228
+ return result;
229
+ }
200
230
  function visitStatements(stmts, fileName, entries) {
201
231
  for (const stmt of stmts) {
202
232
  const decl = stmt.type === "ExportNamedDeclaration" || stmt.type === "ExportDefaultDeclaration" ? stmt.declaration : stmt;
@@ -360,6 +390,6 @@ function collectDtsFiles(dir) {
360
390
  return results;
361
391
  }
362
392
  //#endregion
363
- export { collectImportedPackages, collectRelativeReExports, scanDtsFile, scanPackageDts };
393
+ export { collectAllImports, collectImportedPackages, collectRelativeReExports, scanDtsFile, scanPackageDts };
364
394
 
365
395
  //# sourceMappingURL=dts-reader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dts-reader.js","names":[],"sources":["../../../../src/lib/compiler/dts-reader.ts"],"sourcesContent":["import { parseSync } from 'oxc-parser';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { RegistryEntry, RegistryInput } from './registry.js';\n\n/**\n * Scan a single .d.ts file and extract Angular directive/component/pipe\n * metadata from the static ɵdir / ɵcmp / ɵpipe type declarations.\n *\n * This mirrors what ngtsc's DtsMetadataReader does: it reads the type\n * parameters of ɵɵDirectiveDeclaration / ɵɵComponentDeclaration /\n * ɵɵPipeDeclaration to discover selectors, inputs, and outputs for\n * pre-compiled Angular packages.\n */\nexport function scanDtsFile(code: string, fileName: string): RegistryEntry[] {\n // Fast pre-filter — skip files that can't contain Angular declarations\n if (\n !code.includes('DirectiveDeclaration') &&\n !code.includes('ComponentDeclaration') &&\n !code.includes('PipeDeclaration') &&\n !code.includes('NgModuleDeclaration')\n )\n return [];\n\n const { program } = parseSync(fileName, code);\n const entries: RegistryEntry[] = [];\n\n visitStatements(program.body, fileName, entries);\n return entries;\n}\n\n/**\n * Resolve a package's directory in node_modules, scan all its .d.ts files,\n * and return RegistryEntry[] for every Angular declaration found.\n *\n * @param packageName e.g. \"@angular/router\"\n * @param basePath project root (where node_modules lives)\n */\nexport function scanPackageDts(\n packageName: string,\n basePath: string,\n): RegistryEntry[] {\n // Walk up from basePath to find the nearest node_modules containing the package.\n // This handles monorepos where node_modules is at the workspace root,\n // not in the project subdirectory.\n let pkgDir = '';\n let searchBase = basePath;\n while (searchBase !== path.dirname(searchBase)) {\n const candidate = path.join(searchBase, 'node_modules', packageName);\n if (fs.existsSync(candidate)) {\n pkgDir = candidate;\n break;\n }\n searchBase = path.dirname(searchBase);\n }\n if (!pkgDir) return [];\n\n // Build a map from className → correct import path using package.json exports.\n // This handles packages with sub-entry points (e.g. @angular/material/tabs)\n // where re-exported classes must be imported from their origin entry point.\n const classToImportPath = buildClassToImportMap(packageName, pkgDir);\n\n // Check for a \"types\" directory first (Angular packages use this),\n // then fall back to the package root.\n const typesDir = path.join(pkgDir, 'types');\n const searchDir = fs.existsSync(typesDir) ? typesDir : pkgDir;\n\n const dtsFiles = collectDtsFiles(searchDir);\n const entries: RegistryEntry[] = [];\n\n for (const file of dtsFiles) {\n try {\n const code = fs.readFileSync(file, 'utf-8');\n const fileEntries = scanDtsFile(code, file);\n for (const entry of fileEntries) {\n entry.sourcePackage =\n classToImportPath.get(entry.className) ||\n subEntryFromFilePath(packageName, pkgDir, file) ||\n packageName;\n }\n entries.push(...fileEntries);\n } catch {\n // Skip unreadable files\n }\n }\n\n return entries;\n}\n\n/**\n * Read package.json exports to build a map from class name to the correct\n * sub-entry import path (e.g. \"MatTabNav\" → \"@angular/material/tabs\").\n *\n * For each sub-entry that has a \"types\" field, the corresponding .d.ts file\n * is read to collect declared class names and re-exported names.\n */\nfunction buildClassToImportMap(\n packageName: string,\n pkgDir: string,\n): Map<string, string> {\n const map = new Map<string, string>();\n try {\n const pkgJson = JSON.parse(\n fs.readFileSync(path.join(pkgDir, 'package.json'), 'utf-8'),\n );\n if (!pkgJson.exports) return map;\n\n for (const [key, value] of Object.entries(pkgJson.exports) as [\n string,\n any,\n ][]) {\n if (key !== '.' && !key.startsWith('./')) continue;\n // Resolve types from the export entry. Some packages declare\n // `types` only at the package root (top-level package.json `types`\n // field) rather than per-export, so fall back to that for `.`.\n let typesFile: string | undefined =\n typeof value === 'object' && value !== null && value.types;\n if (!typesFile && key === '.' && typeof pkgJson.types === 'string') {\n typesFile = pkgJson.types;\n }\n if (!typesFile) continue;\n\n // Root entry (`.`) maps classes to the bare package name; sub-entries\n // (`./tabs`) map to `${packageName}/tabs`. Mapping root-exported\n // classes prevents `subEntryFromFilePath` from deriving an invalid\n // subpath like `ngx-scrollbar/lib` for files that physically live in\n // a `lib/` subdirectory but are only re-exported from the root entry.\n const importPath =\n key === '.' ? packageName : packageName + '/' + key.slice(2);\n const fullTypesPath = path.resolve(pkgDir, typesFile);\n if (!fs.existsSync(fullTypesPath)) continue;\n\n collectExportedClassesFromDts(fullTypesPath, importPath, map);\n }\n } catch {\n // No package.json or no exports — fall back to packageName\n }\n return map;\n}\n\n/**\n * Read a `.d.ts` entry file and add every class it exports to `map`,\n * following `export * from './rel'` chains so re-exported classes from\n * physically nested files (e.g. `lib/foo.d.ts`) are still mapped to the\n * exporting entry's import path.\n *\n * Without this, packages whose root `index.d.ts` is just a barrel of\n * `export * from './lib/...'` would never get their classes mapped, and the\n * `subEntryFromFilePath` fallback would derive an invalid `${pkg}/lib`\n * import for files living under `lib/`.\n */\nfunction collectExportedClassesFromDts(\n filePath: string,\n importPath: string,\n map: Map<string, string>,\n visited: Set<string> = new Set(),\n): void {\n if (visited.has(filePath)) return;\n visited.add(filePath);\n let code: string;\n try {\n code = fs.readFileSync(filePath, 'utf-8');\n } catch {\n return;\n }\n\n let program: any;\n try {\n program = parseSync(filePath, code).program;\n } catch {\n return;\n }\n\n const dir = path.dirname(filePath);\n for (const stmt of program.body || []) {\n // `declare class Foo` (top-level)\n if (stmt.type === 'ClassDeclaration' && stmt.id?.name) {\n map.set(stmt.id.name, importPath);\n continue;\n }\n\n // `export declare class Foo` / `export class Foo` /\n // `export { A, B as C } from '...'` / `export { A, B }`\n if (stmt.type === 'ExportNamedDeclaration') {\n if (\n stmt.declaration?.type === 'ClassDeclaration' &&\n stmt.declaration.id?.name\n ) {\n map.set(stmt.declaration.id.name, importPath);\n }\n for (const spec of stmt.specifiers || []) {\n // ExportSpecifier: { local, exported }\n const exportedNode = spec.exported;\n const exportedName =\n exportedNode?.type === 'Identifier'\n ? exportedNode.name\n : exportedNode?.type === 'Literal'\n ? exportedNode.value\n : undefined;\n if (typeof exportedName === 'string') {\n map.set(exportedName, importPath);\n }\n }\n continue;\n }\n\n // `export * from './rel'` and `export * as Ns from './rel'`\n if (stmt.type === 'ExportAllDeclaration') {\n const rel: string | undefined = stmt.source?.value;\n if (!rel || !rel.startsWith('.')) continue;\n // TypeScript preserves the original specifier text in emitted\n // `.d.ts` files, so NodeNext-style packages keep their `.js`\n // (or `.mjs`) extensions in re-exports — but the actual\n // declaration is at `foo.d.ts` / `foo/index.d.ts`. Strip the\n // ESM extension before probing.\n const normalizedRel = rel.replace(/\\.(?:js|mjs)$/u, '');\n const candidates = [\n path.resolve(dir, normalizedRel + '.d.ts'),\n path.resolve(dir, normalizedRel, 'index.d.ts'),\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n collectExportedClassesFromDts(candidate, importPath, map, visited);\n break;\n }\n }\n continue;\n }\n }\n}\n\n/**\n * Derive a sub-entry import path from a .d.ts file's location relative to the\n * package root. This handles older Angular packages that keep .d.ts files in\n * subdirectories (e.g. `@angular/material/tabs/index.d.ts`) instead of a\n * top-level `types/` folder.\n *\n * Returns `undefined` when no sub-entry can be determined (e.g. file is at the\n * package root, inside `types/`, or in a non-entry directory).\n */\nfunction subEntryFromFilePath(\n packageName: string,\n pkgDir: string,\n filePath: string,\n): string | undefined {\n const NON_ENTRY_DIRS = new Set([\n 'types',\n 'fesm2022',\n 'fesm2020',\n 'fesm2015',\n 'esm2022',\n 'esm2020',\n 'esm2015',\n 'bundles',\n 'schematics',\n 'node_modules',\n ]);\n const rel = path.relative(pkgDir, filePath);\n const segments = rel.split(path.sep);\n // File directly in pkgDir (no subdirectory) → no sub-entry\n if (segments.length < 2) return undefined;\n const firstDir = segments[0];\n // Skip internal/build directories and chunk files\n if (NON_ENTRY_DIRS.has(firstDir) || firstDir.startsWith('_'))\n return undefined;\n return packageName + '/' + firstDir;\n}\n\n/**\n * Parse a source file with OXC and return the set of bare-specifier package\n * names it imports (e.g. \"@angular/router\", \"rxjs\"). Relative imports are\n * skipped.\n */\nexport function collectImportedPackages(\n code: string,\n fileName: string,\n): Set<string> {\n const packages = new Set<string>();\n const { program } = parseSync(fileName, code);\n\n for (const stmt of program.body) {\n if (stmt.type !== 'ImportDeclaration') continue;\n const specifier: string = stmt.source?.value;\n if (!specifier || specifier.startsWith('.')) continue;\n\n const parts = specifier.split('/');\n packages.add(\n specifier.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0],\n );\n }\n\n return packages;\n}\n\n/**\n * Parse a source file with OXC and return the relative-path specifiers it\n * re-exports via `export * from './x'`, `export * as Ns from './x'`, or\n * `export { … } from './x'`. Bare-specifier re-exports are skipped.\n *\n * Used by the analog Vite plugin to walk library entry barrels at startup\n * (e.g. `helm/select/src/index.ts` → `./lib/hlm-select`) so the underlying\n * directive classes land in the registry before any consumer is compiled.\n */\nexport function collectRelativeReExports(\n code: string,\n fileName: string,\n): string[] {\n let program: any;\n try {\n program = parseSync(fileName, code).program;\n } catch {\n return [];\n }\n const result: string[] = [];\n for (const stmt of program.body || []) {\n if (\n stmt.type !== 'ExportAllDeclaration' &&\n stmt.type !== 'ExportNamedDeclaration'\n ) {\n continue;\n }\n // ExportNamedDeclaration without `source` is `export { x }` (no\n // re-export), which we don't care about here.\n const specifier: string | undefined = stmt.source?.value;\n if (!specifier || !specifier.startsWith('.')) continue;\n result.push(specifier);\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction visitStatements(\n stmts: any[],\n fileName: string,\n entries: RegistryEntry[],\n) {\n for (const stmt of stmts) {\n // Unwrap exports: `export declare class ...` / `export default class ...`\n const decl =\n stmt.type === 'ExportNamedDeclaration' ||\n stmt.type === 'ExportDefaultDeclaration'\n ? stmt.declaration\n : stmt;\n\n if (!decl) continue;\n\n // Recurse into `declare module \"...\" { ... }` blocks\n if (decl.type === 'TSModuleDeclaration' && decl.body?.body) {\n visitStatements(decl.body.body, fileName, entries);\n continue;\n }\n\n if (decl.type !== 'ClassDeclaration' || !decl.id?.name) continue;\n const className: string = decl.id.name;\n const members: any[] = decl.body?.body || [];\n\n for (const member of members) {\n if (member.type !== 'PropertyDefinition' || !member.static) continue;\n const propName: string | undefined = member.key?.name;\n\n // Read the type annotation: e.g. `i0.ɵɵDirectiveDeclaration<...>`\n const typeRef = member.typeAnnotation?.typeAnnotation;\n if (!typeRef || typeRef.type !== 'TSTypeReference') continue;\n\n const typeName = qualifiedName(typeRef.typeName);\n const typeParams: any[] | undefined = typeRef.typeArguments?.params;\n\n if (\n (propName === 'ɵdir' || propName === 'ɵcmp') &&\n (typeName.includes('DirectiveDeclaration') ||\n typeName.includes('ComponentDeclaration')) &&\n typeParams &&\n typeParams.length >= 5\n ) {\n const selector = literalString(typeParams[1]);\n if (!selector) continue;\n\n const inputs = extractInputs(typeParams[3]);\n const outputs = extractOutputs(typeParams[4]);\n\n entries.push({\n selector: selector.split(',')[0].trim(),\n kind: propName === 'ɵcmp' ? 'component' : 'directive',\n fileName,\n className,\n ...(Object.keys(inputs).length > 0 ? { inputs } : {}),\n ...(Object.keys(outputs).length > 0 ? { outputs } : {}),\n });\n } else if (\n propName === 'ɵpipe' &&\n typeName.includes('PipeDeclaration') &&\n typeParams &&\n typeParams.length >= 2\n ) {\n const pipeName = literalString(typeParams[1]);\n if (!pipeName) continue;\n\n entries.push({\n selector: pipeName,\n kind: 'pipe',\n pipeName,\n fileName,\n className,\n });\n } else if (\n propName === 'ɵmod' &&\n typeName.includes('NgModuleDeclaration') &&\n typeParams &&\n typeParams.length >= 4\n ) {\n // ɵɵNgModuleDeclaration<Module, Declarations, Imports, Exports>\n // Extract exported class names from the 4th type param (index 3).\n const exportsParam = typeParams[3];\n const exportedNames: string[] = [];\n if (exportsParam?.type === 'TSTupleType' && exportsParam.elementTypes) {\n for (const el of exportsParam.elementTypes) {\n if (\n el.type === 'TSTypeQuery' &&\n el.exprName?.type === 'Identifier'\n ) {\n exportedNames.push(el.exprName.name);\n } else if (\n el.type === 'TSTypeQuery' &&\n el.exprName?.type === 'TSQualifiedName'\n ) {\n // e.g. typeof i2.BidiModule → extract \"BidiModule\"\n const right = el.exprName.right;\n if (right?.type === 'Identifier') {\n exportedNames.push(right.name);\n }\n }\n }\n }\n entries.push({\n selector: className,\n kind: 'ngmodule',\n exports: exportedNames,\n fileName,\n className,\n });\n }\n }\n }\n}\n\n/**\n * Extract inputs from the type-argument at position [3].\n *\n * Handles two formats:\n * v16+: { \"prop\": { \"alias\": \"binding\"; \"required\": false; \"isSignal\"?: true } }\n * pre-v16: { \"prop\": \"binding\" }\n */\nfunction extractInputs(node: any): Record<string, RegistryInput> {\n const inputs: Record<string, RegistryInput> = {};\n if (node?.type !== 'TSTypeLiteral') return inputs;\n\n for (const member of node.members) {\n if (member.type !== 'TSPropertySignature') continue;\n const propName = keyName(member.key);\n const innerType = member.typeAnnotation?.typeAnnotation;\n if (!propName || !innerType) continue;\n\n if (innerType.type === 'TSTypeLiteral') {\n // v16+ object format\n let alias = propName;\n let required = false;\n let isSignal = false;\n\n for (const inner of innerType.members) {\n if (inner.type !== 'TSPropertySignature') continue;\n const key = keyName(inner.key);\n const val = inner.typeAnnotation?.typeAnnotation;\n if (!key || !val) continue;\n\n if (key === 'alias') {\n alias = literalString(val) ?? propName;\n } else if (key === 'required') {\n required = literalBoolean(val) === true;\n } else if (key === 'isSignal') {\n isSignal = literalBoolean(val) === true;\n }\n }\n\n inputs[propName] = {\n classPropertyName: propName,\n bindingPropertyName: alias,\n isSignal,\n required,\n };\n } else {\n // pre-v16 string format\n const alias = literalString(innerType);\n if (alias) {\n inputs[propName] = {\n classPropertyName: propName,\n bindingPropertyName: alias,\n isSignal: false,\n required: false,\n };\n }\n }\n }\n\n return inputs;\n}\n\n/**\n * Extract outputs from the type-argument at position [4].\n * Format: { \"propName\": \"eventName\" }\n */\nfunction extractOutputs(node: any): Record<string, string> {\n const outputs: Record<string, string> = {};\n if (node?.type !== 'TSTypeLiteral') return outputs;\n\n for (const member of node.members) {\n if (member.type !== 'TSPropertySignature') continue;\n const propName = keyName(member.key);\n const val = member.typeAnnotation?.typeAnnotation;\n if (!propName || !val) continue;\n\n const value = literalString(val);\n if (value) outputs[propName] = value;\n }\n\n return outputs;\n}\n\n/** Get the string name from a property key (Identifier or Literal). */\nfunction keyName(key: any): string | undefined {\n if (!key) return undefined;\n if (key.type === 'Identifier') return key.name;\n if (key.type === 'Literal' && typeof key.value === 'string') return key.value;\n return undefined;\n}\n\n/** Build a dotted name from an Identifier or TSQualifiedName. */\nfunction qualifiedName(node: any): string {\n if (!node) return '';\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'TSQualifiedName')\n return qualifiedName(node.left) + '.' + qualifiedName(node.right);\n return '';\n}\n\n/** Extract a string value from a TSLiteralType node. */\nfunction literalString(node: any): string | undefined {\n if (\n node?.type === 'TSLiteralType' &&\n node.literal?.type === 'Literal' &&\n typeof node.literal.value === 'string'\n ) {\n return node.literal.value;\n }\n return undefined;\n}\n\n/** Extract a boolean value from a TSLiteralType node. */\nfunction literalBoolean(node: any): boolean | undefined {\n if (\n node?.type === 'TSLiteralType' &&\n node.literal?.type === 'Literal' &&\n typeof node.literal.value === 'boolean'\n ) {\n return node.literal.value;\n }\n return undefined;\n}\n\n/** Recursively collect all .d.ts files under a directory. */\nfunction collectDtsFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return results;\n }\n\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory() && entry.name !== 'node_modules') {\n results.push(...collectDtsFiles(full));\n } else if (entry.isFile() && entry.name.endsWith('.d.ts')) {\n results.push(full);\n }\n }\n\n return results;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"dts-reader.js","names":[],"sources":["../../../../src/lib/compiler/dts-reader.ts"],"sourcesContent":["import { parseSync } from 'oxc-parser';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { RegistryEntry, RegistryInput } from './registry.js';\n\n/**\n * Scan a single .d.ts file and extract Angular directive/component/pipe\n * metadata from the static ɵdir / ɵcmp / ɵpipe type declarations.\n *\n * This mirrors what ngtsc's DtsMetadataReader does: it reads the type\n * parameters of ɵɵDirectiveDeclaration / ɵɵComponentDeclaration /\n * ɵɵPipeDeclaration to discover selectors, inputs, and outputs for\n * pre-compiled Angular packages.\n */\nexport function scanDtsFile(code: string, fileName: string): RegistryEntry[] {\n // Fast pre-filter — skip files that can't contain Angular declarations\n if (\n !code.includes('DirectiveDeclaration') &&\n !code.includes('ComponentDeclaration') &&\n !code.includes('PipeDeclaration') &&\n !code.includes('NgModuleDeclaration')\n )\n return [];\n\n const { program } = parseSync(fileName, code);\n const entries: RegistryEntry[] = [];\n\n visitStatements(program.body, fileName, entries);\n return entries;\n}\n\n/**\n * Resolve a package's directory in node_modules, scan all its .d.ts files,\n * and return RegistryEntry[] for every Angular declaration found.\n *\n * @param packageName e.g. \"@angular/router\"\n * @param basePath project root (where node_modules lives)\n */\nexport function scanPackageDts(\n packageName: string,\n basePath: string,\n visited?: Set<string>,\n): RegistryEntry[] {\n // Walk up from basePath to find the nearest node_modules containing the package.\n // This handles monorepos where node_modules is at the workspace root,\n // not in the project subdirectory.\n let pkgDir = '';\n let searchBase = basePath;\n while (searchBase !== path.dirname(searchBase)) {\n const candidate = path.join(searchBase, 'node_modules', packageName);\n if (fs.existsSync(candidate)) {\n pkgDir = candidate;\n break;\n }\n searchBase = path.dirname(searchBase);\n }\n if (!pkgDir) return [];\n\n // Build a map from className → correct import path using package.json exports.\n // This handles packages with sub-entry points (e.g. @angular/material/tabs)\n // where re-exported classes must be imported from their origin entry point.\n const classToImportPath = buildClassToImportMap(packageName, pkgDir);\n\n // Check for a \"types\" directory first (Angular packages use this),\n // then fall back to the package root.\n const typesDir = path.join(pkgDir, 'types');\n const searchDir = fs.existsSync(typesDir) ? typesDir : pkgDir;\n\n const dtsFiles = collectDtsFiles(searchDir);\n const entries: RegistryEntry[] = [];\n // Packages re-exported by this package's NgModule declarations. A library\n // NgModule can re-export another package's module (e.g. BrowserModule exports\n // CommonModule), so those packages must be scanned too or their directives\n // (NgIf, NgForOf, …) never reach the registry.\n const referencedPackages = new Set<string>();\n\n for (const file of dtsFiles) {\n try {\n const code = fs.readFileSync(file, 'utf-8');\n const fileEntries = scanDtsFile(code, file);\n for (const entry of fileEntries) {\n entry.sourcePackage =\n classToImportPath.get(entry.className) ||\n subEntryFromFilePath(packageName, pkgDir, file) ||\n packageName;\n }\n entries.push(...fileEntries);\n // Only follow cross-package imports of declaration files that actually\n // contain an NgModule — those are the ones whose exports can pull in\n // another package's directives/pipes. This keeps the walk bounded.\n if (visited && fileEntries.some((e) => e.kind === 'ngmodule')) {\n for (const p of collectImportedPackages(code, file)) {\n referencedPackages.add(p);\n }\n }\n } catch {\n // Skip unreadable files\n }\n }\n\n if (visited) {\n for (const p of referencedPackages) {\n if (p === packageName || visited.has(p)) continue;\n visited.add(p);\n try {\n entries.push(...scanPackageDts(p, basePath, visited));\n } catch {\n // Package may not have .d.ts or not be Angular\n }\n }\n }\n\n return entries;\n}\n\n/**\n * Read package.json exports to build a map from class name to the correct\n * sub-entry import path (e.g. \"MatTabNav\" → \"@angular/material/tabs\").\n *\n * For each sub-entry that has a \"types\" field, the corresponding .d.ts file\n * is read to collect declared class names and re-exported names.\n */\nfunction buildClassToImportMap(\n packageName: string,\n pkgDir: string,\n): Map<string, string> {\n const map = new Map<string, string>();\n try {\n const pkgJson = JSON.parse(\n fs.readFileSync(path.join(pkgDir, 'package.json'), 'utf-8'),\n );\n if (!pkgJson.exports) return map;\n\n for (const [key, value] of Object.entries(pkgJson.exports) as [\n string,\n any,\n ][]) {\n if (key !== '.' && !key.startsWith('./')) continue;\n // Resolve types from the export entry. Some packages declare\n // `types` only at the package root (top-level package.json `types`\n // field) rather than per-export, so fall back to that for `.`.\n let typesFile: string | undefined =\n typeof value === 'object' && value !== null && value.types;\n if (!typesFile && key === '.' && typeof pkgJson.types === 'string') {\n typesFile = pkgJson.types;\n }\n if (!typesFile) continue;\n\n // Root entry (`.`) maps classes to the bare package name; sub-entries\n // (`./tabs`) map to `${packageName}/tabs`. Mapping root-exported\n // classes prevents `subEntryFromFilePath` from deriving an invalid\n // subpath like `ngx-scrollbar/lib` for files that physically live in\n // a `lib/` subdirectory but are only re-exported from the root entry.\n const importPath =\n key === '.' ? packageName : packageName + '/' + key.slice(2);\n const fullTypesPath = path.resolve(pkgDir, typesFile);\n if (!fs.existsSync(fullTypesPath)) continue;\n\n collectExportedClassesFromDts(fullTypesPath, importPath, map);\n }\n } catch {\n // No package.json or no exports — fall back to packageName\n }\n return map;\n}\n\n/**\n * Read a `.d.ts` entry file and add every class it exports to `map`,\n * following `export * from './rel'` chains so re-exported classes from\n * physically nested files (e.g. `lib/foo.d.ts`) are still mapped to the\n * exporting entry's import path.\n *\n * Without this, packages whose root `index.d.ts` is just a barrel of\n * `export * from './lib/...'` would never get their classes mapped, and the\n * `subEntryFromFilePath` fallback would derive an invalid `${pkg}/lib`\n * import for files living under `lib/`.\n */\nfunction collectExportedClassesFromDts(\n filePath: string,\n importPath: string,\n map: Map<string, string>,\n visited: Set<string> = new Set(),\n): void {\n if (visited.has(filePath)) return;\n visited.add(filePath);\n let code: string;\n try {\n code = fs.readFileSync(filePath, 'utf-8');\n } catch {\n return;\n }\n\n let program: any;\n try {\n program = parseSync(filePath, code).program;\n } catch {\n return;\n }\n\n const dir = path.dirname(filePath);\n for (const stmt of program.body || []) {\n // `declare class Foo` (top-level)\n if (stmt.type === 'ClassDeclaration' && stmt.id?.name) {\n map.set(stmt.id.name, importPath);\n continue;\n }\n\n // `export declare class Foo` / `export class Foo` /\n // `export { A, B as C } from '...'` / `export { A, B }`\n if (stmt.type === 'ExportNamedDeclaration') {\n if (\n stmt.declaration?.type === 'ClassDeclaration' &&\n stmt.declaration.id?.name\n ) {\n map.set(stmt.declaration.id.name, importPath);\n }\n for (const spec of stmt.specifiers || []) {\n // ExportSpecifier: { local, exported }\n const exportedNode = spec.exported;\n const exportedName =\n exportedNode?.type === 'Identifier'\n ? exportedNode.name\n : exportedNode?.type === 'Literal'\n ? exportedNode.value\n : undefined;\n if (typeof exportedName === 'string') {\n map.set(exportedName, importPath);\n }\n }\n continue;\n }\n\n // `export * from './rel'` and `export * as Ns from './rel'`\n if (stmt.type === 'ExportAllDeclaration') {\n const rel: string | undefined = stmt.source?.value;\n if (!rel || !rel.startsWith('.')) continue;\n // TypeScript preserves the original specifier text in emitted\n // `.d.ts` files, so NodeNext-style packages keep their `.js`\n // (or `.mjs`) extensions in re-exports — but the actual\n // declaration is at `foo.d.ts` / `foo/index.d.ts`. Strip the\n // ESM extension before probing.\n const normalizedRel = rel.replace(/\\.(?:js|mjs)$/u, '');\n const candidates = [\n path.resolve(dir, normalizedRel + '.d.ts'),\n path.resolve(dir, normalizedRel, 'index.d.ts'),\n ];\n for (const candidate of candidates) {\n if (fs.existsSync(candidate)) {\n collectExportedClassesFromDts(candidate, importPath, map, visited);\n break;\n }\n }\n continue;\n }\n }\n}\n\n/**\n * Derive a sub-entry import path from a .d.ts file's location relative to the\n * package root. This handles older Angular packages that keep .d.ts files in\n * subdirectories (e.g. `@angular/material/tabs/index.d.ts`) instead of a\n * top-level `types/` folder.\n *\n * Returns `undefined` when no sub-entry can be determined (e.g. file is at the\n * package root, inside `types/`, or in a non-entry directory).\n */\nfunction subEntryFromFilePath(\n packageName: string,\n pkgDir: string,\n filePath: string,\n): string | undefined {\n const NON_ENTRY_DIRS = new Set([\n 'types',\n 'fesm2022',\n 'fesm2020',\n 'fesm2015',\n 'esm2022',\n 'esm2020',\n 'esm2015',\n 'bundles',\n 'schematics',\n 'node_modules',\n ]);\n const rel = path.relative(pkgDir, filePath);\n const segments = rel.split(path.sep);\n // File directly in pkgDir (no subdirectory) → no sub-entry\n if (segments.length < 2) return undefined;\n const firstDir = segments[0];\n // Skip internal/build directories and chunk files\n if (NON_ENTRY_DIRS.has(firstDir) || firstDir.startsWith('_'))\n return undefined;\n return packageName + '/' + firstDir;\n}\n\n/**\n * Parse a source file with OXC and return the set of bare-specifier package\n * names it imports (e.g. \"@angular/router\", \"rxjs\"). Relative imports are\n * skipped.\n */\nexport function collectImportedPackages(\n code: string,\n fileName: string,\n program?: ReturnType<typeof parseSync>['program'],\n): Set<string> {\n const packages = new Set<string>();\n program ??= parseSync(fileName, code).program;\n\n for (const stmt of program.body) {\n if (stmt.type !== 'ImportDeclaration') continue;\n const specifier: string = stmt.source?.value;\n if (!specifier || specifier.startsWith('.')) continue;\n\n const parts = specifier.split('/');\n packages.add(\n specifier.startsWith('@') ? parts.slice(0, 2).join('/') : parts[0],\n );\n }\n\n return packages;\n}\n\n/**\n * Parse a source file with OXC and return the relative-path specifiers it\n * re-exports via `export * from './x'`, `export * as Ns from './x'`, or\n * `export { … } from './x'`. Bare-specifier re-exports are skipped.\n *\n * Used by the analog Vite plugin to walk library entry barrels at startup\n * (e.g. `helm/select/src/index.ts` → `./lib/hlm-select`) so the underlying\n * directive classes land in the registry before any consumer is compiled.\n */\nexport function collectRelativeReExports(\n code: string,\n fileName: string,\n program?: ReturnType<typeof parseSync>['program'],\n): string[] {\n if (!program) {\n try {\n program = parseSync(fileName, code).program;\n } catch {\n return [];\n }\n }\n const result: string[] = [];\n for (const stmt of program.body || []) {\n if (\n stmt.type !== 'ExportAllDeclaration' &&\n stmt.type !== 'ExportNamedDeclaration'\n ) {\n continue;\n }\n // ExportNamedDeclaration without `source` is `export { x }` (no\n // re-export), which we don't care about here.\n const specifier: string | undefined = stmt.source?.value;\n if (!specifier || !specifier.startsWith('.')) continue;\n result.push(specifier);\n }\n return result;\n}\n\n/**\n * Parse a source file with OXC and return every module specifier it imports or\n * re-exports from (relative AND bare), including `import`, `export * from`, and\n * `export { … } from`. Used to walk the transitive import graph at startup so\n * the registry contains components/directives/pipes/modules from files not\n * directly listed in tsconfig `files`/`include` (transitively-imported app\n * sources) or behind wildcard `paths` (workspace libraries).\n */\nexport function collectAllImports(\n code: string,\n fileName: string,\n program?: ReturnType<typeof parseSync>['program'],\n): string[] {\n if (!program) {\n try {\n program = parseSync(fileName, code).program;\n } catch {\n return [];\n }\n }\n const result: string[] = [];\n for (const stmt of program.body || []) {\n if (\n stmt.type === 'ImportDeclaration' ||\n stmt.type === 'ExportAllDeclaration' ||\n stmt.type === 'ExportNamedDeclaration'\n ) {\n const specifier: string | undefined = stmt.source?.value;\n if (specifier) result.push(specifier);\n }\n }\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction visitStatements(\n stmts: any[],\n fileName: string,\n entries: RegistryEntry[],\n) {\n for (const stmt of stmts) {\n // Unwrap exports: `export declare class ...` / `export default class ...`\n const decl =\n stmt.type === 'ExportNamedDeclaration' ||\n stmt.type === 'ExportDefaultDeclaration'\n ? stmt.declaration\n : stmt;\n\n if (!decl) continue;\n\n // Recurse into `declare module \"...\" { ... }` blocks\n if (decl.type === 'TSModuleDeclaration' && decl.body?.body) {\n visitStatements(decl.body.body, fileName, entries);\n continue;\n }\n\n if (decl.type !== 'ClassDeclaration' || !decl.id?.name) continue;\n const className: string = decl.id.name;\n const members: any[] = decl.body?.body || [];\n\n for (const member of members) {\n if (member.type !== 'PropertyDefinition' || !member.static) continue;\n const propName: string | undefined = member.key?.name;\n\n // Read the type annotation: e.g. `i0.ɵɵDirectiveDeclaration<...>`\n const typeRef = member.typeAnnotation?.typeAnnotation;\n if (!typeRef || typeRef.type !== 'TSTypeReference') continue;\n\n const typeName = qualifiedName(typeRef.typeName);\n const typeParams: any[] | undefined = typeRef.typeArguments?.params;\n\n if (\n (propName === 'ɵdir' || propName === 'ɵcmp') &&\n (typeName.includes('DirectiveDeclaration') ||\n typeName.includes('ComponentDeclaration')) &&\n typeParams &&\n typeParams.length >= 5\n ) {\n const selector = literalString(typeParams[1]);\n if (!selector) continue;\n\n const inputs = extractInputs(typeParams[3]);\n const outputs = extractOutputs(typeParams[4]);\n\n entries.push({\n selector: selector.split(',')[0].trim(),\n kind: propName === 'ɵcmp' ? 'component' : 'directive',\n fileName,\n className,\n ...(Object.keys(inputs).length > 0 ? { inputs } : {}),\n ...(Object.keys(outputs).length > 0 ? { outputs } : {}),\n });\n } else if (\n propName === 'ɵpipe' &&\n typeName.includes('PipeDeclaration') &&\n typeParams &&\n typeParams.length >= 2\n ) {\n const pipeName = literalString(typeParams[1]);\n if (!pipeName) continue;\n\n entries.push({\n selector: pipeName,\n kind: 'pipe',\n pipeName,\n fileName,\n className,\n });\n } else if (\n propName === 'ɵmod' &&\n typeName.includes('NgModuleDeclaration') &&\n typeParams &&\n typeParams.length >= 4\n ) {\n // ɵɵNgModuleDeclaration<Module, Declarations, Imports, Exports>\n // Extract exported class names from the 4th type param (index 3).\n const exportsParam = typeParams[3];\n const exportedNames: string[] = [];\n if (exportsParam?.type === 'TSTupleType' && exportsParam.elementTypes) {\n for (const el of exportsParam.elementTypes) {\n if (\n el.type === 'TSTypeQuery' &&\n el.exprName?.type === 'Identifier'\n ) {\n exportedNames.push(el.exprName.name);\n } else if (\n el.type === 'TSTypeQuery' &&\n el.exprName?.type === 'TSQualifiedName'\n ) {\n // e.g. typeof i2.BidiModule → extract \"BidiModule\"\n const right = el.exprName.right;\n if (right?.type === 'Identifier') {\n exportedNames.push(right.name);\n }\n }\n }\n }\n entries.push({\n selector: className,\n kind: 'ngmodule',\n exports: exportedNames,\n fileName,\n className,\n });\n }\n }\n }\n}\n\n/**\n * Extract inputs from the type-argument at position [3].\n *\n * Handles two formats:\n * v16+: { \"prop\": { \"alias\": \"binding\"; \"required\": false; \"isSignal\"?: true } }\n * pre-v16: { \"prop\": \"binding\" }\n */\nfunction extractInputs(node: any): Record<string, RegistryInput> {\n const inputs: Record<string, RegistryInput> = {};\n if (node?.type !== 'TSTypeLiteral') return inputs;\n\n for (const member of node.members) {\n if (member.type !== 'TSPropertySignature') continue;\n const propName = keyName(member.key);\n const innerType = member.typeAnnotation?.typeAnnotation;\n if (!propName || !innerType) continue;\n\n if (innerType.type === 'TSTypeLiteral') {\n // v16+ object format\n let alias = propName;\n let required = false;\n let isSignal = false;\n\n for (const inner of innerType.members) {\n if (inner.type !== 'TSPropertySignature') continue;\n const key = keyName(inner.key);\n const val = inner.typeAnnotation?.typeAnnotation;\n if (!key || !val) continue;\n\n if (key === 'alias') {\n alias = literalString(val) ?? propName;\n } else if (key === 'required') {\n required = literalBoolean(val) === true;\n } else if (key === 'isSignal') {\n isSignal = literalBoolean(val) === true;\n }\n }\n\n inputs[propName] = {\n classPropertyName: propName,\n bindingPropertyName: alias,\n isSignal,\n required,\n };\n } else {\n // pre-v16 string format\n const alias = literalString(innerType);\n if (alias) {\n inputs[propName] = {\n classPropertyName: propName,\n bindingPropertyName: alias,\n isSignal: false,\n required: false,\n };\n }\n }\n }\n\n return inputs;\n}\n\n/**\n * Extract outputs from the type-argument at position [4].\n * Format: { \"propName\": \"eventName\" }\n */\nfunction extractOutputs(node: any): Record<string, string> {\n const outputs: Record<string, string> = {};\n if (node?.type !== 'TSTypeLiteral') return outputs;\n\n for (const member of node.members) {\n if (member.type !== 'TSPropertySignature') continue;\n const propName = keyName(member.key);\n const val = member.typeAnnotation?.typeAnnotation;\n if (!propName || !val) continue;\n\n const value = literalString(val);\n if (value) outputs[propName] = value;\n }\n\n return outputs;\n}\n\n/** Get the string name from a property key (Identifier or Literal). */\nfunction keyName(key: any): string | undefined {\n if (!key) return undefined;\n if (key.type === 'Identifier') return key.name;\n if (key.type === 'Literal' && typeof key.value === 'string') return key.value;\n return undefined;\n}\n\n/** Build a dotted name from an Identifier or TSQualifiedName. */\nfunction qualifiedName(node: any): string {\n if (!node) return '';\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'TSQualifiedName')\n return qualifiedName(node.left) + '.' + qualifiedName(node.right);\n return '';\n}\n\n/** Extract a string value from a TSLiteralType node. */\nfunction literalString(node: any): string | undefined {\n if (\n node?.type === 'TSLiteralType' &&\n node.literal?.type === 'Literal' &&\n typeof node.literal.value === 'string'\n ) {\n return node.literal.value;\n }\n return undefined;\n}\n\n/** Extract a boolean value from a TSLiteralType node. */\nfunction literalBoolean(node: any): boolean | undefined {\n if (\n node?.type === 'TSLiteralType' &&\n node.literal?.type === 'Literal' &&\n typeof node.literal.value === 'boolean'\n ) {\n return node.literal.value;\n }\n return undefined;\n}\n\n/** Recursively collect all .d.ts files under a directory. */\nfunction collectDtsFiles(dir: string): string[] {\n const results: string[] = [];\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch {\n return results;\n }\n\n for (const entry of entries) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory() && entry.name !== 'node_modules') {\n results.push(...collectDtsFiles(full));\n } else if (entry.isFile() && entry.name.endsWith('.d.ts')) {\n results.push(full);\n }\n }\n\n return results;\n}\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export { compile, type CompileResult, type CompileOptions } from "./compile.js";
2
+ export { ANGULAR_DECORATORS, ANGULAR_DECORATOR_CALL_RE } from "./constants.js";
2
3
  export { scanFile, type RegistryEntry, type ComponentRegistry } from "./registry.js";
3
- export { scanDtsFile, scanPackageDts, collectImportedPackages, collectRelativeReExports } from "./dts-reader.js";
4
+ export { scanDtsFile, scanPackageDts, collectImportedPackages, collectRelativeReExports, collectAllImports } from "./dts-reader.js";
4
5
  export { jitTransform, type JitTransformResult } from "./jit-transform.js";
5
6
  export { generateHmrCode } from "./hmr.js";
6
7
  export { inlineResourceUrls, extractInlineStyles } from "./resource-inliner.js";
@@ -1,3 +1,4 @@
1
+ import "./constants.js";
1
2
  import "./debug.js";
2
3
  import "./compile.js";
3
4
  import "./registry.js";
@@ -44,7 +44,7 @@ function findAllClasses(node) {
44
44
  function jitTransform(sourceCode, fileName) {
45
45
  const { program } = parseSync(fileName, sourceCode);
46
46
  const ms = new MagicString(sourceCode, { filename: fileName });
47
- const typeOnlyImports = detectTypeOnlyImportNames(sourceCode);
47
+ const typeOnlyImports = detectTypeOnlyImportNames(sourceCode, program);
48
48
  let hasAngularClass = false;
49
49
  const allClasses = findAllClasses(program.body);
50
50
  const allEmittedStatements = [];
@@ -1 +1 @@
1
- {"version":3,"file":"jit-transform.js","names":[],"sources":["../../../../src/lib/compiler/jit-transform.ts"],"sourcesContent":["import { parseSync } from 'oxc-parser';\nimport MagicString from 'magic-string';\nimport { detectTypeOnlyImportNames } from './type-elision.js';\nimport { buildCtorParameters, buildPropDecorators } from './jit-metadata.js';\nimport { ANGULAR_DECORATORS, FIELD_DECORATORS } from './constants.js';\n\nexport interface JitTransformResult {\n code: string;\n map: any;\n}\n\n/**\n * Recursively find all ClassDeclaration nodes in an OXC AST.\n * Handles top-level, exported, and nested classes (e.g. inside function scopes).\n */\nfunction findAllClasses(node: any): any[] {\n const result: any[] = [];\n if (!node || typeof node !== 'object') return result;\n if (Array.isArray(node)) {\n for (const item of node) {\n result.push(...findAllClasses(item));\n }\n return result;\n }\n if (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') {\n result.push(node);\n }\n for (const key of Object.keys(node)) {\n if (\n key === 'type' ||\n key === 'start' ||\n key === 'end' ||\n key === 'range' ||\n key === 'loc'\n )\n continue;\n result.push(...findAllClasses(node[key]));\n }\n return result;\n}\n\n/**\n * JIT transform for Angular files.\n *\n * Converts Angular decorators to static metadata arrays that Angular's\n * runtime JIT compiler reads via ReflectionCapabilities:\n *\n * - Class.decorators = [{ type: Component, args: [{...}] }]\n * - Class.ctorParameters = () => [{ type: ServiceA, decorators: [{type: Optional}] }]\n * - Class.propDecorators = { name: [{ type: Input }], ... }\n *\n * Also emits ɵfac (factory function) with constructor DI and downlevels\n * signal APIs (input, model, output, viewChild, etc.) to propDecorators.\n *\n * No template compilation — Angular's JIT compiler handles that at runtime.\n * Requires `import '@angular/compiler'` in main.ts for the browser JIT.\n *\n * Uses OXC's native Rust parser instead of TypeScript's parser for ~1.5x\n * faster parsing and source-position slicing instead of getText() calls.\n */\nexport function jitTransform(\n sourceCode: string,\n fileName: string,\n): JitTransformResult {\n const { program } = parseSync(fileName, sourceCode);\n const ms = new MagicString(sourceCode, { filename: fileName });\n const typeOnlyImports = detectTypeOnlyImportNames(sourceCode);\n let hasAngularClass = false;\n\n const allClasses = findAllClasses(program.body);\n\n // Accumulates every class's emitted statements so the post-loop import\n // detection (missing field-decorator imports) can scan all of them.\n // The statements themselves are inserted in-scope after each class via\n // `ms.appendLeft(node.end, ...)` rather than dumped at the end of the\n // file — a class declared inside a function/callback scope (e.g. a host\n // `@Component` defined inside a `describe(...)`/`it(...)` block in a test)\n // is not in scope at module end, so a file-end emit would reference an\n // undefined name (#2360).\n const allEmittedStatements: string[] = [];\n let importCounter = 0;\n const resourceImports: string[] = [];\n let needsJitImport = false;\n\n for (const node of allClasses) {\n const decorators: any[] = node.decorators || [];\n\n const angularDecs = decorators.filter((dec: any) => {\n const expr = dec.expression;\n if (!expr || expr.type !== 'CallExpression') return false;\n const name: string | undefined = expr.callee?.name;\n // Keep @Injectable and @Service on the class — their decorator\n // functions self-register ɵprov/ɵfac at class definition time and\n // there is no JIT compile entry point to call instead.\n if (name === 'Injectable' || name === 'Service') return false;\n return name !== undefined && ANGULAR_DECORATORS.has(name);\n });\n if (angularDecs.length === 0) continue;\n\n const className: string | undefined = node.id?.name;\n if (!className) continue;\n hasAngularClass = true;\n\n // Statements emitted for THIS class. Inserted directly after the class\n // body (see end of loop) so they run in the class's own lexical scope.\n const classStatements: string[] = [];\n\n // 1. Remove Angular decorators from source\n for (const dec of angularDecs) {\n const start: number = dec.start;\n let trimEnd: number = dec.end;\n while (trimEnd < sourceCode.length && /\\s/.test(sourceCode[trimEnd]))\n trimEnd++;\n ms.remove(start, trimEnd);\n }\n\n // 2. Emit Class.decorators = [{ type: DecName, args: [...] }]\n // For @Component: convert templateUrl/styleUrl/styleUrls to ESM imports\n const decoratorMeta: { name: string; argsText: string }[] = [];\n const decoratorEntries = angularDecs.map((dec: any) => {\n const call = dec.expression;\n const decName: string = call.callee.name;\n const args: any[] = call.arguments || [];\n\n if (\n args.length > 0 &&\n decName === 'Component' &&\n args[0].type === 'ObjectExpression'\n ) {\n // Rewrite component metadata: convert external resources to imports\n const obj = args[0];\n const rewrittenProps: string[] = [];\n\n for (const prop of obj.properties) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property') {\n rewrittenProps.push(sourceCode.slice(prop.start, prop.end));\n continue;\n }\n const key: string = prop.key?.name || prop.key?.value;\n const val = prop.value;\n\n if (\n key === 'templateUrl' &&\n (val?.type === 'StringLiteral' ||\n (val?.type === 'Literal' && typeof val.value === 'string'))\n ) {\n // templateUrl: './foo.html' → template: _tpl0 (with import)\n const varName = `_jit_tpl_${importCounter++}`;\n resourceImports.push(`import ${varName} from '${val.value}?raw';`);\n rewrittenProps.push(`template: ${varName}`);\n } else if (\n key === 'styleUrl' &&\n (val?.type === 'StringLiteral' ||\n (val?.type === 'Literal' && typeof val.value === 'string'))\n ) {\n // styleUrl: './foo.scss' → styles: [_style0]\n const varName = `_jit_style_${importCounter++}`;\n resourceImports.push(\n `import ${varName} from '${val.value}?inline';`,\n );\n rewrittenProps.push(`styles: [${varName}]`);\n } else if (key === 'styleUrls' && val?.type === 'ArrayExpression') {\n // styleUrls: ['./a.scss', './b.css'] → styles: [_style0, _style1]\n const vars: string[] = [];\n for (const el of val.elements) {\n if (\n el?.type === 'StringLiteral' ||\n (el?.type === 'Literal' && typeof el.value === 'string')\n ) {\n const varName = `_jit_style_${importCounter++}`;\n resourceImports.push(\n `import ${varName} from '${el.value}?inline';`,\n );\n vars.push(varName);\n }\n }\n rewrittenProps.push(`styles: [${vars.join(', ')}]`);\n } else {\n rewrittenProps.push(sourceCode.slice(prop.start, prop.end));\n }\n }\n const rewrittenArgsText = `{${rewrittenProps.join(', ')}}`;\n decoratorMeta.push({ name: decName, argsText: rewrittenArgsText });\n return `{ type: ${decName}, args: [${rewrittenArgsText}] }`;\n }\n\n if (args.length > 0) {\n const argsText = args\n .map((a: any) => sourceCode.slice(a.start, a.end))\n .join(', ');\n decoratorMeta.push({ name: decName, argsText });\n return `{ type: ${decName}, args: [${argsText}] }`;\n }\n decoratorMeta.push({ name: decName, argsText: '{}' });\n return `{ type: ${decName} }`;\n });\n classStatements.push(\n `${className}.decorators = [${decoratorEntries.join(', ')}];`,\n );\n\n // 2b. Trigger JIT compilation with the rewritten decorator metadata\n for (const dm of decoratorMeta) {\n needsJitImport = true;\n switch (dm.name) {\n case 'Component':\n classStatements.push(\n `_jitCompileComponent(${className}, ${dm.argsText});`,\n );\n break;\n case 'Directive':\n classStatements.push(\n `_jitCompileDirective(${className}, ${dm.argsText});`,\n );\n break;\n case 'Pipe':\n classStatements.push(\n `_jitCompilePipe(${className}, ${dm.argsText});`,\n );\n break;\n case 'NgModule':\n classStatements.push(\n `_jitCompileNgModule(${className}, ${dm.argsText});`,\n );\n break;\n }\n }\n\n // 3. Emit Class.ctorParameters for constructor DI\n const ctorParams = buildCtorParameters(node, sourceCode, typeOnlyImports);\n if (ctorParams) {\n classStatements.push(\n `${className}.ctorParameters = () => [${ctorParams}];`,\n );\n }\n\n // 4. Emit Class.propDecorators for field decorators + signal APIs\n const propDecorators = buildPropDecorators(node, sourceCode);\n if (propDecorators) {\n classStatements.push(`${className}.propDecorators = ${propDecorators};`);\n }\n\n // 5. Remove member and parameter decorators from source now that\n // they have been extracted into static metadata above.\n const members: any[] = node.body?.body || [];\n for (const member of members) {\n const memberDecs: any[] = member.decorators || [];\n for (const dec of memberDecs) {\n const start: number = dec.start;\n let trimEnd: number = dec.end;\n while (trimEnd < sourceCode.length && /\\s/.test(sourceCode[trimEnd]))\n trimEnd++;\n ms.remove(start, trimEnd);\n }\n // Constructor parameter decorators\n if (member.type === 'MethodDefinition' && member.kind === 'constructor') {\n const params: any[] =\n member.value?.params?.items || member.value?.params || [];\n for (const param of params) {\n // Decorators may live on the TSParameterProperty wrapper or the inner param\n const allParamDecs: any[] = [\n ...(param.decorators || []),\n ...(param.type === 'TSParameterProperty' &&\n param.parameter?.decorators\n ? param.parameter.decorators\n : []),\n ];\n for (const dec of allParamDecs) {\n const start: number = dec.start;\n let trimEnd: number = dec.end;\n while (\n trimEnd < sourceCode.length &&\n /\\s/.test(sourceCode[trimEnd])\n )\n trimEnd++;\n ms.remove(start, trimEnd);\n }\n }\n }\n }\n\n // Insert this class's metadata statements directly after the class body\n // so they execute in the class's own lexical scope. `node.end` is the\n // position just past the closing brace (decorators were stripped before\n // `node.start`), so for a top-level class this is module scope and for a\n // class nested in a function/callback it is that enclosing scope —\n // keeping the class identifier in scope either way (#2360).\n if (classStatements.length > 0) {\n allEmittedStatements.push(...classStatements);\n ms.appendLeft(node.end, '\\n' + classStatements.join('\\n') + '\\n');\n }\n }\n\n if (!hasAngularClass) {\n return { code: sourceCode, map: null };\n }\n\n // Prepend ESM imports for external templates/styles\n if (resourceImports.length > 0) {\n ms.prepend(resourceImports.join('\\n') + '\\n');\n }\n\n // Prepend imports for decorator classes referenced by signal API downleveling\n // (e.g. input() → {type: Input}, model() → {type: Input} + {type: Output})\n const existingImports = new Set<string>();\n for (const stmt of program.body) {\n if (\n (stmt as any).type === 'ImportDeclaration' &&\n (stmt as any).source?.value === '@angular/core'\n ) {\n for (const spec of (stmt as any).specifiers || []) {\n if (spec.type === 'ImportSpecifier') {\n existingImports.add(spec.local?.name || spec.imported?.name);\n }\n }\n }\n }\n const allPostCode = allEmittedStatements.join('\\n');\n const missingDecorators: string[] = [];\n for (const dec of FIELD_DECORATORS) {\n if (allPostCode.includes(`type: ${dec}`) && !existingImports.has(dec)) {\n missingDecorators.push(dec);\n }\n }\n if (missingDecorators.length > 0) {\n ms.prepend(\n `import { ${missingDecorators.join(', ')} } from '@angular/core';\\n`,\n );\n }\n\n // Prepend JIT compiler imports\n if (needsJitImport) {\n ms.prepend(\n `import { ɵcompileComponent as _jitCompileComponent, ɵcompileDirective as _jitCompileDirective, ɵcompilePipe as _jitCompilePipe, ɵcompileNgModule as _jitCompileNgModule } from '@angular/core';\\n`,\n );\n }\n\n const map = ms.generateMap({\n source: fileName,\n file: fileName + '.js',\n includeContent: true,\n hires: 'boundary',\n });\n\n return { code: ms.toString(), map };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"jit-transform.js","names":[],"sources":["../../../../src/lib/compiler/jit-transform.ts"],"sourcesContent":["import { parseSync } from 'oxc-parser';\nimport MagicString from 'magic-string';\nimport { detectTypeOnlyImportNames } from './type-elision.js';\nimport { buildCtorParameters, buildPropDecorators } from './jit-metadata.js';\nimport { ANGULAR_DECORATORS, FIELD_DECORATORS } from './constants.js';\n\nexport interface JitTransformResult {\n code: string;\n map: any;\n}\n\n/**\n * Recursively find all ClassDeclaration nodes in an OXC AST.\n * Handles top-level, exported, and nested classes (e.g. inside function scopes).\n */\nfunction findAllClasses(node: any): any[] {\n const result: any[] = [];\n if (!node || typeof node !== 'object') return result;\n if (Array.isArray(node)) {\n for (const item of node) {\n result.push(...findAllClasses(item));\n }\n return result;\n }\n if (node.type === 'ClassDeclaration' || node.type === 'ClassExpression') {\n result.push(node);\n }\n for (const key of Object.keys(node)) {\n if (\n key === 'type' ||\n key === 'start' ||\n key === 'end' ||\n key === 'range' ||\n key === 'loc'\n )\n continue;\n result.push(...findAllClasses(node[key]));\n }\n return result;\n}\n\n/**\n * JIT transform for Angular files.\n *\n * Converts Angular decorators to static metadata arrays that Angular's\n * runtime JIT compiler reads via ReflectionCapabilities:\n *\n * - Class.decorators = [{ type: Component, args: [{...}] }]\n * - Class.ctorParameters = () => [{ type: ServiceA, decorators: [{type: Optional}] }]\n * - Class.propDecorators = { name: [{ type: Input }], ... }\n *\n * Also emits ɵfac (factory function) with constructor DI and downlevels\n * signal APIs (input, model, output, viewChild, etc.) to propDecorators.\n *\n * No template compilation — Angular's JIT compiler handles that at runtime.\n * Requires `import '@angular/compiler'` in main.ts for the browser JIT.\n *\n * Uses OXC's native Rust parser instead of TypeScript's parser for ~1.5x\n * faster parsing and source-position slicing instead of getText() calls.\n */\nexport function jitTransform(\n sourceCode: string,\n fileName: string,\n): JitTransformResult {\n const { program } = parseSync(fileName, sourceCode);\n const ms = new MagicString(sourceCode, { filename: fileName });\n const typeOnlyImports = detectTypeOnlyImportNames(sourceCode, program);\n let hasAngularClass = false;\n\n const allClasses = findAllClasses(program.body);\n\n // Accumulates every class's emitted statements so the post-loop import\n // detection (missing field-decorator imports) can scan all of them.\n // The statements themselves are inserted in-scope after each class via\n // `ms.appendLeft(node.end, ...)` rather than dumped at the end of the\n // file — a class declared inside a function/callback scope (e.g. a host\n // `@Component` defined inside a `describe(...)`/`it(...)` block in a test)\n // is not in scope at module end, so a file-end emit would reference an\n // undefined name (#2360).\n const allEmittedStatements: string[] = [];\n let importCounter = 0;\n const resourceImports: string[] = [];\n let needsJitImport = false;\n\n for (const node of allClasses) {\n const decorators: any[] = node.decorators || [];\n\n const angularDecs = decorators.filter((dec: any) => {\n const expr = dec.expression;\n if (!expr || expr.type !== 'CallExpression') return false;\n const name: string | undefined = expr.callee?.name;\n // Keep @Injectable and @Service on the class — their decorator\n // functions self-register ɵprov/ɵfac at class definition time and\n // there is no JIT compile entry point to call instead.\n if (name === 'Injectable' || name === 'Service') return false;\n return name !== undefined && ANGULAR_DECORATORS.has(name);\n });\n if (angularDecs.length === 0) continue;\n\n const className: string | undefined = node.id?.name;\n if (!className) continue;\n hasAngularClass = true;\n\n // Statements emitted for THIS class. Inserted directly after the class\n // body (see end of loop) so they run in the class's own lexical scope.\n const classStatements: string[] = [];\n\n // 1. Remove Angular decorators from source\n for (const dec of angularDecs) {\n const start: number = dec.start;\n let trimEnd: number = dec.end;\n while (trimEnd < sourceCode.length && /\\s/.test(sourceCode[trimEnd]))\n trimEnd++;\n ms.remove(start, trimEnd);\n }\n\n // 2. Emit Class.decorators = [{ type: DecName, args: [...] }]\n // For @Component: convert templateUrl/styleUrl/styleUrls to ESM imports\n const decoratorMeta: { name: string; argsText: string }[] = [];\n const decoratorEntries = angularDecs.map((dec: any) => {\n const call = dec.expression;\n const decName: string = call.callee.name;\n const args: any[] = call.arguments || [];\n\n if (\n args.length > 0 &&\n decName === 'Component' &&\n args[0].type === 'ObjectExpression'\n ) {\n // Rewrite component metadata: convert external resources to imports\n const obj = args[0];\n const rewrittenProps: string[] = [];\n\n for (const prop of obj.properties) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property') {\n rewrittenProps.push(sourceCode.slice(prop.start, prop.end));\n continue;\n }\n const key: string = prop.key?.name || prop.key?.value;\n const val = prop.value;\n\n if (\n key === 'templateUrl' &&\n (val?.type === 'StringLiteral' ||\n (val?.type === 'Literal' && typeof val.value === 'string'))\n ) {\n // templateUrl: './foo.html' → template: _tpl0 (with import)\n const varName = `_jit_tpl_${importCounter++}`;\n resourceImports.push(`import ${varName} from '${val.value}?raw';`);\n rewrittenProps.push(`template: ${varName}`);\n } else if (\n key === 'styleUrl' &&\n (val?.type === 'StringLiteral' ||\n (val?.type === 'Literal' && typeof val.value === 'string'))\n ) {\n // styleUrl: './foo.scss' → styles: [_style0]\n const varName = `_jit_style_${importCounter++}`;\n resourceImports.push(\n `import ${varName} from '${val.value}?inline';`,\n );\n rewrittenProps.push(`styles: [${varName}]`);\n } else if (key === 'styleUrls' && val?.type === 'ArrayExpression') {\n // styleUrls: ['./a.scss', './b.css'] → styles: [_style0, _style1]\n const vars: string[] = [];\n for (const el of val.elements) {\n if (\n el?.type === 'StringLiteral' ||\n (el?.type === 'Literal' && typeof el.value === 'string')\n ) {\n const varName = `_jit_style_${importCounter++}`;\n resourceImports.push(\n `import ${varName} from '${el.value}?inline';`,\n );\n vars.push(varName);\n }\n }\n rewrittenProps.push(`styles: [${vars.join(', ')}]`);\n } else {\n rewrittenProps.push(sourceCode.slice(prop.start, prop.end));\n }\n }\n const rewrittenArgsText = `{${rewrittenProps.join(', ')}}`;\n decoratorMeta.push({ name: decName, argsText: rewrittenArgsText });\n return `{ type: ${decName}, args: [${rewrittenArgsText}] }`;\n }\n\n if (args.length > 0) {\n const argsText = args\n .map((a: any) => sourceCode.slice(a.start, a.end))\n .join(', ');\n decoratorMeta.push({ name: decName, argsText });\n return `{ type: ${decName}, args: [${argsText}] }`;\n }\n decoratorMeta.push({ name: decName, argsText: '{}' });\n return `{ type: ${decName} }`;\n });\n classStatements.push(\n `${className}.decorators = [${decoratorEntries.join(', ')}];`,\n );\n\n // 2b. Trigger JIT compilation with the rewritten decorator metadata\n for (const dm of decoratorMeta) {\n needsJitImport = true;\n switch (dm.name) {\n case 'Component':\n classStatements.push(\n `_jitCompileComponent(${className}, ${dm.argsText});`,\n );\n break;\n case 'Directive':\n classStatements.push(\n `_jitCompileDirective(${className}, ${dm.argsText});`,\n );\n break;\n case 'Pipe':\n classStatements.push(\n `_jitCompilePipe(${className}, ${dm.argsText});`,\n );\n break;\n case 'NgModule':\n classStatements.push(\n `_jitCompileNgModule(${className}, ${dm.argsText});`,\n );\n break;\n }\n }\n\n // 3. Emit Class.ctorParameters for constructor DI\n const ctorParams = buildCtorParameters(node, sourceCode, typeOnlyImports);\n if (ctorParams) {\n classStatements.push(\n `${className}.ctorParameters = () => [${ctorParams}];`,\n );\n }\n\n // 4. Emit Class.propDecorators for field decorators + signal APIs\n const propDecorators = buildPropDecorators(node, sourceCode);\n if (propDecorators) {\n classStatements.push(`${className}.propDecorators = ${propDecorators};`);\n }\n\n // 5. Remove member and parameter decorators from source now that\n // they have been extracted into static metadata above.\n const members: any[] = node.body?.body || [];\n for (const member of members) {\n const memberDecs: any[] = member.decorators || [];\n for (const dec of memberDecs) {\n const start: number = dec.start;\n let trimEnd: number = dec.end;\n while (trimEnd < sourceCode.length && /\\s/.test(sourceCode[trimEnd]))\n trimEnd++;\n ms.remove(start, trimEnd);\n }\n // Constructor parameter decorators\n if (member.type === 'MethodDefinition' && member.kind === 'constructor') {\n const params: any[] =\n member.value?.params?.items || member.value?.params || [];\n for (const param of params) {\n // Decorators may live on the TSParameterProperty wrapper or the inner param\n const allParamDecs: any[] = [\n ...(param.decorators || []),\n ...(param.type === 'TSParameterProperty' &&\n param.parameter?.decorators\n ? param.parameter.decorators\n : []),\n ];\n for (const dec of allParamDecs) {\n const start: number = dec.start;\n let trimEnd: number = dec.end;\n while (\n trimEnd < sourceCode.length &&\n /\\s/.test(sourceCode[trimEnd])\n )\n trimEnd++;\n ms.remove(start, trimEnd);\n }\n }\n }\n }\n\n // Insert this class's metadata statements directly after the class body\n // so they execute in the class's own lexical scope. `node.end` is the\n // position just past the closing brace (decorators were stripped before\n // `node.start`), so for a top-level class this is module scope and for a\n // class nested in a function/callback it is that enclosing scope —\n // keeping the class identifier in scope either way (#2360).\n if (classStatements.length > 0) {\n allEmittedStatements.push(...classStatements);\n ms.appendLeft(node.end, '\\n' + classStatements.join('\\n') + '\\n');\n }\n }\n\n if (!hasAngularClass) {\n return { code: sourceCode, map: null };\n }\n\n // Prepend ESM imports for external templates/styles\n if (resourceImports.length > 0) {\n ms.prepend(resourceImports.join('\\n') + '\\n');\n }\n\n // Prepend imports for decorator classes referenced by signal API downleveling\n // (e.g. input() → {type: Input}, model() → {type: Input} + {type: Output})\n const existingImports = new Set<string>();\n for (const stmt of program.body) {\n if (\n (stmt as any).type === 'ImportDeclaration' &&\n (stmt as any).source?.value === '@angular/core'\n ) {\n for (const spec of (stmt as any).specifiers || []) {\n if (spec.type === 'ImportSpecifier') {\n existingImports.add(spec.local?.name || spec.imported?.name);\n }\n }\n }\n }\n const allPostCode = allEmittedStatements.join('\\n');\n const missingDecorators: string[] = [];\n for (const dec of FIELD_DECORATORS) {\n if (allPostCode.includes(`type: ${dec}`) && !existingImports.has(dec)) {\n missingDecorators.push(dec);\n }\n }\n if (missingDecorators.length > 0) {\n ms.prepend(\n `import { ${missingDecorators.join(', ')} } from '@angular/core';\\n`,\n );\n }\n\n // Prepend JIT compiler imports\n if (needsJitImport) {\n ms.prepend(\n `import { ɵcompileComponent as _jitCompileComponent, ɵcompileDirective as _jitCompileDirective, ɵcompilePipe as _jitCompilePipe, ɵcompileNgModule as _jitCompileNgModule } from '@angular/core';\\n`,\n );\n }\n\n const map = ms.generateMap({\n source: fileName,\n file: fileName + '.js',\n includeContent: true,\n hires: 'boundary',\n });\n\n return { code: ms.toString(), map };\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import * as ts from "typescript";
2
1
  import * as o from "@angular/compiler";
2
+ import * as ts from "typescript";
3
3
  //#region packages/vite-plugin-angular/src/lib/compiler/js-emitter.ts
4
4
  /** Shared printer — only used as fallback for complex WrappedNodeExpr (e.g. decorator args). */
5
5
  var sharedPrinter = ts.createPrinter({ removeComments: true });
@@ -300,7 +300,7 @@ var JSEmitter = class JSEmitter {
300
300
  visitInvokeFunctionExpr(ast) {
301
301
  const fn = ast.fn.visitExpression(this, null);
302
302
  const args = ast.args.map((a) => this.emitExpr(a)).join(", ");
303
- if (ast.fn instanceof o.ArrowFunctionExpr || ast.fn instanceof o.FunctionExpr) return "(" + fn + ")(" + args + ")";
303
+ if (ast.fn instanceof o.ArrowFunctionExpr || ast.fn instanceof o.FunctionExpr || ast.fn instanceof o.WrappedNodeExpr) return "(" + fn + ")(" + args + ")";
304
304
  return fn + "(" + args + ")";
305
305
  }
306
306
  visitReadVarExpr(ast) {
@@ -1 +1 @@
1
- {"version":3,"file":"js-emitter.js","names":[],"sources":["../../../../src/lib/compiler/js-emitter.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport * as o from '@angular/compiler';\n\n/** Shared printer — only used as fallback for complex WrappedNodeExpr (e.g. decorator args). */\nconst sharedPrinter = ts.createPrinter({ removeComments: true });\nconst emptySourceFile = ts.createSourceFile(\n '_.ts',\n '',\n ts.ScriptTarget.Latest,\n false,\n);\n\n// Operator metadata table — name, JS string, and precedence (higher = tighter\n// binding). Used to build version-aware lookup maps below.\n//\n// Why a runtime build instead of static `[o.BinaryOperator.Equals]: '=='`\n// literals: Angular's `BinaryOperator` enum gains members between major\n// versions (Assign and the 9 compound assignments were added in v21,\n// Exponentiation/In in v20, InstanceOf in v21). On older Angular versions\n// the missing members evaluate to `undefined` at module load time, and\n// every `[undefined]: '...'` entry collides on the single string key\n// `\"undefined\"` — last write wins. Pre-Phase-1, that gave the v19 install\n// `BINARY_OP_STR[\"undefined\"] === '??='`, so any expression with an\n// unknown operator emitted `??=` instead of failing loudly. Building the\n// table by iterating known names and skipping `undefined` values\n// eliminates the collision: members that don't exist on the installed\n// Angular are simply absent from the map.\n//\n// Precedence values match MDN's table, skipping levels not used by Angular\n// (bitwise XOR, shifts).\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence\nconst OP_DEFINITIONS: ReadonlyArray<\n readonly [name: string, str: string, precedence: number]\n> = [\n ['Assign', '=', 2],\n ['AdditionAssignment', '+=', 2],\n ['SubtractionAssignment', '-=', 2],\n ['MultiplicationAssignment', '*=', 2],\n ['DivisionAssignment', '/=', 2],\n ['RemainderAssignment', '%=', 2],\n ['ExponentiationAssignment', '**=', 2],\n ['AndAssignment', '&&=', 2],\n ['OrAssignment', '||=', 2],\n ['NullishCoalesceAssignment', '??=', 2],\n ['NullishCoalesce', '??', 4],\n ['Or', '||', 4],\n ['And', '&&', 5],\n ['BitwiseOr', '|', 6],\n ['BitwiseAnd', '&', 8],\n ['Equals', '==', 9],\n ['NotEquals', '!=', 9],\n ['Identical', '===', 9],\n ['NotIdentical', '!==', 9],\n ['Lower', '<', 10],\n ['LowerEquals', '<=', 10],\n ['Bigger', '>', 10],\n ['BiggerEquals', '>=', 10],\n ['In', 'in', 10],\n ['InstanceOf', 'instanceof', 10],\n ['Plus', '+', 12],\n ['Minus', '-', 12],\n ['Multiply', '*', 13],\n ['Divide', '/', 13],\n ['Modulo', '%', 13],\n ['Exponentiation', '**', 14],\n];\n\n/** Operator integer values that represent assignment forms (`=`, `+=`, etc.). */\nconst ASSIGNMENT_OP_NAMES: ReadonlySet<string> = new Set([\n 'Assign',\n 'AdditionAssignment',\n 'SubtractionAssignment',\n 'MultiplicationAssignment',\n 'DivisionAssignment',\n 'RemainderAssignment',\n 'ExponentiationAssignment',\n 'AndAssignment',\n 'OrAssignment',\n 'NullishCoalesceAssignment',\n]);\n\nconst BINARY_OP_STR = new Map<number, string>();\nconst BINARY_PRECEDENCE = new Map<number, number>();\nconst ASSIGNMENT_OP_VALUES = new Set<number>();\n\nfor (const [name, str, precedence] of OP_DEFINITIONS) {\n const value = (o.BinaryOperator as Record<string, unknown>)[name];\n if (typeof value !== 'number') continue;\n BINARY_OP_STR.set(value, str);\n BINARY_PRECEDENCE.set(value, precedence);\n if (ASSIGNMENT_OP_NAMES.has(name)) {\n ASSIGNMENT_OP_VALUES.add(value);\n }\n}\n\n/** Returns true when `op` represents any kind of assignment (`=`, `+=`, etc.). */\nfunction isAssignmentOperator(op: o.BinaryOperator): boolean {\n return ASSIGNMENT_OP_VALUES.has(op);\n}\n\n/**\n * Determine whether a child expression needs parentheses when it appears\n * as an operand of `parentOp`.\n */\nfunction childNeedsParens(\n parentOp: o.BinaryOperator,\n child: o.Expression,\n isRhs: boolean,\n): boolean {\n if (!(child instanceof o.BinaryOperatorExpr)) return false;\n\n const childOp = child.operator;\n const parentPrec = BINARY_PRECEDENCE.get(parentOp);\n const childPrec = BINARY_PRECEDENCE.get(childOp);\n if (parentPrec === undefined || childPrec === undefined) return false;\n\n // ?? cannot appear with || or && without explicit grouping (JS spec)\n if (\n (parentOp === o.BinaryOperator.NullishCoalesce &&\n (childOp === o.BinaryOperator.And || childOp === o.BinaryOperator.Or)) ||\n (childOp === o.BinaryOperator.NullishCoalesce &&\n (parentOp === o.BinaryOperator.And || parentOp === o.BinaryOperator.Or))\n ) {\n return true;\n }\n\n // Child has strictly lower precedence\n if (childPrec < parentPrec) return true;\n\n // Same precedence — depends on associativity and position\n if (childPrec === parentPrec) {\n // ** is right-associative: LHS same-prec needs parens, RHS does not\n if (parentOp === o.BinaryOperator.Exponentiation) return !isRhs;\n // All other ops are left-associative: RHS same-prec needs parens\n return isRhs;\n }\n\n return false;\n}\n\n/**\n * Wrap a receiver expression in parens when emitting `<receiver>.name` or\n * `<receiver>.name(args)`. Two cases produce a JS parse error otherwise:\n *\n * 1. A `BinaryOperatorExpr` receiver: `a / 3600.toFixed(2)` parses as\n * `a / 3600.toFixed(2)` where `3600.toFixed` is read as the start of a\n * decimal literal followed by an identifier — an \"Invalid characters\n * after number\" error. Wrapping gives `(a / 3600).toFixed(2)`.\n * 2. A non-negative integer `LiteralExpr` receiver: `42.toFixed(2)` is\n * invalid for the same decimal-literal-ambiguity reason. Wrapping gives\n * `(42).toFixed(2)`. Negative numbers are already emitted as `(-42)` by\n * `visitLiteralExpr`. Floats (e.g. `4.5.toFixed`) and strings parse fine.\n *\n * Other expression kinds either already self-wrap (`ConditionalExpr`,\n * `UnaryOperatorExpr`) or are primary forms that don't need parens\n * (`ReadVarExpr`, `ReadPropExpr`, `InvokeFunctionExpr`, etc.).\n */\nfunction emitReceiverForMemberAccess(\n receiver: o.Expression,\n emitted: string,\n): string {\n if (receiver instanceof o.BinaryOperatorExpr) return '(' + emitted + ')';\n if (\n receiver instanceof o.LiteralExpr &&\n typeof receiver.value === 'number' &&\n receiver.value >= 0\n ) {\n return '(' + emitted + ')';\n }\n return emitted;\n}\n\n/** Polyfill for `__makeTemplateObject` used in downleveled `$localize` calls. */\nconst MAKE_TEMPLATE_OBJECT_POLYFILL =\n '(this&&this.__makeTemplateObject||function(e,t){return Object.defineProperty?Object.defineProperty(e,\"raw\",{value:t}):e.raw=t,e})';\n\nconst SINGLE_QUOTE_ESCAPE_RE = /[\\\\'\\n\\r]/g;\n\n/** Escape a string for use as a single-quoted string literal. */\nfunction escapeForLocalize(input: string): string {\n const body = input.replace(SINGLE_QUOTE_ESCAPE_RE, (match) => {\n if (match === '\\n') return '\\\\n';\n if (match === '\\r') return '\\\\r';\n return `\\\\${match}`;\n });\n return `'${body}'`;\n}\n\n/**\n * Emits Angular output AST directly to JavaScript strings, bypassing\n * ts.factory node creation and ts.Printer serialization (~4x faster).\n */\nclass JSEmitter implements o.ExpressionVisitor, o.StatementVisitor {\n /** Set by compile() so WrappedNodeExpr fallback can print with correct source context. */\n static _currentSourceFile: ts.SourceFile | undefined;\n /** Set by compile() so OXC-based WrappedNodeExpr can slice original source. */\n static _currentSourceCode: string | undefined;\n\n private emitExpr(e: any): string {\n if (!e) return 'null';\n if (typeof e.visitExpression === 'function')\n return e.visitExpression(this, null);\n // Angular v21 LiteralMapPropertyAssignment: {key, value, quoted}\n if ('key' in e && 'value' in e) {\n const key = e.quoted ? JSON.stringify(e.key) : e.key;\n return key + ': ' + this.emitExpr(e.value);\n }\n return 'null';\n }\n visitWrappedNodeExpr(ast: o.WrappedNodeExpr<any>) {\n const node = ast.node;\n\n // Raw source text: already resolved to a string at wrap time\n if (typeof node === 'string') return node;\n\n // OXC AST nodes: identified by string `type` property + numeric start/end\n if (typeof node.type === 'string' && typeof node.start === 'number') {\n const src = JSEmitter._currentSourceCode;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'StringLiteral') return JSON.stringify(node.value);\n if (node.type === 'NumericLiteral') return String(node.value);\n if (node.type === 'BooleanLiteral') return node.value ? 'true' : 'false';\n if (node.type === 'NullLiteral') return 'null';\n if (node.type === 'TemplateLiteral' && !node.expressions?.length)\n return '`' + node.quasis[0].value.raw + '`';\n // Fallback: slice original source for complex OXC nodes\n if (src) return src.slice(node.start, node.end);\n return 'null';\n }\n\n // TypeScript AST nodes: identified by numeric `kind` property\n if (node.kind === ts.SyntaxKind.Identifier)\n return (node as ts.Identifier).escapedText as string;\n if (node.kind === ts.SyntaxKind.StringLiteral)\n return JSON.stringify((node as ts.StringLiteral).text);\n if (node.kind === ts.SyntaxKind.NumericLiteral)\n return (node as ts.NumericLiteral).text;\n if (node.kind === ts.SyntaxKind.TrueKeyword) return 'true';\n if (node.kind === ts.SyntaxKind.FalseKeyword) return 'false';\n if (node.kind === ts.SyntaxKind.NullKeyword) return 'null';\n if (node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral)\n return '`' + (node as ts.NoSubstitutionTemplateLiteral).text + '`';\n // Fallback for complex wrapped TS nodes (e.g. decorator arguments, array literals).\n // Use currentSourceFile when available for correct position-based printing.\n return sharedPrinter.printNode(\n ts.EmitHint.Unspecified,\n node,\n JSEmitter._currentSourceFile || emptySourceFile,\n );\n }\n visitExternalExpr(ast: o.ExternalExpr) {\n const name = ast.value.name;\n if (name === 'ngDevMode') return name;\n // When name is null/undefined, this is a bare module reference (e.g. ngImport: i0)\n if (!name) return 'i0';\n return 'i0.' + name;\n }\n visitLiteralExpr(ast: o.LiteralExpr) {\n const v = ast.value;\n if (typeof v === 'string') return JSON.stringify(v);\n if (typeof v === 'number') return v < 0 ? '(-' + -v + ')' : '' + v;\n if (typeof v === 'boolean') return v ? 'true' : 'false';\n if (v === undefined) return 'void 0';\n return 'null';\n }\n visitLiteralArrayExpr(ast: o.LiteralArrayExpr) {\n return '[' + ast.entries.map((e) => this.emitExpr(e)).join(', ') + ']';\n }\n visitLiteralMapExpr(ast: o.LiteralMapExpr) {\n return '{' + ast.entries.map((e) => this.emitExpr(e)).join(', ') + '}';\n }\n visitInvokeFunctionExpr(ast: o.InvokeFunctionExpr) {\n const fn = ast.fn.visitExpression(this, null);\n const args = ast.args.map((a: any) => this.emitExpr(a)).join(', ');\n // Wrap arrow/function expressions in parens for valid IIFE syntax\n if (\n ast.fn instanceof o.ArrowFunctionExpr ||\n ast.fn instanceof o.FunctionExpr\n ) {\n return '(' + fn + ')(' + args + ')';\n }\n return fn + '(' + args + ')';\n }\n visitReadVarExpr(ast: o.ReadVarExpr) {\n if (ast.name === 'this') return 'this';\n if (ast.name === 'super') return 'super';\n return ast.name!;\n }\n visitReadPropExpr(ast: o.ReadPropExpr) {\n const receiver = ast.receiver.visitExpression(this, null);\n return emitReceiverForMemberAccess(ast.receiver, receiver) + '.' + ast.name;\n }\n visitReadKeyExpr(ast: o.ReadKeyExpr) {\n const receiver = ast.receiver.visitExpression(this, null);\n return (\n emitReceiverForMemberAccess(ast.receiver, receiver) +\n '[' +\n ast.index.visitExpression(this, null) +\n ']'\n );\n }\n visitConditionalExpr(ast: o.ConditionalExpr) {\n return (\n '(' +\n ast.condition.visitExpression(this, null) +\n ' ? ' +\n ast.trueCase.visitExpression(this, null) +\n ' : ' +\n ast.falseCase!.visitExpression(this, null) +\n ')'\n );\n }\n visitBinaryOperatorExpr(ast: o.BinaryOperatorExpr) {\n // `BINARY_OP_STR.get(...)` returns `undefined` when the operator value\n // doesn't exist in the installed Angular's `BinaryOperator` enum (the\n // enum is missing 13 members on v19, 11 on v20). Falling back to `'='`\n // would silently produce wrong code; instead, we throw so the error\n // surfaces in the DEBUG output and the calling test fails loudly.\n const op = BINARY_OP_STR.get(ast.operator);\n if (op === undefined) {\n throw new Error(\n `[fast-compile] Unsupported BinaryOperator value ${ast.operator} ` +\n `on @angular/compiler ${o.VERSION?.full ?? '(unknown version)'}`,\n );\n }\n\n const lhsRaw = ast.lhs.visitExpression(this, null);\n const rhsRaw = ast.rhs.visitExpression(this, null);\n\n const lhs = childNeedsParens(ast.operator, ast.lhs, false)\n ? '(' + lhsRaw + ')'\n : lhsRaw;\n const rhs = childNeedsParens(ast.operator, ast.rhs, true)\n ? '(' + rhsRaw + ')'\n : rhsRaw;\n\n const expr = lhs + ' ' + op + ' ' + rhs;\n\n // Wrap assignments in parens so they work correctly as ternary conditions:\n // (tmp = val) ? a : b vs tmp = val ? a : b\n //\n // `isAssignmentOperator` is built at module load time from the operator\n // names that actually exist on the installed Angular's enum. This\n // works whether `Assign` is present (v21+) or absent (v19/v20) — on\n // older versions the assignment branch is simply unreachable because\n // Angular's compiler never constructs an Assign-operator expression.\n if (isAssignmentOperator(ast.operator)) {\n return '(' + expr + ')';\n }\n return expr;\n }\n visitNotExpr(ast: o.NotExpr) {\n return '!(' + ast.condition.visitExpression(this, null) + ')';\n }\n visitFunctionExpr(ast: o.FunctionExpr) {\n return (\n '(' +\n ast.params.map((p: any) => p.name).join(', ') +\n ') => {' +\n ast.statements.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n }\n visitArrowFunctionExpr(ast: o.ArrowFunctionExpr) {\n const params = '(' + ast.params.map((p: any) => p.name).join(', ') + ')';\n if (Array.isArray(ast.body))\n return (\n params +\n ' => {' +\n ast.body.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n const bodyExpr = (ast.body as o.Expression).visitExpression(this, null);\n // Wrap object literals in parens so `() => {key: val}` isn't parsed\n // as a block with a labeled statement.\n if (ast.body instanceof o.LiteralMapExpr) {\n return params + ' => (' + bodyExpr + ')';\n }\n return params + ' => ' + bodyExpr;\n }\n // `Write*Expr` visitors must wrap the assignment in parentheses so that\n // it composes correctly when nested inside higher-precedence parents\n // (e.g. as the test of a `ConditionalExpr`). Without the wrapping,\n // tmp = ctx.data() ? 0 : -1\n // parses as `tmp = (ctx.data() ? 0 : -1)` because assignment binds\n // looser than the ternary, which silently assigns the wrong value to\n // `tmp`. Angular's own `AbstractEmitterVisitor.visitWriteVarExpr`\n // applies the same context-sensitive wrapping (it skips the parens\n // when the assignment is a top-level statement to avoid `(x = 1);`\n // noise; we always wrap for simplicity — the redundant parens at\n // statement level are harmless).\n //\n // This matters specifically on Angular v19/v20, where assignment is\n // represented in the IR via `WriteVarExpr` / `AssignTemporaryExpr →\n // WriteVarExpr`. On v21+ the same construct is represented via\n // `BinaryOperatorExpr(Assign, ...)`, which `visitBinaryOperatorExpr`\n // already wraps via `isAssignmentOperator`. Without these wrappers,\n // `@if (data(); as item)` and similar conditional alias forms emit\n // runtime-broken code on v19/v20.\n visitWriteVarExpr(ast: any) {\n return '(' + ast.name + ' = ' + ast.value.visitExpression(this, null) + ')';\n }\n visitWritePropExpr(ast: any) {\n return (\n '(' +\n ast.receiver.visitExpression(this, null) +\n '.' +\n ast.name +\n ' = ' +\n ast.value.visitExpression(this, null) +\n ')'\n );\n }\n visitWriteKeyExpr(ast: any) {\n return (\n '(' +\n ast.receiver.visitExpression(this, null) +\n '[' +\n ast.index.visitExpression(this, null) +\n '] = ' +\n ast.value.visitExpression(this, null) +\n ')'\n );\n }\n visitInvokeMethodExpr(ast: any) {\n const receiver = ast.receiver.visitExpression(this, null);\n return (\n emitReceiverForMemberAccess(ast.receiver, receiver) +\n '.' +\n ast.name +\n '(' +\n ast.args.map((a: any) => this.emitExpr(a)).join(', ') +\n ')'\n );\n }\n visitTypeofExpr(ast: o.TypeofExpr) {\n return 'typeof ' + ast.expr.visitExpression(this, null);\n }\n visitUnaryOperatorExpr(ast: o.UnaryOperatorExpr) {\n return '-(' + ast.expr.visitExpression(this, null) + ')';\n }\n visitInstantiateExpr(ast: o.InstantiateExpr) {\n return (\n 'new (' +\n ast.classExpr.visitExpression(this, null) +\n ')(' +\n ast.args.map((a: any) => this.emitExpr(a)).join(', ') +\n ')'\n );\n }\n visitCommaExpr(ast: o.CommaExpr) {\n return ast.parts.map((p: any) => p.visitExpression(this, null)).join(', ');\n }\n visitParenthesizedExpr(ast: o.ParenthesizedExpr) {\n return '(' + ast.expr.visitExpression(this, null) + ')';\n }\n visitVoidExpr(ast: o.VoidExpr) {\n return 'void ' + ast.expr.visitExpression(this, null);\n }\n visitSpreadElementExpr(ast: o.SpreadElementExpr) {\n return '...' + (ast as any).expression.visitExpression(this, null);\n }\n visitDynamicImportExpr(ast: o.DynamicImportExpr) {\n return (\n 'import(' +\n (typeof ast.url === 'string'\n ? JSON.stringify(ast.url)\n : ast.url.visitExpression(this, null)) +\n ')'\n );\n }\n visitTemplateLiteralExpr(ast: o.TemplateLiteralExpr) {\n return (\n '`' +\n ast.elements[0].text +\n ast.expressions\n .map(\n (e: any, i: number) =>\n '${' +\n e.visitExpression(this, null) +\n '}' +\n ast.elements[i + 1].text,\n )\n .join('') +\n '`'\n );\n }\n visitTaggedTemplateLiteralExpr(ast: any) {\n const elements = ast.template.elements;\n const expressions = ast.template.expressions;\n const head = elements[0].text;\n const spans = expressions\n .map(\n (e: any, i: number) =>\n '${' + e.visitExpression(this, null) + '}' + elements[i + 1].text,\n )\n .join('');\n return ast.tag.visitExpression(this, null) + '`' + head + spans + '`';\n }\n visitLocalizedString(ast: o.LocalizedString) {\n // Emit the downleveled form:\n // $localize(makeTemplateObject(cooked, raw), expr1, expr2, ...)\n const parts: { cooked: string; raw: string }[] = [ast.serializeI18nHead()];\n for (let i = 1; i < ast.messageParts.length; i++) {\n parts.push(ast.serializeI18nTemplatePart(i));\n }\n const cooked = parts.map((p) => escapeForLocalize(p.cooked)).join(', ');\n const raw = parts.map((p) => escapeForLocalize(p.raw)).join(', ');\n const exprs = ast.expressions.map((e) => this.emitExpr(e));\n return (\n '$localize(' +\n MAKE_TEMPLATE_OBJECT_POLYFILL +\n '([' +\n cooked +\n '], [' +\n raw +\n '])' +\n (exprs.length > 0 ? ', ' + exprs.join(', ') : '') +\n ')'\n );\n }\n visitRegularExpressionLiteral(ast: any) {\n return '/' + (ast.body ?? ast.pattern) + '/' + ast.flags;\n }\n visitTemplateLiteralElementExpr(ast: o.TemplateLiteralElementExpr) {\n return JSON.stringify(ast.text);\n }\n // Statement visitors\n visitReturnStmt(stmt: o.ReturnStatement) {\n return 'return ' + stmt.value.visitExpression(this, null) + ';';\n }\n visitExpressionStmt(stmt: o.ExpressionStatement) {\n return stmt.expr.visitExpression(this, null) + ';';\n }\n visitIfStmt(stmt: o.IfStmt) {\n let s =\n 'if (' +\n stmt.condition.visitExpression(this, null) +\n ') {' +\n stmt.trueCase.map((s2: any) => s2.visitStatement(this, null)).join(' ') +\n '}';\n if (stmt.falseCase.length)\n s +=\n ' else {' +\n stmt.falseCase\n .map((s2: any) => s2.visitStatement(this, null))\n .join(' ') +\n '}';\n return s;\n }\n visitDeclareVarStmt(stmt: o.DeclareVarStmt) {\n const kw = stmt.hasModifier(o.StmtModifier.Final) ? 'const' : 'let';\n return (\n kw +\n ' ' +\n stmt.name +\n (stmt.value ? ' = ' + stmt.value.visitExpression(this, null) : '') +\n ';'\n );\n }\n visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt) {\n return (\n 'function ' +\n stmt.name +\n '(' +\n stmt.params.map((p: any) => p.name).join(', ') +\n ') {' +\n stmt.statements.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n }\n}\n\nconst stringEmitter = new JSEmitter();\n\n/** Emit Angular output AST expression directly to a JavaScript string. */\nexport function emitAngularExpr(expr: o.Expression): string {\n return expr.visitExpression(stringEmitter, null);\n}\n\n/** Emit Angular output AST statement directly to a JavaScript string. */\nexport function emitAngularStmt(stmt: o.Statement): string {\n return stmt.visitStatement(stringEmitter, null);\n}\n\n/** Set the current source file for WrappedNodeExpr fallback printing. */\nexport function setEmitterSourceFile(sf: ts.SourceFile | undefined): void {\n JSEmitter._currentSourceFile = sf;\n}\n\n/** Set the current source code for OXC-based WrappedNodeExpr slice fallback. */\nexport function setEmitterSourceCode(code: string | undefined): void {\n JSEmitter._currentSourceCode = code;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"js-emitter.js","names":[],"sources":["../../../../src/lib/compiler/js-emitter.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport * as o from '@angular/compiler';\n\n/** Shared printer — only used as fallback for complex WrappedNodeExpr (e.g. decorator args). */\nconst sharedPrinter = ts.createPrinter({ removeComments: true });\nconst emptySourceFile = ts.createSourceFile(\n '_.ts',\n '',\n ts.ScriptTarget.Latest,\n false,\n);\n\n// Operator metadata table — name, JS string, and precedence (higher = tighter\n// binding). Used to build version-aware lookup maps below.\n//\n// Why a runtime build instead of static `[o.BinaryOperator.Equals]: '=='`\n// literals: Angular's `BinaryOperator` enum gains members between major\n// versions (Assign and the 9 compound assignments were added in v21,\n// Exponentiation/In in v20, InstanceOf in v21). On older Angular versions\n// the missing members evaluate to `undefined` at module load time, and\n// every `[undefined]: '...'` entry collides on the single string key\n// `\"undefined\"` — last write wins. Pre-Phase-1, that gave the v19 install\n// `BINARY_OP_STR[\"undefined\"] === '??='`, so any expression with an\n// unknown operator emitted `??=` instead of failing loudly. Building the\n// table by iterating known names and skipping `undefined` values\n// eliminates the collision: members that don't exist on the installed\n// Angular are simply absent from the map.\n//\n// Precedence values match MDN's table, skipping levels not used by Angular\n// (bitwise XOR, shifts).\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_precedence\nconst OP_DEFINITIONS: ReadonlyArray<\n readonly [name: string, str: string, precedence: number]\n> = [\n ['Assign', '=', 2],\n ['AdditionAssignment', '+=', 2],\n ['SubtractionAssignment', '-=', 2],\n ['MultiplicationAssignment', '*=', 2],\n ['DivisionAssignment', '/=', 2],\n ['RemainderAssignment', '%=', 2],\n ['ExponentiationAssignment', '**=', 2],\n ['AndAssignment', '&&=', 2],\n ['OrAssignment', '||=', 2],\n ['NullishCoalesceAssignment', '??=', 2],\n ['NullishCoalesce', '??', 4],\n ['Or', '||', 4],\n ['And', '&&', 5],\n ['BitwiseOr', '|', 6],\n ['BitwiseAnd', '&', 8],\n ['Equals', '==', 9],\n ['NotEquals', '!=', 9],\n ['Identical', '===', 9],\n ['NotIdentical', '!==', 9],\n ['Lower', '<', 10],\n ['LowerEquals', '<=', 10],\n ['Bigger', '>', 10],\n ['BiggerEquals', '>=', 10],\n ['In', 'in', 10],\n ['InstanceOf', 'instanceof', 10],\n ['Plus', '+', 12],\n ['Minus', '-', 12],\n ['Multiply', '*', 13],\n ['Divide', '/', 13],\n ['Modulo', '%', 13],\n ['Exponentiation', '**', 14],\n];\n\n/** Operator integer values that represent assignment forms (`=`, `+=`, etc.). */\nconst ASSIGNMENT_OP_NAMES: ReadonlySet<string> = new Set([\n 'Assign',\n 'AdditionAssignment',\n 'SubtractionAssignment',\n 'MultiplicationAssignment',\n 'DivisionAssignment',\n 'RemainderAssignment',\n 'ExponentiationAssignment',\n 'AndAssignment',\n 'OrAssignment',\n 'NullishCoalesceAssignment',\n]);\n\nconst BINARY_OP_STR = new Map<number, string>();\nconst BINARY_PRECEDENCE = new Map<number, number>();\nconst ASSIGNMENT_OP_VALUES = new Set<number>();\n\nfor (const [name, str, precedence] of OP_DEFINITIONS) {\n const value = (o.BinaryOperator as Record<string, unknown>)[name];\n if (typeof value !== 'number') continue;\n BINARY_OP_STR.set(value, str);\n BINARY_PRECEDENCE.set(value, precedence);\n if (ASSIGNMENT_OP_NAMES.has(name)) {\n ASSIGNMENT_OP_VALUES.add(value);\n }\n}\n\n/** Returns true when `op` represents any kind of assignment (`=`, `+=`, etc.). */\nfunction isAssignmentOperator(op: o.BinaryOperator): boolean {\n return ASSIGNMENT_OP_VALUES.has(op);\n}\n\n/**\n * Determine whether a child expression needs parentheses when it appears\n * as an operand of `parentOp`.\n */\nfunction childNeedsParens(\n parentOp: o.BinaryOperator,\n child: o.Expression,\n isRhs: boolean,\n): boolean {\n if (!(child instanceof o.BinaryOperatorExpr)) return false;\n\n const childOp = child.operator;\n const parentPrec = BINARY_PRECEDENCE.get(parentOp);\n const childPrec = BINARY_PRECEDENCE.get(childOp);\n if (parentPrec === undefined || childPrec === undefined) return false;\n\n // ?? cannot appear with || or && without explicit grouping (JS spec)\n if (\n (parentOp === o.BinaryOperator.NullishCoalesce &&\n (childOp === o.BinaryOperator.And || childOp === o.BinaryOperator.Or)) ||\n (childOp === o.BinaryOperator.NullishCoalesce &&\n (parentOp === o.BinaryOperator.And || parentOp === o.BinaryOperator.Or))\n ) {\n return true;\n }\n\n // Child has strictly lower precedence\n if (childPrec < parentPrec) return true;\n\n // Same precedence — depends on associativity and position\n if (childPrec === parentPrec) {\n // ** is right-associative: LHS same-prec needs parens, RHS does not\n if (parentOp === o.BinaryOperator.Exponentiation) return !isRhs;\n // All other ops are left-associative: RHS same-prec needs parens\n return isRhs;\n }\n\n return false;\n}\n\n/**\n * Wrap a receiver expression in parens when emitting `<receiver>.name` or\n * `<receiver>.name(args)`. Two cases produce a JS parse error otherwise:\n *\n * 1. A `BinaryOperatorExpr` receiver: `a / 3600.toFixed(2)` parses as\n * `a / 3600.toFixed(2)` where `3600.toFixed` is read as the start of a\n * decimal literal followed by an identifier — an \"Invalid characters\n * after number\" error. Wrapping gives `(a / 3600).toFixed(2)`.\n * 2. A non-negative integer `LiteralExpr` receiver: `42.toFixed(2)` is\n * invalid for the same decimal-literal-ambiguity reason. Wrapping gives\n * `(42).toFixed(2)`. Negative numbers are already emitted as `(-42)` by\n * `visitLiteralExpr`. Floats (e.g. `4.5.toFixed`) and strings parse fine.\n *\n * Other expression kinds either already self-wrap (`ConditionalExpr`,\n * `UnaryOperatorExpr`) or are primary forms that don't need parens\n * (`ReadVarExpr`, `ReadPropExpr`, `InvokeFunctionExpr`, etc.).\n */\nfunction emitReceiverForMemberAccess(\n receiver: o.Expression,\n emitted: string,\n): string {\n if (receiver instanceof o.BinaryOperatorExpr) return '(' + emitted + ')';\n if (\n receiver instanceof o.LiteralExpr &&\n typeof receiver.value === 'number' &&\n receiver.value >= 0\n ) {\n return '(' + emitted + ')';\n }\n return emitted;\n}\n\n/** Polyfill for `__makeTemplateObject` used in downleveled `$localize` calls. */\nconst MAKE_TEMPLATE_OBJECT_POLYFILL =\n '(this&&this.__makeTemplateObject||function(e,t){return Object.defineProperty?Object.defineProperty(e,\"raw\",{value:t}):e.raw=t,e})';\n\nconst SINGLE_QUOTE_ESCAPE_RE = /[\\\\'\\n\\r]/g;\n\n/** Escape a string for use as a single-quoted string literal. */\nfunction escapeForLocalize(input: string): string {\n const body = input.replace(SINGLE_QUOTE_ESCAPE_RE, (match) => {\n if (match === '\\n') return '\\\\n';\n if (match === '\\r') return '\\\\r';\n return `\\\\${match}`;\n });\n return `'${body}'`;\n}\n\n/**\n * Emits Angular output AST directly to JavaScript strings, bypassing\n * ts.factory node creation and ts.Printer serialization (~4x faster).\n */\nclass JSEmitter implements o.ExpressionVisitor, o.StatementVisitor {\n /** Set by compile() so WrappedNodeExpr fallback can print with correct source context. */\n static _currentSourceFile: ts.SourceFile | undefined;\n /** Set by compile() so OXC-based WrappedNodeExpr can slice original source. */\n static _currentSourceCode: string | undefined;\n\n private emitExpr(e: any): string {\n if (!e) return 'null';\n if (typeof e.visitExpression === 'function')\n return e.visitExpression(this, null);\n // Angular v21 LiteralMapPropertyAssignment: {key, value, quoted}\n if ('key' in e && 'value' in e) {\n const key = e.quoted ? JSON.stringify(e.key) : e.key;\n return key + ': ' + this.emitExpr(e.value);\n }\n return 'null';\n }\n visitWrappedNodeExpr(ast: o.WrappedNodeExpr<any>) {\n const node = ast.node;\n\n // Raw source text: already resolved to a string at wrap time\n if (typeof node === 'string') return node;\n\n // OXC AST nodes: identified by string `type` property + numeric start/end\n if (typeof node.type === 'string' && typeof node.start === 'number') {\n const src = JSEmitter._currentSourceCode;\n if (node.type === 'Identifier') return node.name;\n if (node.type === 'StringLiteral') return JSON.stringify(node.value);\n if (node.type === 'NumericLiteral') return String(node.value);\n if (node.type === 'BooleanLiteral') return node.value ? 'true' : 'false';\n if (node.type === 'NullLiteral') return 'null';\n if (node.type === 'TemplateLiteral' && !node.expressions?.length)\n return '`' + node.quasis[0].value.raw + '`';\n // Fallback: slice original source for complex OXC nodes\n if (src) return src.slice(node.start, node.end);\n return 'null';\n }\n\n // TypeScript AST nodes: identified by numeric `kind` property\n if (node.kind === ts.SyntaxKind.Identifier)\n return (node as ts.Identifier).escapedText as string;\n if (node.kind === ts.SyntaxKind.StringLiteral)\n return JSON.stringify((node as ts.StringLiteral).text);\n if (node.kind === ts.SyntaxKind.NumericLiteral)\n return (node as ts.NumericLiteral).text;\n if (node.kind === ts.SyntaxKind.TrueKeyword) return 'true';\n if (node.kind === ts.SyntaxKind.FalseKeyword) return 'false';\n if (node.kind === ts.SyntaxKind.NullKeyword) return 'null';\n if (node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral)\n return '`' + (node as ts.NoSubstitutionTemplateLiteral).text + '`';\n // Fallback for complex wrapped TS nodes (e.g. decorator arguments, array literals).\n // Use currentSourceFile when available for correct position-based printing.\n return sharedPrinter.printNode(\n ts.EmitHint.Unspecified,\n node,\n JSEmitter._currentSourceFile || emptySourceFile,\n );\n }\n visitExternalExpr(ast: o.ExternalExpr) {\n const name = ast.value.name;\n if (name === 'ngDevMode') return name;\n // When name is null/undefined, this is a bare module reference (e.g. ngImport: i0)\n if (!name) return 'i0';\n return 'i0.' + name;\n }\n visitLiteralExpr(ast: o.LiteralExpr) {\n const v = ast.value;\n if (typeof v === 'string') return JSON.stringify(v);\n if (typeof v === 'number') return v < 0 ? '(-' + -v + ')' : '' + v;\n if (typeof v === 'boolean') return v ? 'true' : 'false';\n if (v === undefined) return 'void 0';\n return 'null';\n }\n visitLiteralArrayExpr(ast: o.LiteralArrayExpr) {\n return '[' + ast.entries.map((e) => this.emitExpr(e)).join(', ') + ']';\n }\n visitLiteralMapExpr(ast: o.LiteralMapExpr) {\n return '{' + ast.entries.map((e) => this.emitExpr(e)).join(', ') + '}';\n }\n visitInvokeFunctionExpr(ast: o.InvokeFunctionExpr) {\n const fn = ast.fn.visitExpression(this, null);\n const args = ast.args.map((a: any) => this.emitExpr(a)).join(', ');\n // Wrap arrow/function expressions in parens for valid IIFE syntax. A\n // `WrappedNodeExpr` callee is a raw user expression (e.g. an\n // `@Injectable({ useFactory: (a, b) => … })` arrow); without parens the\n // argument list binds to the arrow's *body* (`… => new X(a, b)(args)`)\n // instead of invoking the arrow. Parenthesizing any wrapped callee is\n // always semantically safe.\n if (\n ast.fn instanceof o.ArrowFunctionExpr ||\n ast.fn instanceof o.FunctionExpr ||\n ast.fn instanceof o.WrappedNodeExpr\n ) {\n return '(' + fn + ')(' + args + ')';\n }\n return fn + '(' + args + ')';\n }\n visitReadVarExpr(ast: o.ReadVarExpr) {\n if (ast.name === 'this') return 'this';\n if (ast.name === 'super') return 'super';\n return ast.name!;\n }\n visitReadPropExpr(ast: o.ReadPropExpr) {\n const receiver = ast.receiver.visitExpression(this, null);\n return emitReceiverForMemberAccess(ast.receiver, receiver) + '.' + ast.name;\n }\n visitReadKeyExpr(ast: o.ReadKeyExpr) {\n const receiver = ast.receiver.visitExpression(this, null);\n return (\n emitReceiverForMemberAccess(ast.receiver, receiver) +\n '[' +\n ast.index.visitExpression(this, null) +\n ']'\n );\n }\n visitConditionalExpr(ast: o.ConditionalExpr) {\n return (\n '(' +\n ast.condition.visitExpression(this, null) +\n ' ? ' +\n ast.trueCase.visitExpression(this, null) +\n ' : ' +\n ast.falseCase!.visitExpression(this, null) +\n ')'\n );\n }\n visitBinaryOperatorExpr(ast: o.BinaryOperatorExpr) {\n // `BINARY_OP_STR.get(...)` returns `undefined` when the operator value\n // doesn't exist in the installed Angular's `BinaryOperator` enum (the\n // enum is missing 13 members on v19, 11 on v20). Falling back to `'='`\n // would silently produce wrong code; instead, we throw so the error\n // surfaces in the DEBUG output and the calling test fails loudly.\n const op = BINARY_OP_STR.get(ast.operator);\n if (op === undefined) {\n throw new Error(\n `[fast-compile] Unsupported BinaryOperator value ${ast.operator} ` +\n `on @angular/compiler ${o.VERSION?.full ?? '(unknown version)'}`,\n );\n }\n\n const lhsRaw = ast.lhs.visitExpression(this, null);\n const rhsRaw = ast.rhs.visitExpression(this, null);\n\n const lhs = childNeedsParens(ast.operator, ast.lhs, false)\n ? '(' + lhsRaw + ')'\n : lhsRaw;\n const rhs = childNeedsParens(ast.operator, ast.rhs, true)\n ? '(' + rhsRaw + ')'\n : rhsRaw;\n\n const expr = lhs + ' ' + op + ' ' + rhs;\n\n // Wrap assignments in parens so they work correctly as ternary conditions:\n // (tmp = val) ? a : b vs tmp = val ? a : b\n //\n // `isAssignmentOperator` is built at module load time from the operator\n // names that actually exist on the installed Angular's enum. This\n // works whether `Assign` is present (v21+) or absent (v19/v20) — on\n // older versions the assignment branch is simply unreachable because\n // Angular's compiler never constructs an Assign-operator expression.\n if (isAssignmentOperator(ast.operator)) {\n return '(' + expr + ')';\n }\n return expr;\n }\n visitNotExpr(ast: o.NotExpr) {\n return '!(' + ast.condition.visitExpression(this, null) + ')';\n }\n visitFunctionExpr(ast: o.FunctionExpr) {\n return (\n '(' +\n ast.params.map((p: any) => p.name).join(', ') +\n ') => {' +\n ast.statements.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n }\n visitArrowFunctionExpr(ast: o.ArrowFunctionExpr) {\n const params = '(' + ast.params.map((p: any) => p.name).join(', ') + ')';\n if (Array.isArray(ast.body))\n return (\n params +\n ' => {' +\n ast.body.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n const bodyExpr = (ast.body as o.Expression).visitExpression(this, null);\n // Wrap object literals in parens so `() => {key: val}` isn't parsed\n // as a block with a labeled statement.\n if (ast.body instanceof o.LiteralMapExpr) {\n return params + ' => (' + bodyExpr + ')';\n }\n return params + ' => ' + bodyExpr;\n }\n // `Write*Expr` visitors must wrap the assignment in parentheses so that\n // it composes correctly when nested inside higher-precedence parents\n // (e.g. as the test of a `ConditionalExpr`). Without the wrapping,\n // tmp = ctx.data() ? 0 : -1\n // parses as `tmp = (ctx.data() ? 0 : -1)` because assignment binds\n // looser than the ternary, which silently assigns the wrong value to\n // `tmp`. Angular's own `AbstractEmitterVisitor.visitWriteVarExpr`\n // applies the same context-sensitive wrapping (it skips the parens\n // when the assignment is a top-level statement to avoid `(x = 1);`\n // noise; we always wrap for simplicity — the redundant parens at\n // statement level are harmless).\n //\n // This matters specifically on Angular v19/v20, where assignment is\n // represented in the IR via `WriteVarExpr` / `AssignTemporaryExpr →\n // WriteVarExpr`. On v21+ the same construct is represented via\n // `BinaryOperatorExpr(Assign, ...)`, which `visitBinaryOperatorExpr`\n // already wraps via `isAssignmentOperator`. Without these wrappers,\n // `@if (data(); as item)` and similar conditional alias forms emit\n // runtime-broken code on v19/v20.\n visitWriteVarExpr(ast: any) {\n return '(' + ast.name + ' = ' + ast.value.visitExpression(this, null) + ')';\n }\n visitWritePropExpr(ast: any) {\n return (\n '(' +\n ast.receiver.visitExpression(this, null) +\n '.' +\n ast.name +\n ' = ' +\n ast.value.visitExpression(this, null) +\n ')'\n );\n }\n visitWriteKeyExpr(ast: any) {\n return (\n '(' +\n ast.receiver.visitExpression(this, null) +\n '[' +\n ast.index.visitExpression(this, null) +\n '] = ' +\n ast.value.visitExpression(this, null) +\n ')'\n );\n }\n visitInvokeMethodExpr(ast: any) {\n const receiver = ast.receiver.visitExpression(this, null);\n return (\n emitReceiverForMemberAccess(ast.receiver, receiver) +\n '.' +\n ast.name +\n '(' +\n ast.args.map((a: any) => this.emitExpr(a)).join(', ') +\n ')'\n );\n }\n visitTypeofExpr(ast: o.TypeofExpr) {\n return 'typeof ' + ast.expr.visitExpression(this, null);\n }\n visitUnaryOperatorExpr(ast: o.UnaryOperatorExpr) {\n return '-(' + ast.expr.visitExpression(this, null) + ')';\n }\n visitInstantiateExpr(ast: o.InstantiateExpr) {\n return (\n 'new (' +\n ast.classExpr.visitExpression(this, null) +\n ')(' +\n ast.args.map((a: any) => this.emitExpr(a)).join(', ') +\n ')'\n );\n }\n visitCommaExpr(ast: o.CommaExpr) {\n return ast.parts.map((p: any) => p.visitExpression(this, null)).join(', ');\n }\n visitParenthesizedExpr(ast: o.ParenthesizedExpr) {\n return '(' + ast.expr.visitExpression(this, null) + ')';\n }\n visitVoidExpr(ast: o.VoidExpr) {\n return 'void ' + ast.expr.visitExpression(this, null);\n }\n visitSpreadElementExpr(ast: o.SpreadElementExpr) {\n return '...' + (ast as any).expression.visitExpression(this, null);\n }\n visitDynamicImportExpr(ast: o.DynamicImportExpr) {\n return (\n 'import(' +\n (typeof ast.url === 'string'\n ? JSON.stringify(ast.url)\n : ast.url.visitExpression(this, null)) +\n ')'\n );\n }\n visitTemplateLiteralExpr(ast: o.TemplateLiteralExpr) {\n return (\n '`' +\n ast.elements[0].text +\n ast.expressions\n .map(\n (e: any, i: number) =>\n '${' +\n e.visitExpression(this, null) +\n '}' +\n ast.elements[i + 1].text,\n )\n .join('') +\n '`'\n );\n }\n visitTaggedTemplateLiteralExpr(ast: any) {\n const elements = ast.template.elements;\n const expressions = ast.template.expressions;\n const head = elements[0].text;\n const spans = expressions\n .map(\n (e: any, i: number) =>\n '${' + e.visitExpression(this, null) + '}' + elements[i + 1].text,\n )\n .join('');\n return ast.tag.visitExpression(this, null) + '`' + head + spans + '`';\n }\n visitLocalizedString(ast: o.LocalizedString) {\n // Emit the downleveled form:\n // $localize(makeTemplateObject(cooked, raw), expr1, expr2, ...)\n const parts: { cooked: string; raw: string }[] = [ast.serializeI18nHead()];\n for (let i = 1; i < ast.messageParts.length; i++) {\n parts.push(ast.serializeI18nTemplatePart(i));\n }\n const cooked = parts.map((p) => escapeForLocalize(p.cooked)).join(', ');\n const raw = parts.map((p) => escapeForLocalize(p.raw)).join(', ');\n const exprs = ast.expressions.map((e) => this.emitExpr(e));\n return (\n '$localize(' +\n MAKE_TEMPLATE_OBJECT_POLYFILL +\n '([' +\n cooked +\n '], [' +\n raw +\n '])' +\n (exprs.length > 0 ? ', ' + exprs.join(', ') : '') +\n ')'\n );\n }\n visitRegularExpressionLiteral(ast: any) {\n return '/' + (ast.body ?? ast.pattern) + '/' + ast.flags;\n }\n visitTemplateLiteralElementExpr(ast: o.TemplateLiteralElementExpr) {\n return JSON.stringify(ast.text);\n }\n // Statement visitors\n visitReturnStmt(stmt: o.ReturnStatement) {\n return 'return ' + stmt.value.visitExpression(this, null) + ';';\n }\n visitExpressionStmt(stmt: o.ExpressionStatement) {\n return stmt.expr.visitExpression(this, null) + ';';\n }\n visitIfStmt(stmt: o.IfStmt) {\n let s =\n 'if (' +\n stmt.condition.visitExpression(this, null) +\n ') {' +\n stmt.trueCase.map((s2: any) => s2.visitStatement(this, null)).join(' ') +\n '}';\n if (stmt.falseCase.length)\n s +=\n ' else {' +\n stmt.falseCase\n .map((s2: any) => s2.visitStatement(this, null))\n .join(' ') +\n '}';\n return s;\n }\n visitDeclareVarStmt(stmt: o.DeclareVarStmt) {\n const kw = stmt.hasModifier(o.StmtModifier.Final) ? 'const' : 'let';\n return (\n kw +\n ' ' +\n stmt.name +\n (stmt.value ? ' = ' + stmt.value.visitExpression(this, null) : '') +\n ';'\n );\n }\n visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt) {\n return (\n 'function ' +\n stmt.name +\n '(' +\n stmt.params.map((p: any) => p.name).join(', ') +\n ') {' +\n stmt.statements.map((s: any) => s.visitStatement(this, null)).join(' ') +\n '}'\n );\n }\n}\n\nconst stringEmitter = new JSEmitter();\n\n/** Emit Angular output AST expression directly to a JavaScript string. */\nexport function emitAngularExpr(expr: o.Expression): string {\n return expr.visitExpression(stringEmitter, null);\n}\n\n/** Emit Angular output AST statement directly to a JavaScript string. */\nexport function emitAngularStmt(stmt: o.Statement): string {\n return stmt.visitStatement(stringEmitter, null);\n}\n\n/** Set the current source file for WrappedNodeExpr fallback printing. */\nexport function setEmitterSourceFile(sf: ts.SourceFile | undefined): void {\n JSEmitter._currentSourceFile = sf;\n}\n\n/** Set the current source code for OXC-based WrappedNodeExpr slice fallback. */\nexport function setEmitterSourceCode(code: string | undefined): void {\n JSEmitter._currentSourceCode = code;\n}\n"],"mappings":"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"}