@analogjs/vite-plugin-angular 3.0.0-alpha.36 → 3.0.0-alpha.38

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 (69) hide show
  1. package/README.md +22 -0
  2. package/package.json +3 -4
  3. package/src/lib/angular-jit-plugin.js +3 -0
  4. package/src/lib/angular-jit-plugin.js.map +1 -1
  5. package/src/lib/angular-vite-plugin.d.ts +12 -7
  6. package/src/lib/angular-vite-plugin.js +7 -5
  7. package/src/lib/angular-vite-plugin.js.map +1 -1
  8. package/src/lib/compiler/angular-version.d.ts +19 -0
  9. package/src/lib/compiler/angular-version.js +16 -0
  10. package/src/lib/compiler/angular-version.js.map +1 -0
  11. package/src/lib/compiler/class-field-lowering.d.ts +23 -0
  12. package/src/lib/compiler/class-field-lowering.js +131 -0
  13. package/src/lib/compiler/class-field-lowering.js.map +1 -0
  14. package/src/lib/compiler/compile.d.ts +44 -0
  15. package/src/lib/compiler/compile.js +731 -0
  16. package/src/lib/compiler/compile.js.map +1 -0
  17. package/src/lib/compiler/constants.d.ts +18 -0
  18. package/src/lib/compiler/constants.js +52 -0
  19. package/src/lib/compiler/constants.js.map +1 -0
  20. package/src/lib/compiler/debug.d.ts +22 -0
  21. package/src/lib/compiler/debug.js +20 -0
  22. package/src/lib/compiler/debug.js.map +1 -0
  23. package/src/lib/compiler/defer.d.ts +47 -0
  24. package/src/lib/compiler/defer.js +138 -0
  25. package/src/lib/compiler/defer.js.map +1 -0
  26. package/src/lib/compiler/dts-reader.d.ts +35 -0
  27. package/src/lib/compiler/dts-reader.js +365 -0
  28. package/src/lib/compiler/dts-reader.js.map +1 -0
  29. package/src/lib/compiler/hmr.d.ts +16 -0
  30. package/src/lib/compiler/hmr.js +69 -0
  31. package/src/lib/compiler/hmr.js.map +1 -0
  32. package/src/lib/compiler/index.d.ts +7 -0
  33. package/src/lib/compiler/index.js +7 -0
  34. package/src/lib/compiler/jit-metadata.d.ts +14 -0
  35. package/src/lib/compiler/jit-metadata.js +146 -0
  36. package/src/lib/compiler/jit-metadata.js.map +1 -0
  37. package/src/lib/compiler/jit-transform.d.ts +24 -0
  38. package/src/lib/compiler/jit-transform.js +200 -0
  39. package/src/lib/compiler/jit-transform.js.map +1 -0
  40. package/src/lib/compiler/js-emitter.d.ts +10 -0
  41. package/src/lib/compiler/js-emitter.js +420 -0
  42. package/src/lib/compiler/js-emitter.js.map +1 -0
  43. package/src/lib/compiler/metadata.d.ts +45 -0
  44. package/src/lib/compiler/metadata.js +633 -0
  45. package/src/lib/compiler/metadata.js.map +1 -0
  46. package/src/lib/compiler/registry.d.ts +49 -0
  47. package/src/lib/compiler/registry.js +164 -0
  48. package/src/lib/compiler/registry.js.map +1 -0
  49. package/src/lib/compiler/resource-inliner.d.ts +21 -0
  50. package/src/lib/compiler/resource-inliner.js +152 -0
  51. package/src/lib/compiler/resource-inliner.js.map +1 -0
  52. package/src/lib/compiler/style-ast.d.ts +8 -0
  53. package/src/lib/compiler/style-ast.js +54 -0
  54. package/src/lib/compiler/style-ast.js.map +1 -0
  55. package/src/lib/compiler/styles.d.ts +13 -0
  56. package/src/lib/compiler/test-helpers.d.ts +7 -0
  57. package/src/lib/compiler/type-elision.d.ts +26 -0
  58. package/src/lib/compiler/type-elision.js +211 -0
  59. package/src/lib/compiler/type-elision.js.map +1 -0
  60. package/src/lib/compiler/utils.d.ts +10 -0
  61. package/src/lib/compiler/utils.js +35 -0
  62. package/src/lib/compiler/utils.js.map +1 -0
  63. package/src/lib/{analog-compiler-plugin.d.ts → fast-compile-plugin.d.ts} +3 -3
  64. package/src/lib/{analog-compiler-plugin.js → fast-compile-plugin.js} +46 -33
  65. package/src/lib/fast-compile-plugin.js.map +1 -0
  66. package/src/lib/utils/virtual-resources.d.ts +16 -0
  67. package/src/lib/utils/virtual-resources.js +31 -2
  68. package/src/lib/utils/virtual-resources.js.map +1 -1
  69. package/src/lib/analog-compiler-plugin.js.map +0 -1
