@analogjs/vite-plugin-angular 3.0.0-alpha.7 → 3.0.0-alpha.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/migrations/migrate-setup-vitest/migrate-setup-vitest.d.ts +2 -0
- package/migrations/migrate-setup-vitest/migrate-setup-vitest.js +49 -0
- package/migrations/migrate-setup-vitest/migrate-setup-vitest.js.map +1 -0
- package/migrations/migration.json +7 -1
- package/migrations/migrations.json +9 -0
- package/migrations/update-3-0-0/migrate-setup-vitest.d.ts +2 -0
- package/migrations/update-3-0-0/migrate-setup-vitest.js +36 -0
- package/migrations/update-3-0-0/migrate-setup-vitest.js.map +1 -0
- package/package.json +51 -12
- package/src/index.d.ts +5 -2
- package/src/index.js +6 -2
- package/src/index.js.map +1 -1
- package/src/lib/analog-plugin-interop.d.ts +40 -0
- package/src/lib/analog-plugin-interop.js +61 -0
- package/src/lib/analog-plugin-interop.js.map +1 -0
- package/src/lib/angular-build-optimizer-plugin.d.ts +4 -4
- package/src/lib/angular-build-optimizer-plugin.js +57 -62
- package/src/lib/angular-build-optimizer-plugin.js.map +1 -1
- package/src/lib/angular-jit-plugin.d.ts +3 -3
- package/src/lib/angular-jit-plugin.js +51 -37
- package/src/lib/angular-jit-plugin.js.map +1 -1
- package/src/lib/angular-pending-tasks.plugin.d.ts +7 -7
- package/src/lib/angular-pending-tasks.plugin.js +17 -18
- package/src/lib/angular-pending-tasks.plugin.js.map +1 -1
- package/src/lib/angular-vite-plugin.d.ts +177 -69
- package/src/lib/angular-vite-plugin.js +1227 -1084
- package/src/lib/angular-vite-plugin.js.map +1 -1
- package/src/lib/angular-vitest-plugin.d.ts +26 -17
- package/src/lib/angular-vitest-plugin.js +106 -114
- package/src/lib/angular-vitest-plugin.js.map +1 -1
- package/src/lib/compilation-api/compilation-api-plugin.d.ts +29 -0
- package/src/lib/compilation-api/compilation-api-plugin.js +491 -0
- package/src/lib/compilation-api/compilation-api-plugin.js.map +1 -0
- package/src/lib/compilation-api/index.d.ts +1 -0
- package/src/lib/compilation-api/index.js +1 -0
- package/src/lib/compiler/angular-version.d.ts +19 -0
- package/src/lib/compiler/angular-version.js +31 -0
- package/src/lib/compiler/angular-version.js.map +1 -0
- package/src/lib/compiler/class-field-lowering.d.ts +23 -0
- package/src/lib/compiler/class-field-lowering.js +131 -0
- package/src/lib/compiler/class-field-lowering.js.map +1 -0
- package/src/lib/compiler/compile.d.ts +50 -0
- package/src/lib/compiler/compile.js +814 -0
- package/src/lib/compiler/compile.js.map +1 -0
- package/src/lib/compiler/constants.d.ts +24 -0
- package/src/lib/compiler/constants.js +59 -0
- package/src/lib/compiler/constants.js.map +1 -0
- package/src/lib/compiler/debug.d.ts +22 -0
- package/src/lib/compiler/debug.js +20 -0
- package/src/lib/compiler/debug.js.map +1 -0
- package/src/lib/compiler/defer.d.ts +57 -0
- package/src/lib/compiler/defer.js +154 -0
- package/src/lib/compiler/defer.js.map +1 -0
- package/src/lib/compiler/dts-reader.d.ts +45 -0
- package/src/lib/compiler/dts-reader.js +395 -0
- package/src/lib/compiler/dts-reader.js.map +1 -0
- package/src/lib/compiler/hmr.d.ts +16 -0
- package/src/lib/compiler/hmr.js +69 -0
- package/src/lib/compiler/hmr.js.map +1 -0
- package/src/lib/compiler/index.d.ts +8 -0
- package/src/lib/compiler/index.js +8 -0
- package/src/lib/compiler/jit-metadata.d.ts +14 -0
- package/src/lib/compiler/jit-metadata.js +168 -0
- package/src/lib/compiler/jit-metadata.js.map +1 -0
- package/src/lib/compiler/jit-transform.d.ts +24 -0
- package/src/lib/compiler/jit-transform.js +204 -0
- package/src/lib/compiler/jit-transform.js.map +1 -0
- package/src/lib/compiler/js-emitter.d.ts +10 -0
- package/src/lib/compiler/js-emitter.js +446 -0
- package/src/lib/compiler/js-emitter.js.map +1 -0
- package/src/lib/compiler/metadata.d.ts +36 -0
- package/src/lib/compiler/metadata.js +710 -0
- package/src/lib/compiler/metadata.js.map +1 -0
- package/src/lib/compiler/registry.d.ts +56 -0
- package/src/lib/compiler/registry.js +176 -0
- package/src/lib/compiler/registry.js.map +1 -0
- package/src/lib/compiler/resource-inliner.d.ts +43 -0
- package/src/lib/compiler/resource-inliner.js +230 -0
- package/src/lib/compiler/resource-inliner.js.map +1 -0
- package/src/lib/compiler/style-ast.d.ts +9 -0
- package/src/lib/compiler/style-ast.js +54 -0
- package/src/lib/compiler/style-ast.js.map +1 -0
- package/src/lib/compiler/styles.d.ts +13 -0
- package/src/lib/compiler/test-helpers.d.ts +7 -0
- package/src/lib/compiler/type-elision.d.ts +28 -0
- package/src/lib/compiler/type-elision.js +211 -0
- package/src/lib/compiler/type-elision.js.map +1 -0
- package/src/lib/compiler/utils.d.ts +40 -0
- package/src/lib/compiler/utils.js +76 -0
- package/src/lib/compiler/utils.js.map +1 -0
- package/src/lib/compiler-plugin.d.ts +13 -12
- package/src/lib/compiler-plugin.js +40 -44
- package/src/lib/compiler-plugin.js.map +1 -1
- package/src/lib/component-resolvers.d.ts +23 -5
- package/src/lib/component-resolvers.js +107 -64
- package/src/lib/component-resolvers.js.map +1 -1
- package/src/lib/encapsulation-plugin.d.ts +13 -0
- package/src/lib/encapsulation-plugin.js +48 -0
- package/src/lib/encapsulation-plugin.js.map +1 -0
- package/src/lib/fast-compile-plugin.d.ts +28 -0
- package/src/lib/fast-compile-plugin.js +414 -0
- package/src/lib/fast-compile-plugin.js.map +1 -0
- package/src/lib/host.d.ts +10 -8
- package/src/lib/host.js +113 -101
- package/src/lib/host.js.map +1 -1
- package/src/lib/live-reload-plugin.d.ts +5 -5
- package/src/lib/live-reload-plugin.js +61 -63
- package/src/lib/live-reload-plugin.js.map +1 -1
- package/src/lib/models.d.ts +9 -9
- package/src/lib/nx-folder-plugin.d.ts +5 -5
- package/src/lib/nx-folder-plugin.js +18 -16
- package/src/lib/nx-folder-plugin.js.map +1 -1
- package/src/lib/plugins/file-replacements.plugin.d.ts +4 -4
- package/src/lib/plugins/file-replacements.plugin.js +40 -62
- package/src/lib/plugins/file-replacements.plugin.js.map +1 -1
- package/src/lib/router-plugin.d.ts +1 -1
- package/src/lib/router-plugin.js +35 -23
- package/src/lib/router-plugin.js.map +1 -1
- package/src/lib/style-pipeline.d.ts +15 -0
- package/src/lib/style-pipeline.js +31 -0
- package/src/lib/style-pipeline.js.map +1 -0
- package/src/lib/style-preprocessor.d.ts +35 -0
- package/src/lib/style-preprocessor.js +35 -0
- package/src/lib/style-preprocessor.js.map +1 -0
- package/src/lib/stylesheet-registry.d.ts +74 -0
- package/src/lib/stylesheet-registry.js +174 -0
- package/src/lib/stylesheet-registry.js.map +1 -0
- package/src/lib/tailwind-plugin.d.ts +34 -0
- package/src/lib/tailwind-plugin.js +116 -0
- package/src/lib/tailwind-plugin.js.map +1 -0
- package/src/lib/tools/package.json +2 -7
- package/src/lib/tools/src/builders/vite/vite-build.impl.js +33 -38
- package/src/lib/tools/src/builders/vite/vite-build.impl.js.map +1 -1
- package/src/lib/tools/src/builders/vite-dev-server/dev-server.impl.js +51 -62
- package/src/lib/tools/src/builders/vite-dev-server/dev-server.impl.js.map +1 -1
- package/src/lib/tools/src/index.js +0 -2
- package/src/lib/utils/compilation-shared.d.ts +62 -0
- package/src/lib/utils/compilation-shared.js +138 -0
- package/src/lib/utils/compilation-shared.js.map +1 -0
- package/src/lib/utils/compiler-plugin-options.d.ts +11 -11
- package/src/lib/utils/css-extension-resolver.d.ts +32 -0
- package/src/lib/utils/css-extension-resolver.js +73 -0
- package/src/lib/utils/css-extension-resolver.js.map +1 -0
- package/src/lib/utils/debug-harness.d.ts +23 -0
- package/src/lib/utils/debug-harness.js +88 -0
- package/src/lib/utils/debug-harness.js.map +1 -0
- package/src/lib/utils/debug-log-file.d.ts +5 -0
- package/src/lib/utils/debug-log-file.js +56 -0
- package/src/lib/utils/debug-log-file.js.map +1 -0
- package/src/lib/utils/debug.d.ts +28 -0
- package/src/lib/utils/debug.js +39 -0
- package/src/lib/utils/debug.js.map +1 -0
- package/src/lib/utils/devkit.d.ts +6 -6
- package/src/lib/utils/devkit.js +34 -38
- package/src/lib/utils/devkit.js.map +1 -1
- package/src/lib/utils/hmr-candidates.d.ts +28 -28
- package/src/lib/utils/jit-inline-styles.d.ts +3 -0
- package/src/lib/utils/jit-inline-styles.js +16 -0
- package/src/lib/utils/jit-inline-styles.js.map +1 -0
- package/src/lib/utils/plugin-config.d.ts +41 -0
- package/src/lib/utils/plugin-config.js +85 -0
- package/src/lib/utils/plugin-config.js.map +1 -0
- package/src/lib/utils/rolldown.d.ts +2 -0
- package/src/lib/utils/rolldown.js +12 -0
- package/src/lib/utils/rolldown.js.map +1 -0
- package/src/lib/utils/safe-module-paths.d.ts +16 -0
- package/src/lib/utils/safe-module-paths.js +29 -0
- package/src/lib/utils/safe-module-paths.js.map +1 -0
- package/src/lib/utils/source-file-cache.d.ts +8 -15
- package/src/lib/utils/source-file-cache.js +35 -37
- package/src/lib/utils/source-file-cache.js.map +1 -1
- package/src/lib/utils/tailwind-reference.d.ts +12 -0
- package/src/lib/utils/tailwind-reference.js +99 -0
- package/src/lib/utils/tailwind-reference.js.map +1 -0
- package/src/lib/utils/transform-cache.d.ts +43 -0
- package/src/lib/utils/transform-cache.js +97 -0
- package/src/lib/utils/transform-cache.js.map +1 -0
- package/src/lib/utils/tsconfig-resolver.d.ts +28 -0
- package/src/lib/utils/tsconfig-resolver.js +191 -0
- package/src/lib/utils/tsconfig-resolver.js.map +1 -0
- package/src/lib/utils/virtual-ids.d.ts +4 -0
- package/src/lib/utils/virtual-ids.js +23 -0
- package/src/lib/utils/virtual-ids.js.map +1 -0
- package/src/lib/utils/virtual-resources.d.ts +19 -0
- package/src/lib/utils/virtual-resources.js +38 -0
- package/src/lib/utils/virtual-resources.js.map +1 -0
- package/src/lib/virtual-modules-plugin.d.ts +5 -0
- package/src/lib/virtual-modules-plugin.js +23 -0
- package/src/lib/virtual-modules-plugin.js.map +1 -0
- package/src/test-setup.d.ts +2 -0
- package/setup-vitest.d.ts +0 -4
- package/setup-vitest.js +0 -215
- package/setup-vitest.js.map +0 -1
- package/src/lib/models.js +0 -1
- package/src/lib/models.js.map +0 -1
- package/src/lib/tools/README.md +0 -3
- package/src/lib/tools/src/index.d.ts +0 -0
- package/src/lib/tools/src/index.js.map +0 -1
- package/src/lib/utils/compiler-plugin-options.js +0 -1
- package/src/lib/utils/compiler-plugin-options.js.map +0 -1
- package/src/lib/utils/hmr-candidates.js +0 -272
- package/src/lib/utils/hmr-candidates.js.map +0 -1
|
@@ -0,0 +1,168 @@
|
|
|
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
|
+
* Read a string-literal `alias` value out of an OXC ObjectExpression.
|
|
26
|
+
* Returns null when the arg isn't an object literal, has no alias, or
|
|
27
|
+
* the alias value isn't a static string. Shorthand `{alias}` is skipped
|
|
28
|
+
* because the identifier wouldn't be in scope when the propDecorators
|
|
29
|
+
* static block is evaluated at class top level.
|
|
30
|
+
*/
|
|
31
|
+
function extractAlias(optArg) {
|
|
32
|
+
if (!optArg || optArg.type !== "ObjectExpression") return null;
|
|
33
|
+
for (const p of optArg.properties || []) {
|
|
34
|
+
if (p.type !== "ObjectProperty" && p.type !== "Property") continue;
|
|
35
|
+
if (p.shorthand) continue;
|
|
36
|
+
if ((p.key?.name || p.key?.value) !== "alias") continue;
|
|
37
|
+
const v = p.value;
|
|
38
|
+
if (v?.type === "StringLiteral") return v.value;
|
|
39
|
+
if (v?.type === "Literal" && typeof v.value === "string") return v.value;
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
function escapeStringLiteral(s) {
|
|
44
|
+
return s.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Build ctorParameters for constructor DI in JIT format:
|
|
48
|
+
* [{ type: ServiceA }, { type: ServiceB, decorators: [{type: Optional}] }]
|
|
49
|
+
*
|
|
50
|
+
* Accepts an OXC ClassDeclaration node and the original source string.
|
|
51
|
+
*/
|
|
52
|
+
function buildCtorParameters(classNode, sourceCode, typeOnlyImports) {
|
|
53
|
+
const ctor = (classNode.body?.body || []).find((m) => m.type === "MethodDefinition" && m.kind === "constructor");
|
|
54
|
+
if (!ctor) return null;
|
|
55
|
+
const params = ctor.value?.params?.items || ctor.value?.params || [];
|
|
56
|
+
if (params.length === 0) return null;
|
|
57
|
+
const result = [];
|
|
58
|
+
for (const param of params) {
|
|
59
|
+
const parts = [];
|
|
60
|
+
const actualParam = param.type === "TSParameterProperty" ? param.parameter : param;
|
|
61
|
+
const typeAnn = actualParam?.typeAnnotation?.typeAnnotation ?? param?.typeAnnotation?.typeAnnotation;
|
|
62
|
+
let typeName = null;
|
|
63
|
+
if (typeAnn) {
|
|
64
|
+
if (typeAnn.type === "TSTypeReference" && typeAnn.typeName) typeName = typeAnn.typeName.name ?? sourceCode.slice(typeAnn.typeName.start, typeAnn.typeName.end);
|
|
65
|
+
else if (typeAnn.type === "TSUnionType") {
|
|
66
|
+
for (const t of typeAnn.types || []) if (t.type === "TSTypeReference" && t.typeName) {
|
|
67
|
+
typeName = t.typeName.name ?? sourceCode.slice(t.typeName.start, t.typeName.end);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (typeName && !typeOnlyImports.has(typeName)) parts.push(`type: ${typeName}`);
|
|
73
|
+
else parts.push(`type: undefined`);
|
|
74
|
+
const paramDecs = param.decorators || actualParam?.decorators || [];
|
|
75
|
+
if (paramDecs.length > 0) {
|
|
76
|
+
const decEntries = paramDecs.map((dec) => {
|
|
77
|
+
const expr = dec.expression;
|
|
78
|
+
if (!expr || expr.type !== "CallExpression") return "";
|
|
79
|
+
const name = expr.callee?.name;
|
|
80
|
+
if (!name) return "";
|
|
81
|
+
const args = expr.arguments || [];
|
|
82
|
+
if (args.length > 0) return `{type: ${name}, args: [${args.map((a) => sourceCode.slice(a.start, a.end)).join(", ")}]}`;
|
|
83
|
+
return `{type: ${name}}`;
|
|
84
|
+
}).filter(Boolean);
|
|
85
|
+
if (decEntries.length > 0) parts.push(`decorators: [${decEntries.join(", ")}]`);
|
|
86
|
+
}
|
|
87
|
+
result.push(`{${parts.join(", ")}}`);
|
|
88
|
+
}
|
|
89
|
+
return result.join(", ");
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Build propDecorators for field decorators + signal API downleveling.
|
|
93
|
+
* Returns a JS object literal string or null if no props.
|
|
94
|
+
*
|
|
95
|
+
* Accepts an OXC ClassDeclaration node and the original source string.
|
|
96
|
+
*/
|
|
97
|
+
function buildPropDecorators(classNode, sourceCode) {
|
|
98
|
+
const props = {};
|
|
99
|
+
const members = classNode.body?.body || [];
|
|
100
|
+
for (const member of members) {
|
|
101
|
+
const memberName = member.key?.name;
|
|
102
|
+
if (!memberName) continue;
|
|
103
|
+
const explicitDecoratorNames = /* @__PURE__ */ new Set();
|
|
104
|
+
const decorators = member.decorators || [];
|
|
105
|
+
for (const dec of decorators) {
|
|
106
|
+
const expr = dec.expression;
|
|
107
|
+
if (!expr || expr.type !== "CallExpression") continue;
|
|
108
|
+
const decName = expr.callee?.name;
|
|
109
|
+
if (!decName || !FIELD_DECORATORS.has(decName)) continue;
|
|
110
|
+
explicitDecoratorNames.add(decName);
|
|
111
|
+
if (!props[memberName]) props[memberName] = [];
|
|
112
|
+
const args = expr.arguments || [];
|
|
113
|
+
if (args.length > 0) props[memberName].push(`{type: ${decName}, args: [${args.map((a) => sourceCode.slice(a.start, a.end)).join(", ")}]}`);
|
|
114
|
+
else props[memberName].push(`{type: ${decName}}`);
|
|
115
|
+
}
|
|
116
|
+
if (member.type === "PropertyDefinition" && member.value?.type === "CallExpression") {
|
|
117
|
+
const signalCall = getCallApi(member.value);
|
|
118
|
+
if (!signalCall) continue;
|
|
119
|
+
const { api, required } = signalCall;
|
|
120
|
+
const args = member.value.arguments || [];
|
|
121
|
+
const hasInput = explicitDecoratorNames.has("Input");
|
|
122
|
+
const hasOutput = explicitDecoratorNames.has("Output");
|
|
123
|
+
const hasQuery = explicitDecoratorNames.has("ViewChild") || explicitDecoratorNames.has("ViewChildren") || explicitDecoratorNames.has("ContentChild") || explicitDecoratorNames.has("ContentChildren");
|
|
124
|
+
if (api === "input" && hasInput) continue;
|
|
125
|
+
if (api === "model" && (hasInput || hasOutput)) continue;
|
|
126
|
+
if ((api === "output" || api === "outputFromObservable") && hasOutput) continue;
|
|
127
|
+
if ((api === "viewChild" || api === "viewChildren" || api === "contentChild" || api === "contentChildren") && hasQuery) continue;
|
|
128
|
+
if (api === "input") {
|
|
129
|
+
if (!props[memberName]) props[memberName] = [];
|
|
130
|
+
const optArg = required ? args[0] : args[1];
|
|
131
|
+
const optParts = [];
|
|
132
|
+
if (optArg?.type === "ObjectExpression") for (const p of optArg.properties || []) {
|
|
133
|
+
if (p.type !== "ObjectProperty" && p.type !== "Property") continue;
|
|
134
|
+
if (p.shorthand) continue;
|
|
135
|
+
const pKey = p.key?.name || p.key?.value;
|
|
136
|
+
if (pKey === "isSignal" || pKey === "required" || pKey === "transform") continue;
|
|
137
|
+
optParts.push(sourceCode.slice(p.start, p.end));
|
|
138
|
+
}
|
|
139
|
+
optParts.push(`isSignal: true`, `required: ${required}`);
|
|
140
|
+
props[memberName].push(`{type: Input, args: [{${optParts.join(", ")}}]}`);
|
|
141
|
+
} else if (api === "model") {
|
|
142
|
+
if (!props[memberName]) props[memberName] = [];
|
|
143
|
+
const bindingName = extractAlias(required ? args[0] : args[1]) ?? memberName;
|
|
144
|
+
props[memberName].push(`{type: Input, args: [{isSignal: true, alias: '${escapeStringLiteral(bindingName)}', required: ${required}}]}`);
|
|
145
|
+
props[memberName].push(`{type: Output, args: ['${escapeStringLiteral(bindingName + "Change")}']}`);
|
|
146
|
+
} else if (api === "output" || api === "outputFromObservable") {
|
|
147
|
+
if (!props[memberName]) props[memberName] = [];
|
|
148
|
+
const alias = extractAlias(api === "outputFromObservable" ? args[1] : args[0]);
|
|
149
|
+
if (alias !== null) props[memberName].push(`{type: Output, args: ['${escapeStringLiteral(alias)}']}`);
|
|
150
|
+
else props[memberName].push(`{type: Output}`);
|
|
151
|
+
} else if (api === "viewChild" || api === "viewChildren" || api === "contentChild" || api === "contentChildren") {
|
|
152
|
+
if (!props[memberName]) props[memberName] = [];
|
|
153
|
+
const queryType = api === "viewChildren" ? "ViewChildren" : api === "viewChild" ? "ViewChild" : api === "contentChildren" ? "ContentChildren" : "ContentChild";
|
|
154
|
+
if (args.length > 0) {
|
|
155
|
+
const opts = args.length > 1 ? `{...${sourceCode.slice(args[1].start, args[1].end)}, isSignal: true}` : `{isSignal: true}`;
|
|
156
|
+
props[memberName].push(`{type: ${queryType}, args: [${sourceCode.slice(args[0].start, args[0].end)}, ${opts}]}`);
|
|
157
|
+
} else props[memberName].push(`{type: ${queryType}, args: [undefined, {isSignal: true}]}`);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const entries = Object.entries(props);
|
|
162
|
+
if (entries.length === 0) return null;
|
|
163
|
+
return `{${entries.map(([key, decs]) => `${key}: [${decs.join(", ")}]`).join(", ")}}`;
|
|
164
|
+
}
|
|
165
|
+
//#endregion
|
|
166
|
+
export { buildCtorParameters, buildPropDecorators };
|
|
167
|
+
|
|
168
|
+
//# 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 * Read a string-literal `alias` value out of an OXC ObjectExpression.\n * Returns null when the arg isn't an object literal, has no alias, or\n * the alias value isn't a static string. Shorthand `{alias}` is skipped\n * because the identifier wouldn't be in scope when the propDecorators\n * static block is evaluated at class top level.\n */\nfunction extractAlias(optArg: any): string | null {\n if (!optArg || optArg.type !== 'ObjectExpression') return null;\n for (const p of optArg.properties || []) {\n if (p.type !== 'ObjectProperty' && p.type !== 'Property') continue;\n if (p.shorthand) continue;\n const pKey = p.key?.name || p.key?.value;\n if (pKey !== 'alias') continue;\n const v = p.value;\n if (v?.type === 'StringLiteral') return v.value;\n if (v?.type === 'Literal' && typeof v.value === 'string') return v.value;\n }\n return null;\n}\n\nfunction escapeStringLiteral(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\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 explicitDecoratorNames = new Set<string>();\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 explicitDecoratorNames.add(decName);\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. Skip when a matching explicit decorator\n // is already on the field — Angular's transform bails in that case\n // (input_function.ts, model_function.ts, output_function.ts,\n // query_functions.ts) to avoid duplicate metadata entries.\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 const hasInput = explicitDecoratorNames.has('Input');\n const hasOutput = explicitDecoratorNames.has('Output');\n const hasQuery =\n explicitDecoratorNames.has('ViewChild') ||\n explicitDecoratorNames.has('ViewChildren') ||\n explicitDecoratorNames.has('ContentChild') ||\n explicitDecoratorNames.has('ContentChildren');\n\n if (api === 'input' && hasInput) continue;\n if (api === 'model' && (hasInput || hasOutput)) continue;\n if ((api === 'output' || api === 'outputFromObservable') && hasOutput) {\n continue;\n }\n if (\n (api === 'viewChild' ||\n api === 'viewChildren' ||\n api === 'contentChild' ||\n api === 'contentChildren') &&\n hasQuery\n ) {\n continue;\n }\n\n if (api === 'input') {\n if (!props[memberName]) props[memberName] = [];\n // Preserve original options from the input() call and overlay\n // isSignal/required. `transform` is dropped: the input signal\n // already applies it internally, so forwarding it to the\n // decorator would make Angular's runtime JIT wrap it a second\n // time via the directive metadata's transformFunction slot.\n // Shorthand props ({alias}) are skipped — the identifier\n // wouldn't be in scope when the propDecorators block runs at\n // class top level.\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 if (p.shorthand) continue;\n const pKey = p.key?.name || p.key?.value;\n if (\n pKey === 'isSignal' ||\n pKey === 'required' ||\n pKey === 'transform'\n ) {\n continue;\n }\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 // Both Input and Output must live on the SAME propDecorators key\n // (the class field name). Angular's JIT facade indexes outputs by\n // classPropertyName and reads `instance[classPropertyName]` for\n // the EventEmitter — for a model that's the signal itself, which\n // exposes the emitter via [SIGNAL]. Splitting Output onto a\n // synthetic `<name>Change` key would point at a field that does\n // not exist on the class, breaking two-way bindings.\n if (!props[memberName]) props[memberName] = [];\n const optArg = required ? args[0] : args[1];\n const alias = extractAlias(optArg);\n const bindingName = alias ?? memberName;\n props[memberName].push(\n `{type: Input, args: [{isSignal: true, alias: '${escapeStringLiteral(bindingName)}', required: ${required}}]}`,\n );\n props[memberName].push(\n `{type: Output, args: ['${escapeStringLiteral(bindingName + 'Change')}']}`,\n );\n } else if (api === 'output' || api === 'outputFromObservable') {\n if (!props[memberName]) props[memberName] = [];\n // outputFromObservable(observable, options) — options is args[1].\n // output(options) — options is args[0].\n const optArg = api === 'outputFromObservable' ? args[1] : args[0];\n const alias = extractAlias(optArg);\n if (alias !== null) {\n props[memberName].push(\n `{type: Output, args: ['${escapeStringLiteral(alias)}']}`,\n );\n } else {\n props[memberName].push(`{type: Output}`);\n }\n } else if (\n api === 'viewChild' ||\n api === 'viewChildren' ||\n api === 'contentChild' ||\n api === 'contentChildren'\n ) {\n if (!props[memberName]) props[memberName] = [];\n const queryType =\n api === 'viewChildren'\n ? 'ViewChildren'\n : api === 'viewChild'\n ? 'ViewChild'\n : api === 'contentChildren'\n ? 'ContentChildren'\n : 'ContentChild';\n // Signal queries need `isSignal: true` so the runtime JIT compiler\n // wires them through the signal query infrastructure rather than\n // treating them as plain @ViewChild/@ContentChild assignments.\n // Mirrors Angular's own JIT transform in\n // compiler-cli/.../initializer_api_transforms/query_functions.ts.\n if (args.length > 0) {\n const opts =\n args.length > 1\n ? `{...${sourceCode.slice(args[1].start, args[1].end)}, isSignal: true}`\n : `{isSignal: true}`;\n props[memberName].push(\n `{type: ${queryType}, args: [${sourceCode.slice(args[0].start, args[0].end)}, ${opts}]}`,\n );\n } else {\n props[memberName].push(\n `{type: ${queryType}, args: [undefined, {isSignal: true}]}`,\n );\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,204 @@
|
|
|
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, program);
|
|
48
|
+
let hasAngularClass = false;
|
|
49
|
+
const allClasses = findAllClasses(program.body);
|
|
50
|
+
const allEmittedStatements = [];
|
|
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" || name === "Service") 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
|
+
const classStatements = [];
|
|
67
|
+
for (const dec of angularDecs) {
|
|
68
|
+
const start = dec.start;
|
|
69
|
+
let trimEnd = dec.end;
|
|
70
|
+
while (trimEnd < sourceCode.length && /\s/.test(sourceCode[trimEnd])) trimEnd++;
|
|
71
|
+
ms.remove(start, trimEnd);
|
|
72
|
+
}
|
|
73
|
+
const decoratorMeta = [];
|
|
74
|
+
const decoratorEntries = angularDecs.map((dec) => {
|
|
75
|
+
const call = dec.expression;
|
|
76
|
+
const decName = call.callee.name;
|
|
77
|
+
const args = call.arguments || [];
|
|
78
|
+
if (args.length > 0 && decName === "Component" && args[0].type === "ObjectExpression") {
|
|
79
|
+
const obj = args[0];
|
|
80
|
+
const rewrittenProps = [];
|
|
81
|
+
for (const prop of obj.properties) {
|
|
82
|
+
if (prop.type !== "ObjectProperty" && prop.type !== "Property") {
|
|
83
|
+
rewrittenProps.push(sourceCode.slice(prop.start, prop.end));
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
const key = prop.key?.name || prop.key?.value;
|
|
87
|
+
const val = prop.value;
|
|
88
|
+
if (key === "templateUrl" && (val?.type === "StringLiteral" || val?.type === "Literal" && typeof val.value === "string")) {
|
|
89
|
+
const varName = `_jit_tpl_${importCounter++}`;
|
|
90
|
+
resourceImports.push(`import ${varName} from '${val.value}?raw';`);
|
|
91
|
+
rewrittenProps.push(`template: ${varName}`);
|
|
92
|
+
} else if (key === "styleUrl" && (val?.type === "StringLiteral" || val?.type === "Literal" && typeof val.value === "string")) {
|
|
93
|
+
const varName = `_jit_style_${importCounter++}`;
|
|
94
|
+
resourceImports.push(`import ${varName} from '${val.value}?inline';`);
|
|
95
|
+
rewrittenProps.push(`styles: [${varName}]`);
|
|
96
|
+
} else if (key === "styleUrls" && val?.type === "ArrayExpression") {
|
|
97
|
+
const vars = [];
|
|
98
|
+
for (const el of val.elements) if (el?.type === "StringLiteral" || el?.type === "Literal" && typeof el.value === "string") {
|
|
99
|
+
const varName = `_jit_style_${importCounter++}`;
|
|
100
|
+
resourceImports.push(`import ${varName} from '${el.value}?inline';`);
|
|
101
|
+
vars.push(varName);
|
|
102
|
+
}
|
|
103
|
+
rewrittenProps.push(`styles: [${vars.join(", ")}]`);
|
|
104
|
+
} else rewrittenProps.push(sourceCode.slice(prop.start, prop.end));
|
|
105
|
+
}
|
|
106
|
+
const rewrittenArgsText = `{${rewrittenProps.join(", ")}}`;
|
|
107
|
+
decoratorMeta.push({
|
|
108
|
+
name: decName,
|
|
109
|
+
argsText: rewrittenArgsText
|
|
110
|
+
});
|
|
111
|
+
return `{ type: ${decName}, args: [${rewrittenArgsText}] }`;
|
|
112
|
+
}
|
|
113
|
+
if (args.length > 0) {
|
|
114
|
+
const argsText = args.map((a) => sourceCode.slice(a.start, a.end)).join(", ");
|
|
115
|
+
decoratorMeta.push({
|
|
116
|
+
name: decName,
|
|
117
|
+
argsText
|
|
118
|
+
});
|
|
119
|
+
return `{ type: ${decName}, args: [${argsText}] }`;
|
|
120
|
+
}
|
|
121
|
+
decoratorMeta.push({
|
|
122
|
+
name: decName,
|
|
123
|
+
argsText: "{}"
|
|
124
|
+
});
|
|
125
|
+
return `{ type: ${decName} }`;
|
|
126
|
+
});
|
|
127
|
+
classStatements.push(`${className}.decorators = [${decoratorEntries.join(", ")}];`);
|
|
128
|
+
for (const dm of decoratorMeta) {
|
|
129
|
+
needsJitImport = true;
|
|
130
|
+
switch (dm.name) {
|
|
131
|
+
case "Component":
|
|
132
|
+
classStatements.push(`_jitCompileComponent(${className}, ${dm.argsText});`);
|
|
133
|
+
break;
|
|
134
|
+
case "Directive":
|
|
135
|
+
classStatements.push(`_jitCompileDirective(${className}, ${dm.argsText});`);
|
|
136
|
+
break;
|
|
137
|
+
case "Pipe":
|
|
138
|
+
classStatements.push(`_jitCompilePipe(${className}, ${dm.argsText});`);
|
|
139
|
+
break;
|
|
140
|
+
case "NgModule":
|
|
141
|
+
classStatements.push(`_jitCompileNgModule(${className}, ${dm.argsText});`);
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const ctorParams = buildCtorParameters(node, sourceCode, typeOnlyImports);
|
|
146
|
+
if (ctorParams) classStatements.push(`${className}.ctorParameters = () => [${ctorParams}];`);
|
|
147
|
+
const propDecorators = buildPropDecorators(node, sourceCode);
|
|
148
|
+
if (propDecorators) classStatements.push(`${className}.propDecorators = ${propDecorators};`);
|
|
149
|
+
const members = node.body?.body || [];
|
|
150
|
+
for (const member of members) {
|
|
151
|
+
const memberDecs = member.decorators || [];
|
|
152
|
+
for (const dec of memberDecs) {
|
|
153
|
+
const start = dec.start;
|
|
154
|
+
let trimEnd = dec.end;
|
|
155
|
+
while (trimEnd < sourceCode.length && /\s/.test(sourceCode[trimEnd])) trimEnd++;
|
|
156
|
+
ms.remove(start, trimEnd);
|
|
157
|
+
}
|
|
158
|
+
if (member.type === "MethodDefinition" && member.kind === "constructor") {
|
|
159
|
+
const params = member.value?.params?.items || member.value?.params || [];
|
|
160
|
+
for (const param of params) {
|
|
161
|
+
const allParamDecs = [...param.decorators || [], ...param.type === "TSParameterProperty" && param.parameter?.decorators ? param.parameter.decorators : []];
|
|
162
|
+
for (const dec of allParamDecs) {
|
|
163
|
+
const start = dec.start;
|
|
164
|
+
let trimEnd = dec.end;
|
|
165
|
+
while (trimEnd < sourceCode.length && /\s/.test(sourceCode[trimEnd])) trimEnd++;
|
|
166
|
+
ms.remove(start, trimEnd);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (classStatements.length > 0) {
|
|
172
|
+
allEmittedStatements.push(...classStatements);
|
|
173
|
+
ms.appendLeft(node.end, "\n" + classStatements.join("\n") + "\n");
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (!hasAngularClass) return {
|
|
177
|
+
code: sourceCode,
|
|
178
|
+
map: null
|
|
179
|
+
};
|
|
180
|
+
if (resourceImports.length > 0) ms.prepend(resourceImports.join("\n") + "\n");
|
|
181
|
+
const existingImports = /* @__PURE__ */ new Set();
|
|
182
|
+
for (const stmt of program.body) if (stmt.type === "ImportDeclaration" && stmt.source?.value === "@angular/core") {
|
|
183
|
+
for (const spec of stmt.specifiers || []) if (spec.type === "ImportSpecifier") existingImports.add(spec.local?.name || spec.imported?.name);
|
|
184
|
+
}
|
|
185
|
+
const allPostCode = allEmittedStatements.join("\n");
|
|
186
|
+
const missingDecorators = [];
|
|
187
|
+
for (const dec of FIELD_DECORATORS) if (allPostCode.includes(`type: ${dec}`) && !existingImports.has(dec)) missingDecorators.push(dec);
|
|
188
|
+
if (missingDecorators.length > 0) ms.prepend(`import { ${missingDecorators.join(", ")} } from '@angular/core';\n`);
|
|
189
|
+
if (needsJitImport) ms.prepend(`import { ɵcompileComponent as _jitCompileComponent, ɵcompileDirective as _jitCompileDirective, ɵcompilePipe as _jitCompilePipe, ɵcompileNgModule as _jitCompileNgModule } from '@angular/core';\n`);
|
|
190
|
+
const map = ms.generateMap({
|
|
191
|
+
source: fileName,
|
|
192
|
+
file: fileName + ".js",
|
|
193
|
+
includeContent: true,
|
|
194
|
+
hires: "boundary"
|
|
195
|
+
});
|
|
196
|
+
return {
|
|
197
|
+
code: ms.toString(),
|
|
198
|
+
map
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
//#endregion
|
|
202
|
+
export { jitTransform };
|
|
203
|
+
|
|
204
|
+
//# 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, 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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"}
|
|
@@ -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;
|