@@ -0,0 +1,146 @@
1
+ import { FIELD_DECORATORS } from "./constants.js";
2
+ //#region packages/vite-plugin-angular/src/lib/compiler/jit-metadata.ts
3
+ /**
4
+ * JIT metadata helpers — OXC AST edition.
5
+ *
6
+ * Builds static metadata arrays that Angular's ReflectionCapabilities reads
7
+ * at runtime for JIT compilation (ctorParameters, propDecorators).
8
+ *
9
+ * Uses source-position slicing instead of AST getText() for speed.
10
+ */
11
+ function getCallApi(call) {
12
+ const callee = call.callee;
13
+ if (!callee) return null;
14
+ if (callee.type === "Identifier") return {
15
+ api: callee.name,
16
+ required: false
17
+ };
18
+ if ((callee.type === "StaticMemberExpression" || callee.type === "MemberExpression") && callee.object?.type === "Identifier" && callee.property?.name === "required") return {
19
+ api: callee.object.name,
20
+ required: true
21
+ };
22
+ return null;
23
+ }
24
+ /**
25
+ * Build ctorParameters for constructor DI in JIT format:
26
+ * [{ type: ServiceA }, { type: ServiceB, decorators: [{type: Optional}] }]
27
+ *
28
+ * Accepts an OXC ClassDeclaration node and the original source string.
29
+ */
30
+ function buildCtorParameters(classNode, sourceCode, typeOnlyImports) {
31
+ const ctor = (classNode.body?.body || []).find((m) => m.type === "MethodDefinition" && m.kind === "constructor");
32
+ if (!ctor) return null;
33
+ const params = ctor.value?.params?.items || ctor.value?.params || [];
34
+ if (params.length === 0) return null;
35
+ const result = [];
36
+ for (const param of params) {
37
+ const parts = [];
38
+ const actualParam = param.type === "TSParameterProperty" ? param.parameter : param;
39
+ const typeAnn = actualParam?.typeAnnotation?.typeAnnotation ?? param?.typeAnnotation?.typeAnnotation;
40
+ let typeName = null;
41
+ if (typeAnn) {
42
+ if (typeAnn.type === "TSTypeReference" && typeAnn.typeName) typeName = typeAnn.typeName.name ?? sourceCode.slice(typeAnn.typeName.start, typeAnn.typeName.end);
43
+ else if (typeAnn.type === "TSUnionType") {
44
+ for (const t of typeAnn.types || []) if (t.type === "TSTypeReference" && t.typeName) {
45
+ typeName = t.typeName.name ?? sourceCode.slice(t.typeName.start, t.typeName.end);
46
+ break;
47
+ }
48
+ }
49
+ }
50
+ if (typeName && !typeOnlyImports.has(typeName)) parts.push(`type: ${typeName}`);
51
+ else parts.push(`type: undefined`);
52
+ const paramDecs = param.decorators || actualParam?.decorators || [];
53
+ if (paramDecs.length > 0) {
54
+ const decEntries = paramDecs.map((dec) => {
55
+ const expr = dec.expression;
56
+ if (!expr || expr.type !== "CallExpression") return "";
57
+ const name = expr.callee?.name;
58
+ if (!name) return "";
59
+ const args = expr.arguments || [];
60
+ if (args.length > 0) return `{type: ${name}, args: [${args.map((a) => sourceCode.slice(a.start, a.end)).join(", ")}]}`;
61
+ return `{type: ${name}}`;
62
+ }).filter(Boolean);
63
+ if (decEntries.length > 0) parts.push(`decorators: [${decEntries.join(", ")}]`);
64
+ }
65
+ result.push(`{${parts.join(", ")}}`);
66
+ }
67
+ return result.join(", ");
68
+ }
69
+ /**
70
+ * Build propDecorators for field decorators + signal API downleveling.
71
+ * Returns a JS object literal string or null if no props.
72
+ *
73
+ * Accepts an OXC ClassDeclaration node and the original source string.
74
+ */
75
+ function buildPropDecorators(classNode, sourceCode) {
76
+ const props = {};
77
+ const members = classNode.body?.body || [];
78
+ for (const member of members) {
79
+ const memberName = member.key?.name;
80
+ if (!memberName) continue;
81
+ const decorators = member.decorators || [];
82
+ for (const dec of decorators) {
83
+ const expr = dec.expression;
84
+ if (!expr || expr.type !== "CallExpression") continue;
85
+ const decName = expr.callee?.name;
86
+ if (!decName || !FIELD_DECORATORS.has(decName)) continue;
87
+ if (!props[memberName]) props[memberName] = [];
88
+ const args = expr.arguments || [];
89
+ if (args.length > 0) props[memberName].push(`{type: ${decName}, args: [${args.map((a) => sourceCode.slice(a.start, a.end)).join(", ")}]}`);
90
+ else props[memberName].push(`{type: ${decName}}`);
91
+ }
92
+ if (member.type === "PropertyDefinition" && member.value?.type === "CallExpression") {
93
+ const signalCall = getCallApi(member.value);
94
+ if (!signalCall) continue;
95
+ const { api, required } = signalCall;
96
+ const args = member.value.arguments || [];
97
+ if (api === "input") {
98
+ if (!props[memberName]) props[memberName] = [];
99
+ const optArg = required ? args[0] : args[1];
100
+ const optParts = [];
101
+ if (optArg?.type === "ObjectExpression") for (const p of optArg.properties || []) {
102
+ if (p.type !== "ObjectProperty" && p.type !== "Property") continue;
103
+ const pKey = p.key?.name || p.key?.value;
104
+ if (pKey === "isSignal" || pKey === "required") continue;
105
+ optParts.push(sourceCode.slice(p.start, p.end));
106
+ }
107
+ optParts.push(`isSignal: true`, `required: ${required}`);
108
+ props[memberName].push(`{type: Input, args: [{${optParts.join(", ")}}]}`);
109
+ } else if (api === "model") {
110
+ if (!props[memberName]) props[memberName] = [];
111
+ props[memberName].push(`{type: Input, args: [{isSignal: true}]}`);
112
+ const changeName = memberName + "Change";
113
+ if (!props[changeName]) props[changeName] = [];
114
+ props[changeName].push(`{type: Output, args: ['${changeName}']}`);
115
+ } else if (api === "output" || api === "outputFromObservable") {
116
+ if (!props[memberName]) props[memberName] = [];
117
+ let alias = null;
118
+ const optArg = args[0];
119
+ if (optArg?.type === "ObjectExpression") {
120
+ for (const p of optArg.properties || []) if ((p.type === "ObjectProperty" || p.type === "Property") && (p.key?.name || p.key?.value) === "alias") {
121
+ if (p.value?.type === "StringLiteral" || p.value?.type === "Literal" && typeof p.value.value === "string") alias = p.value.value;
122
+ }
123
+ }
124
+ if (alias) props[memberName].push(`{type: Output, args: ['${alias}']}`);
125
+ else props[memberName].push(`{type: Output}`);
126
+ } else if (api === "viewChild" || api === "viewChildren") {
127
+ if (!props[memberName]) props[memberName] = [];
128
+ const queryType = api === "viewChildren" ? "ViewChildren" : "ViewChild";
129
+ if (args.length > 0) props[memberName].push(`{type: ${queryType}, args: [${sourceCode.slice(args[0].start, args[0].end)}]}`);
130
+ else props[memberName].push(`{type: ${queryType}}`);
131
+ } else if (api === "contentChild" || api === "contentChildren") {
132
+ if (!props[memberName]) props[memberName] = [];
133
+ const queryType = api === "contentChildren" ? "ContentChildren" : "ContentChild";
134
+ if (args.length > 0) props[memberName].push(`{type: ${queryType}, args: [${sourceCode.slice(args[0].start, args[0].end)}]}`);
135
+ else props[memberName].push(`{type: ${queryType}}`);
136
+ }
137
+ }
138
+ }
139
+ const entries = Object.entries(props);
140
+ if (entries.length === 0) return null;
141
+ return `{${entries.map(([key, decs]) => `${key}: [${decs.join(", ")}]`).join(", ")}}`;
142
+ }
143
+ //#endregion
144
+ export { buildCtorParameters, buildPropDecorators };
145
+
146
+ //# sourceMappingURL=jit-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jit-metadata.js","names":[],"sources":["../../../../src/lib/compiler/jit-metadata.ts"],"sourcesContent":["/**\n * JIT metadata helpers — OXC AST edition.\n *\n * Builds static metadata arrays that Angular's ReflectionCapabilities reads\n * at runtime for JIT compilation (ctorParameters, propDecorators).\n *\n * Uses source-position slicing instead of AST getText() for speed.\n */\nimport { FIELD_DECORATORS } from './constants.js';\n\nfunction getCallApi(call: any): { api: string; required: boolean } | null {\n const callee = call.callee;\n if (!callee) return null;\n\n if (callee.type === 'Identifier') {\n return { api: callee.name, required: false };\n }\n\n if (\n (callee.type === 'StaticMemberExpression' ||\n callee.type === 'MemberExpression') &&\n callee.object?.type === 'Identifier' &&\n callee.property?.name === 'required'\n ) {\n return { api: callee.object.name, required: true };\n }\n\n return null;\n}\n\n/**\n * Build ctorParameters for constructor DI in JIT format:\n * [{ type: ServiceA }, { type: ServiceB, decorators: [{type: Optional}] }]\n *\n * Accepts an OXC ClassDeclaration node and the original source string.\n */\nexport function buildCtorParameters(\n classNode: any,\n sourceCode: string,\n typeOnlyImports: Set<string>,\n): string | null {\n const members: any[] = classNode.body?.body || [];\n const ctor = members.find(\n (m: any) => m.type === 'MethodDefinition' && m.kind === 'constructor',\n );\n if (!ctor) return null;\n\n const params: any[] = ctor.value?.params?.items || ctor.value?.params || [];\n if (params.length === 0) return null;\n\n const result: string[] = [];\n for (const param of params) {\n const parts: string[] = [];\n\n // Handle TSParameterProperty (e.g., constructor(private foo: Bar))\n const actualParam =\n param.type === 'TSParameterProperty' ? param.parameter : param;\n const typeAnn =\n actualParam?.typeAnnotation?.typeAnnotation ??\n param?.typeAnnotation?.typeAnnotation;\n\n // Extract type name from annotation\n let typeName: string | null = null;\n if (typeAnn) {\n if (typeAnn.type === 'TSTypeReference' && typeAnn.typeName) {\n typeName =\n typeAnn.typeName.name ??\n sourceCode.slice(typeAnn.typeName.start, typeAnn.typeName.end);\n } else if (typeAnn.type === 'TSUnionType') {\n for (const t of typeAnn.types || []) {\n if (t.type === 'TSTypeReference' && t.typeName) {\n typeName =\n t.typeName.name ??\n sourceCode.slice(t.typeName.start, t.typeName.end);\n break;\n }\n }\n }\n }\n\n if (typeName && !typeOnlyImports.has(typeName)) {\n parts.push(`type: ${typeName}`);\n } else {\n parts.push(`type: undefined`);\n }\n\n // Extract parameter decorators (may live on TSParameterProperty or the param itself)\n const paramDecs: any[] = param.decorators || actualParam?.decorators || [];\n if (paramDecs.length > 0) {\n const decEntries = paramDecs\n .map((dec: any) => {\n const expr = dec.expression;\n if (!expr || expr.type !== 'CallExpression') return '';\n const name = expr.callee?.name;\n if (!name) return '';\n const args: any[] = expr.arguments || [];\n if (args.length > 0) {\n return `{type: ${name}, args: [${args.map((a: any) => sourceCode.slice(a.start, a.end)).join(', ')}]}`;\n }\n return `{type: ${name}}`;\n })\n .filter(Boolean);\n if (decEntries.length > 0) {\n parts.push(`decorators: [${decEntries.join(', ')}]`);\n }\n }\n\n result.push(`{${parts.join(', ')}}`);\n }\n\n return result.join(', ');\n}\n\n/**\n * Build propDecorators for field decorators + signal API downleveling.\n * Returns a JS object literal string or null if no props.\n *\n * Accepts an OXC ClassDeclaration node and the original source string.\n */\nexport function buildPropDecorators(\n classNode: any,\n sourceCode: string,\n): string | null {\n const props: Record<string, string[]> = {};\n const members: any[] = classNode.body?.body || [];\n\n for (const member of members) {\n const memberName: string | undefined = member.key?.name;\n if (!memberName) continue;\n\n // Check for field decorators (@Input, @Output, @ViewChild, etc.)\n const decorators: any[] = member.decorators || [];\n for (const dec of decorators) {\n const expr = dec.expression;\n if (!expr || expr.type !== 'CallExpression') continue;\n const decName: string | undefined = expr.callee?.name;\n if (!decName || !FIELD_DECORATORS.has(decName)) continue;\n\n if (!props[memberName]) props[memberName] = [];\n const args: any[] = expr.arguments || [];\n if (args.length > 0) {\n props[memberName].push(\n `{type: ${decName}, args: [${args.map((a: any) => sourceCode.slice(a.start, a.end)).join(', ')}]}`,\n );\n } else {\n props[memberName].push(`{type: ${decName}}`);\n }\n }\n\n // Signal API downleveling\n if (\n member.type === 'PropertyDefinition' &&\n member.value?.type === 'CallExpression'\n ) {\n const signalCall = getCallApi(member.value);\n if (!signalCall) continue;\n\n const { api, required } = signalCall;\n const args: any[] = member.value.arguments || [];\n\n if (api === 'input') {\n if (!props[memberName]) props[memberName] = [];\n // Preserve all original options from the input() call and overlay isSignal/required\n const optArg = required ? args[0] : args[1];\n const optParts: string[] = [];\n if (optArg?.type === 'ObjectExpression') {\n for (const p of optArg.properties || []) {\n if (p.type !== 'ObjectProperty' && p.type !== 'Property') continue;\n const pKey = p.key?.name || p.key?.value;\n // Skip isSignal/required — we override them below\n if (pKey === 'isSignal' || pKey === 'required') continue;\n optParts.push(sourceCode.slice(p.start, p.end));\n }\n }\n optParts.push(`isSignal: true`, `required: ${required}`);\n props[memberName].push(\n `{type: Input, args: [{${optParts.join(', ')}}]}`,\n );\n } else if (api === 'model') {\n if (!props[memberName]) props[memberName] = [];\n props[memberName].push(`{type: Input, args: [{isSignal: true}]}`);\n // Model also generates a Change output\n const changeName = memberName + 'Change';\n if (!props[changeName]) props[changeName] = [];\n props[changeName].push(`{type: Output, args: ['${changeName}']}`);\n } else if (api === 'output' || api === 'outputFromObservable') {\n if (!props[memberName]) props[memberName] = [];\n // Extract alias\n let alias: string | null = null;\n const optArg = args[0];\n if (optArg?.type === 'ObjectExpression') {\n for (const p of optArg.properties || []) {\n if (\n (p.type === 'ObjectProperty' || p.type === 'Property') &&\n (p.key?.name || p.key?.value) === 'alias'\n ) {\n if (\n p.value?.type === 'StringLiteral' ||\n (p.value?.type === 'Literal' &&\n typeof p.value.value === 'string')\n ) {\n alias = p.value.value;\n }\n }\n }\n }\n if (alias) {\n props[memberName].push(`{type: Output, args: ['${alias}']}`);\n } else {\n props[memberName].push(`{type: Output}`);\n }\n } else if (api === 'viewChild' || api === 'viewChildren') {\n if (!props[memberName]) props[memberName] = [];\n const queryType = api === 'viewChildren' ? 'ViewChildren' : 'ViewChild';\n if (args.length > 0) {\n props[memberName].push(\n `{type: ${queryType}, args: [${sourceCode.slice(args[0].start, args[0].end)}]}`,\n );\n } else {\n props[memberName].push(`{type: ${queryType}}`);\n }\n } else if (api === 'contentChild' || api === 'contentChildren') {\n if (!props[memberName]) props[memberName] = [];\n const queryType =\n api === 'contentChildren' ? 'ContentChildren' : 'ContentChild';\n if (args.length > 0) {\n props[memberName].push(\n `{type: ${queryType}, args: [${sourceCode.slice(args[0].start, args[0].end)}]}`,\n );\n } else {\n props[memberName].push(`{type: ${queryType}}`);\n }\n }\n }\n }\n\n const entries = Object.entries(props);\n if (entries.length === 0) return null;\n\n const propsStr = entries\n .map(([key, decs]) => `${key}: [${decs.join(', ')}]`)\n .join(', ');\n return `{${propsStr}}`;\n}\n"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ export interface JitTransformResult {
2
+ code: string;
3
+ map: any;
4
+ }
5
+ /**
6
+ * JIT transform for Angular files.
7
+ *
8
+ * Converts Angular decorators to static metadata arrays that Angular's
9
+ * runtime JIT compiler reads via ReflectionCapabilities:
10
+ *
11
+ * - Class.decorators = [{ type: Component, args: [{...}] }]
12
+ * - Class.ctorParameters = () => [{ type: ServiceA, decorators: [{type: Optional}] }]
13
+ * - Class.propDecorators = { name: [{ type: Input }], ... }
14
+ *
15
+ * Also emits ɵfac (factory function) with constructor DI and downlevels
16
+ * signal APIs (input, model, output, viewChild, etc.) to propDecorators.
17
+ *
18
+ * No template compilation — Angular's JIT compiler handles that at runtime.
19
+ * Requires `import '@angular/compiler'` in main.ts for the browser JIT.
20
+ *
21
+ * Uses OXC's native Rust parser instead of TypeScript's parser for ~1.5x
22
+ * faster parsing and source-position slicing instead of getText() calls.
23
+ */
24
+ export declare function jitTransform(sourceCode: string, fileName: string): JitTransformResult;
@@ -0,0 +1,200 @@
1
+ import { ANGULAR_DECORATORS, FIELD_DECORATORS } from "./constants.js";
2
+ import { detectTypeOnlyImportNames } from "./type-elision.js";
3
+ import { buildCtorParameters, buildPropDecorators } from "./jit-metadata.js";
4
+ import { parseSync } from "oxc-parser";
5
+ import MagicString from "magic-string";
6
+ //#region packages/vite-plugin-angular/src/lib/compiler/jit-transform.ts
7
+ /**
8
+ * Recursively find all ClassDeclaration nodes in an OXC AST.
9
+ * Handles top-level, exported, and nested classes (e.g. inside function scopes).
10
+ */
11
+ function findAllClasses(node) {
12
+ const result = [];
13
+ if (!node || typeof node !== "object") return result;
14
+ if (Array.isArray(node)) {
15
+ for (const item of node) result.push(...findAllClasses(item));
16
+ return result;
17
+ }
18
+ if (node.type === "ClassDeclaration" || node.type === "ClassExpression") result.push(node);
19
+ for (const key of Object.keys(node)) {
20
+ if (key === "type" || key === "start" || key === "end" || key === "range" || key === "loc") continue;
21
+ result.push(...findAllClasses(node[key]));
22
+ }
23
+ return result;
24
+ }
25
+ /**
26
+ * JIT transform for Angular files.
27
+ *
28
+ * Converts Angular decorators to static metadata arrays that Angular's
29
+ * runtime JIT compiler reads via ReflectionCapabilities:
30
+ *
31
+ * - Class.decorators = [{ type: Component, args: [{...}] }]
32
+ * - Class.ctorParameters = () => [{ type: ServiceA, decorators: [{type: Optional}] }]
33
+ * - Class.propDecorators = { name: [{ type: Input }], ... }
34
+ *
35
+ * Also emits ɵfac (factory function) with constructor DI and downlevels
36
+ * signal APIs (input, model, output, viewChild, etc.) to propDecorators.
37
+ *
38
+ * No template compilation — Angular's JIT compiler handles that at runtime.
39
+ * Requires `import '@angular/compiler'` in main.ts for the browser JIT.
40
+ *
41
+ * Uses OXC's native Rust parser instead of TypeScript's parser for ~1.5x
42
+ * faster parsing and source-position slicing instead of getText() calls.
43
+ */
44
+ function jitTransform(sourceCode, fileName) {
45
+ const { program } = parseSync(fileName, sourceCode);
46
+ const ms = new MagicString(sourceCode, { filename: fileName });
47
+ const typeOnlyImports = detectTypeOnlyImportNames(sourceCode);
48
+ let hasAngularClass = false;
49
+ const allClasses = findAllClasses(program.body);
50
+ const postClassStatements = [];
51
+ let importCounter = 0;
52
+ const resourceImports = [];
53
+ let needsJitImport = false;
54
+ for (const node of allClasses) {
55
+ const angularDecs = (node.decorators || []).filter((dec) => {
56
+ const expr = dec.expression;
57
+ if (!expr || expr.type !== "CallExpression") return false;
58
+ const name = expr.callee?.name;
59
+ if (name === "Injectable") return false;
60
+ return name !== void 0 && ANGULAR_DECORATORS.has(name);
61
+ });
62
+ if (angularDecs.length === 0) continue;
63
+ const className = node.id?.name;
64
+ if (!className) continue;
65
+ hasAngularClass = true;
66
+ for (const dec of angularDecs) {
67
+ const start = dec.start;
68
+ let trimEnd = dec.end;
69
+ while (trimEnd < sourceCode.length && /\s/.test(sourceCode[trimEnd])) trimEnd++;
70
+ ms.remove(start, trimEnd);
71
+ }
72
+ const decoratorMeta = [];
73
+ const decoratorEntries = angularDecs.map((dec) => {
74
+ const call = dec.expression;
75
+ const decName = call.callee.name;
76
+ const args = call.arguments || [];
77
+ if (args.length > 0 && decName === "Component" && args[0].type === "ObjectExpression") {
78
+ const obj = args[0];
79
+ const rewrittenProps = [];
80
+ for (const prop of obj.properties) {
81
+ if (prop.type !== "ObjectProperty" && prop.type !== "Property") {
82
+ rewrittenProps.push(sourceCode.slice(prop.start, prop.end));
83
+ continue;
84
+ }
85
+ const key = prop.key?.name || prop.key?.value;
86
+ const val = prop.value;
87
+ if (key === "templateUrl" && (val?.type === "StringLiteral" || val?.type === "Literal" && typeof val.value === "string")) {
88
+ const varName = `_jit_tpl_${importCounter++}`;
89
+ resourceImports.push(`import ${varName} from '${val.value}?raw';`);
90
+ rewrittenProps.push(`template: ${varName}`);
91
+ } else if (key === "styleUrl" && (val?.type === "StringLiteral" || val?.type === "Literal" && typeof val.value === "string")) {
92
+ const varName = `_jit_style_${importCounter++}`;
93
+ resourceImports.push(`import ${varName} from '${val.value}?inline';`);
94
+ rewrittenProps.push(`styles: [${varName}]`);
95
+ } else if (key === "styleUrls" && val?.type === "ArrayExpression") {
96
+ const vars = [];
97
+ for (const el of val.elements) if (el?.type === "StringLiteral" || el?.type === "Literal" && typeof el.value === "string") {
98
+ const varName = `_jit_style_${importCounter++}`;
99
+ resourceImports.push(`import ${varName} from '${el.value}?inline';`);
100
+ vars.push(varName);
101
+ }
102
+ rewrittenProps.push(`styles: [${vars.join(", ")}]`);
103
+ } else rewrittenProps.push(sourceCode.slice(prop.start, prop.end));
104
+ }
105
+ const rewrittenArgsText = `{${rewrittenProps.join(", ")}}`;
106
+ decoratorMeta.push({
107
+ name: decName,
108
+ argsText: rewrittenArgsText
109
+ });
110
+ return `{ type: ${decName}, args: [${rewrittenArgsText}] }`;
111
+ }
112
+ if (args.length > 0) {
113
+ const argsText = args.map((a) => sourceCode.slice(a.start, a.end)).join(", ");
114
+ decoratorMeta.push({
115
+ name: decName,
116
+ argsText
117
+ });
118
+ return `{ type: ${decName}, args: [${argsText}] }`;
119
+ }
120
+ decoratorMeta.push({
121
+ name: decName,
122
+ argsText: "{}"
123
+ });
124
+ return `{ type: ${decName} }`;
125
+ });
126
+ postClassStatements.push(`${className}.decorators = [${decoratorEntries.join(", ")}];`);
127
+ for (const dm of decoratorMeta) {
128
+ needsJitImport = true;
129
+ switch (dm.name) {
130
+ case "Component":
131
+ postClassStatements.push(`_jitCompileComponent(${className}, ${dm.argsText});`);
132
+ break;
133
+ case "Directive":
134
+ postClassStatements.push(`_jitCompileDirective(${className}, ${dm.argsText});`);
135
+ break;
136
+ case "Pipe":
137
+ postClassStatements.push(`_jitCompilePipe(${className}, ${dm.argsText});`);
138
+ break;
139
+ case "NgModule":
140
+ postClassStatements.push(`_jitCompileNgModule(${className}, ${dm.argsText});`);
141
+ break;
142
+ }
143
+ }
144
+ const ctorParams = buildCtorParameters(node, sourceCode, typeOnlyImports);
145
+ if (ctorParams) postClassStatements.push(`${className}.ctorParameters = () => [${ctorParams}];`);
146
+ const propDecorators = buildPropDecorators(node, sourceCode);
147
+ if (propDecorators) postClassStatements.push(`${className}.propDecorators = ${propDecorators};`);
148
+ const members = node.body?.body || [];
149
+ for (const member of members) {
150
+ const memberDecs = member.decorators || [];
151
+ for (const dec of memberDecs) {
152
+ const start = dec.start;
153
+ let trimEnd = dec.end;
154
+ while (trimEnd < sourceCode.length && /\s/.test(sourceCode[trimEnd])) trimEnd++;
155
+ ms.remove(start, trimEnd);
156
+ }
157
+ if (member.type === "MethodDefinition" && member.kind === "constructor") {
158
+ const params = member.value?.params?.items || member.value?.params || [];
159
+ for (const param of params) {
160
+ const allParamDecs = [...param.decorators || [], ...param.type === "TSParameterProperty" && param.parameter?.decorators ? param.parameter.decorators : []];
161
+ for (const dec of allParamDecs) {
162
+ const start = dec.start;
163
+ let trimEnd = dec.end;
164
+ while (trimEnd < sourceCode.length && /\s/.test(sourceCode[trimEnd])) trimEnd++;
165
+ ms.remove(start, trimEnd);
166
+ }
167
+ }
168
+ }
169
+ }
170
+ }
171
+ if (!hasAngularClass) return {
172
+ code: sourceCode,
173
+ map: null
174
+ };
175
+ if (resourceImports.length > 0) ms.prepend(resourceImports.join("\n") + "\n");
176
+ const existingImports = /* @__PURE__ */ new Set();
177
+ for (const stmt of program.body) if (stmt.type === "ImportDeclaration" && stmt.source?.value === "@angular/core") {
178
+ for (const spec of stmt.specifiers || []) if (spec.type === "ImportSpecifier") existingImports.add(spec.local?.name || spec.imported?.name);
179
+ }
180
+ const allPostCode = postClassStatements.join("\n");
181
+ const missingDecorators = [];
182
+ for (const dec of FIELD_DECORATORS) if (allPostCode.includes(`type: ${dec}`) && !existingImports.has(dec)) missingDecorators.push(dec);
183
+ if (missingDecorators.length > 0) ms.prepend(`import { ${missingDecorators.join(", ")} } from '@angular/core';\n`);
184
+ if (needsJitImport) ms.prepend(`import { ɵcompileComponent as _jitCompileComponent, ɵcompileDirective as _jitCompileDirective, ɵcompilePipe as _jitCompilePipe, ɵcompileNgModule as _jitCompileNgModule } from '@angular/core';\n`);
185
+ if (postClassStatements.length > 0) ms.append("\n" + postClassStatements.join("\n") + "\n");
186
+ const map = ms.generateMap({
187
+ source: fileName,
188
+ file: fileName + ".js",
189
+ includeContent: true,
190
+ hires: "boundary"
191
+ });
192
+ return {
193
+ code: ms.toString(),
194
+ map
195
+ };
196
+ }
197
+ //#endregion
198
+ export { jitTransform };
199
+
200
+ //# sourceMappingURL=jit-transform.js.map
@@ -0,0 +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 const postClassStatements: 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 on the class — Angular's decorator function\n // self-registers ɵprov (providedIn) at class definition time and\n // there is no ɵcompileInjectable JIT entry point to call instead.\n if (name === 'Injectable') 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 // 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 postClassStatements.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 postClassStatements.push(\n `_jitCompileComponent(${className}, ${dm.argsText});`,\n );\n break;\n case 'Directive':\n postClassStatements.push(\n `_jitCompileDirective(${className}, ${dm.argsText});`,\n );\n break;\n case 'Pipe':\n postClassStatements.push(\n `_jitCompilePipe(${className}, ${dm.argsText});`,\n );\n break;\n case 'NgModule':\n postClassStatements.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 postClassStatements.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 postClassStatements.push(\n `${className}.propDecorators = ${propDecorators};`,\n );\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\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 = postClassStatements.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 // Append all post-class statements at the end\n if (postClassStatements.length > 0) {\n ms.append('\\n' + postClassStatements.join('\\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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"}
@@ -0,0 +1,10 @@
1
+ import * as ts from "typescript";
2
+ import * as o from "@angular/compiler";
3
+ /** Emit Angular output AST expression directly to a JavaScript string. */
4
+ export declare function emitAngularExpr(expr: o.Expression): string;
5
+ /** Emit Angular output AST statement directly to a JavaScript string. */
6
+ export declare function emitAngularStmt(stmt: o.Statement): string;
7
+ /** Set the current source file for WrappedNodeExpr fallback printing. */
8
+ export declare function setEmitterSourceFile(sf: ts.SourceFile | undefined): void;
9
+ /** Set the current source code for OXC-based WrappedNodeExpr slice fallback. */
10
+ export declare function setEmitterSourceCode(code: string | undefined): void;