@zenithbuild/cli 0.6.17 → 0.7.1
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/dist/build/compiler-runtime.d.ts +59 -0
- package/dist/build/compiler-runtime.js +277 -0
- package/dist/build/expression-rewrites.d.ts +88 -0
- package/dist/build/expression-rewrites.js +372 -0
- package/dist/build/hoisted-code-transforms.d.ts +44 -0
- package/dist/build/hoisted-code-transforms.js +316 -0
- package/dist/build/merge-component-ir.d.ts +16 -0
- package/dist/build/merge-component-ir.js +257 -0
- package/dist/build/page-component-loop.d.ts +92 -0
- package/dist/build/page-component-loop.js +257 -0
- package/dist/build/page-ir-normalization.d.ts +23 -0
- package/dist/build/page-ir-normalization.js +370 -0
- package/dist/build/page-loop-metrics.d.ts +100 -0
- package/dist/build/page-loop-metrics.js +131 -0
- package/dist/build/page-loop-state.d.ts +261 -0
- package/dist/build/page-loop-state.js +92 -0
- package/dist/build/page-loop.d.ts +33 -0
- package/dist/build/page-loop.js +217 -0
- package/dist/build/scoped-identifier-rewrite.d.ts +112 -0
- package/dist/build/scoped-identifier-rewrite.js +245 -0
- package/dist/build/server-script.d.ts +41 -0
- package/dist/build/server-script.js +210 -0
- package/dist/build/type-declarations.d.ts +16 -0
- package/dist/build/type-declarations.js +158 -0
- package/dist/build/typescript-expression-utils.d.ts +23 -0
- package/dist/build/typescript-expression-utils.js +272 -0
- package/dist/build.d.ts +10 -18
- package/dist/build.js +74 -2261
- package/dist/component-instance-ir.d.ts +2 -2
- package/dist/component-instance-ir.js +146 -39
- package/dist/component-occurrences.js +63 -15
- package/dist/config.d.ts +66 -0
- package/dist/config.js +86 -0
- package/dist/debug-script.d.ts +1 -0
- package/dist/debug-script.js +8 -0
- package/dist/dev-build-session.d.ts +23 -0
- package/dist/dev-build-session.js +421 -0
- package/dist/dev-server.js +256 -54
- package/dist/framework-components/Image.zen +316 -0
- package/dist/images/materialize.d.ts +17 -0
- package/dist/images/materialize.js +200 -0
- package/dist/images/payload.d.ts +18 -0
- package/dist/images/payload.js +65 -0
- package/dist/images/runtime.d.ts +4 -0
- package/dist/images/runtime.js +254 -0
- package/dist/images/service.d.ts +4 -0
- package/dist/images/service.js +302 -0
- package/dist/images/shared.d.ts +58 -0
- package/dist/images/shared.js +306 -0
- package/dist/index.js +2 -17
- package/dist/manifest.js +45 -0
- package/dist/preview.d.ts +4 -1
- package/dist/preview.js +59 -6
- package/dist/resolve-components.js +20 -3
- package/dist/server-contract.js +3 -2
- package/dist/server-script-composition.d.ts +39 -0
- package/dist/server-script-composition.js +133 -0
- package/dist/startup-profile.d.ts +10 -0
- package/dist/startup-profile.js +62 -0
- package/dist/toolchain-paths.d.ts +1 -0
- package/dist/toolchain-paths.js +31 -0
- package/dist/version-check.d.ts +2 -1
- package/dist/version-check.js +12 -5
- package/package.json +5 -4
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { performance } from 'node:perf_hooks';
|
|
4
|
+
import { applyOccurrenceRewritePlans } from '../component-instance-ir.js';
|
|
5
|
+
import { collectExpandedComponentOccurrences } from '../component-occurrences.js';
|
|
6
|
+
import { expandComponents } from '../resolve-components.js';
|
|
7
|
+
import { composeServerScriptEnvelope, resolveAdjacentServerModules } from '../server-script-composition.js';
|
|
8
|
+
import { createTimedCompilerRunner } from './compiler-runtime.js';
|
|
9
|
+
import { buildComponentExpressionRewrite, mergeExpressionRewriteMaps, resolveRewrittenBindingMetadata } from './expression-rewrites.js';
|
|
10
|
+
import { createPageIrMergeCache } from './merge-component-ir.js';
|
|
11
|
+
import { buildPageOwnerContext, runPageComponentLoop } from './page-component-loop.js';
|
|
12
|
+
import { applyExpressionRewrites, applyScopedIdentifierRewrites, normalizeExpressionBindingDependencies, normalizeExpressionPayload, normalizeHoistedSourcePayload, rewriteLegacyMarkupIdentifiers, rewriteRefBindingIdentifiers, synthesizeSignalBackedCompiledExpressions } from './page-ir-normalization.js';
|
|
13
|
+
import { addBreakdown, emitPageLoopSummary, recordPageProfile } from './page-loop-metrics.js';
|
|
14
|
+
import { applyServerEnvelopeToPageIr, buildOccurrenceCountByPath, createPageBuildState, createPageLoopCaches, createPageLoopExecutionState } from './page-loop-state.js';
|
|
15
|
+
import { buildScopedIdentifierRewrite } from './scoped-identifier-rewrite.js';
|
|
16
|
+
import { extractServerScript } from './server-script.js';
|
|
17
|
+
/**
|
|
18
|
+
* @param {{
|
|
19
|
+
* manifest: Array<{ path: string, file: string }>
|
|
20
|
+
* pagesDir: string
|
|
21
|
+
* srcDir: string
|
|
22
|
+
* registry: Map<string, string>
|
|
23
|
+
* compilerOpts: object
|
|
24
|
+
* compilerBin: string|object
|
|
25
|
+
* softNavigationEnabled: boolean
|
|
26
|
+
* startupProfile: ReturnType<import('../startup-profile.js').createStartupProfiler>
|
|
27
|
+
* compilerTotals: Record<string, number>
|
|
28
|
+
* emitCompilerWarning: (line: string) => void
|
|
29
|
+
* }} input
|
|
30
|
+
* @returns {Promise<{ envelopes: object[], expressionRewriteMetrics: Record<string, number> }>}
|
|
31
|
+
*/
|
|
32
|
+
export async function buildPageEnvelopes(input) {
|
|
33
|
+
const { manifest, pagesDir, srcDir, registry, compilerOpts, compilerBin, softNavigationEnabled, startupProfile, compilerTotals, emitCompilerWarning } = input;
|
|
34
|
+
const cacheState = input.pageLoopCaches || createPageLoopCaches();
|
|
35
|
+
const executionState = createPageLoopExecutionState();
|
|
36
|
+
const { componentIrCache, componentDocumentModeCache, componentExpressionRewriteCache, templateExpressionCache, hoistedCodeTransformCache } = cacheState;
|
|
37
|
+
const { expressionRewriteMetrics, pagePhaseTotals, occurrenceApplyPhaseTotals, bindingResolutionTotals, scopedRewritePhaseTotals, mergePhaseTotals, componentLoopPhaseTotals, pageProfiles, envelopes } = executionState;
|
|
38
|
+
async function cooperativeYield() {
|
|
39
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
40
|
+
}
|
|
41
|
+
const timedRunCompiler = createTimedCompilerRunner(startupProfile, compilerTotals);
|
|
42
|
+
const pageLoopStartedAt = performance.now();
|
|
43
|
+
for (const entry of manifest) {
|
|
44
|
+
const pageStartedAt = performance.now();
|
|
45
|
+
let { pagePhase, pageOccurrenceApplyBreakdown, pageBindingResolutionBreakdown, pageScopedRewriteBreakdown, pageMergeBreakdown, pageComponentLoopBreakdown, pageExpandMs, pageCompileMs, pageOwnerCompileMs, pageComponentCompileMs, pageComponentCacheHits, pageComponentCacheMisses } = createPageBuildState();
|
|
46
|
+
await cooperativeYield();
|
|
47
|
+
const sourceFile = join(pagesDir, entry.file);
|
|
48
|
+
const rawSource = readFileSync(sourceFile, 'utf8');
|
|
49
|
+
const occurrenceCollectStartedAt = performance.now();
|
|
50
|
+
const componentOccurrences = collectExpandedComponentOccurrences(rawSource, registry, sourceFile);
|
|
51
|
+
pagePhase.occurrenceCollectMs = startupProfile.roundMs(performance.now() - occurrenceCollectStartedAt);
|
|
52
|
+
const pageOwnerExtractStartedAt = performance.now();
|
|
53
|
+
const pageOwnerSource = extractServerScript(rawSource, sourceFile, compilerOpts).source;
|
|
54
|
+
pagePhase.serverExtractMs += startupProfile.roundMs(performance.now() - pageOwnerExtractStartedAt);
|
|
55
|
+
const { guardPath: adjacentGuard, loadPath: adjacentLoad } = resolveAdjacentServerModules(sourceFile);
|
|
56
|
+
const expandedStartedAt = performance.now();
|
|
57
|
+
const { expandedSource } = expandComponents(rawSource, registry, sourceFile);
|
|
58
|
+
pageExpandMs = startupProfile.roundMs(performance.now() - expandedStartedAt);
|
|
59
|
+
const expandedServerExtractStartedAt = performance.now();
|
|
60
|
+
const extractedServer = extractServerScript(expandedSource, sourceFile, compilerOpts);
|
|
61
|
+
pagePhase.serverExtractMs += startupProfile.roundMs(performance.now() - expandedServerExtractStartedAt);
|
|
62
|
+
const compileSource = extractedServer.source;
|
|
63
|
+
await cooperativeYield();
|
|
64
|
+
const pageCompileStartedAt = performance.now();
|
|
65
|
+
const pageIr = timedRunCompiler('page', sourceFile, compileSource, compilerOpts, { compilerToolchain: compilerBin, onWarning: emitCompilerWarning });
|
|
66
|
+
pageCompileMs = startupProfile.roundMs(performance.now() - pageCompileStartedAt);
|
|
67
|
+
const composedServer = composeServerScriptEnvelope({
|
|
68
|
+
sourceFile,
|
|
69
|
+
inlineServerScript: extractedServer.serverScript,
|
|
70
|
+
adjacentGuardPath: adjacentGuard,
|
|
71
|
+
adjacentLoadPath: adjacentLoad
|
|
72
|
+
});
|
|
73
|
+
const hasGuard = composedServer.serverScript?.has_guard === true;
|
|
74
|
+
const hasLoad = composedServer.serverScript?.has_load === true;
|
|
75
|
+
applyServerEnvelopeToPageIr({
|
|
76
|
+
pageIr,
|
|
77
|
+
composedServer,
|
|
78
|
+
hasGuard,
|
|
79
|
+
hasLoad,
|
|
80
|
+
entry,
|
|
81
|
+
srcDir,
|
|
82
|
+
sourceFile
|
|
83
|
+
});
|
|
84
|
+
const pageIrMergeCache = createPageIrMergeCache(pageIr);
|
|
85
|
+
const seenStaticImports = new Set();
|
|
86
|
+
const occurrenceCountByPath = buildOccurrenceCountByPath(componentOccurrences);
|
|
87
|
+
const pageExpressionRewriteMap = new Map();
|
|
88
|
+
const pageExpressionBindingMap = new Map();
|
|
89
|
+
const pageAmbiguousExpressionMap = new Set();
|
|
90
|
+
const knownRefKeys = new Set();
|
|
91
|
+
const componentOccurrencePlans = [];
|
|
92
|
+
const { pageOwnerCompileMs: resolvedPageOwnerCompileMs, pageOwnerExpressionRewrite, pageOwnerScopeRewrite } = await buildPageOwnerContext({
|
|
93
|
+
componentOccurrences,
|
|
94
|
+
sourceFile,
|
|
95
|
+
pageOwnerSource,
|
|
96
|
+
compilerOpts,
|
|
97
|
+
compilerBin,
|
|
98
|
+
timedRunCompiler,
|
|
99
|
+
cooperativeYield,
|
|
100
|
+
templateExpressionCache,
|
|
101
|
+
expressionRewriteMetrics,
|
|
102
|
+
startupProfile
|
|
103
|
+
});
|
|
104
|
+
pageOwnerCompileMs = resolvedPageOwnerCompileMs;
|
|
105
|
+
const pageSelfRewriteStartedAt = performance.now();
|
|
106
|
+
const pageSelfExpressionRewrite = buildComponentExpressionRewrite(sourceFile, compileSource, pageIr, compilerOpts, compilerBin, templateExpressionCache, expressionRewriteMetrics);
|
|
107
|
+
pagePhase.selfRewriteMs = startupProfile.roundMs(performance.now() - pageSelfRewriteStartedAt);
|
|
108
|
+
mergeExpressionRewriteMaps(pageExpressionRewriteMap, pageExpressionBindingMap, pageAmbiguousExpressionMap, pageSelfExpressionRewrite, pageIrMergeCache, pageBindingResolutionBreakdown);
|
|
109
|
+
const componentLoopStartedAt = performance.now();
|
|
110
|
+
const pageStats = {
|
|
111
|
+
pageComponentCompileMs,
|
|
112
|
+
pageComponentCacheHits,
|
|
113
|
+
pageComponentCacheMisses
|
|
114
|
+
};
|
|
115
|
+
await runPageComponentLoop({
|
|
116
|
+
componentOccurrences,
|
|
117
|
+
occurrenceCountByPath,
|
|
118
|
+
sourceFile,
|
|
119
|
+
registry,
|
|
120
|
+
compilerOpts,
|
|
121
|
+
compilerBin,
|
|
122
|
+
timedRunCompiler,
|
|
123
|
+
cooperativeYield,
|
|
124
|
+
startupProfile,
|
|
125
|
+
compilerTotals,
|
|
126
|
+
emitCompilerWarning,
|
|
127
|
+
componentIrCache,
|
|
128
|
+
componentDocumentModeCache,
|
|
129
|
+
componentExpressionRewriteCache,
|
|
130
|
+
templateExpressionCache,
|
|
131
|
+
expressionRewriteMetrics,
|
|
132
|
+
pageOwnerExpressionRewrite,
|
|
133
|
+
pageOwnerScopeRewrite,
|
|
134
|
+
pageIr,
|
|
135
|
+
pageIrMergeCache,
|
|
136
|
+
seenStaticImports,
|
|
137
|
+
pageExpressionRewriteMap,
|
|
138
|
+
pageExpressionBindingMap,
|
|
139
|
+
pageAmbiguousExpressionMap,
|
|
140
|
+
knownRefKeys,
|
|
141
|
+
componentOccurrencePlans,
|
|
142
|
+
pagePhase,
|
|
143
|
+
pageBindingResolutionBreakdown,
|
|
144
|
+
pageMergeBreakdown,
|
|
145
|
+
pageComponentLoopBreakdown,
|
|
146
|
+
hoistedCodeTransformCache,
|
|
147
|
+
pageStats
|
|
148
|
+
});
|
|
149
|
+
pageComponentCompileMs = pageStats.pageComponentCompileMs;
|
|
150
|
+
pageComponentCacheHits = pageStats.pageComponentCacheHits;
|
|
151
|
+
pageComponentCacheMisses = pageStats.pageComponentCacheMisses;
|
|
152
|
+
pagePhase.componentLoopMs = startupProfile.roundMs(performance.now() - componentLoopStartedAt);
|
|
153
|
+
const occurrencePlanApplyStartedAt = performance.now();
|
|
154
|
+
applyOccurrenceRewritePlans(pageIr, componentOccurrencePlans, (rewrite, binding) => resolveRewrittenBindingMetadata(pageIrMergeCache, rewrite, binding, pageBindingResolutionBreakdown), pageOccurrenceApplyBreakdown);
|
|
155
|
+
pagePhase.occurrencePlanApplyMs = startupProfile.roundMs(performance.now() - occurrencePlanApplyStartedAt);
|
|
156
|
+
const expressionApplyStartedAt = performance.now();
|
|
157
|
+
applyExpressionRewrites(pageIr, pageExpressionRewriteMap, pageExpressionBindingMap, pageAmbiguousExpressionMap);
|
|
158
|
+
pagePhase.expressionApplyMs = startupProfile.roundMs(performance.now() - expressionApplyStartedAt);
|
|
159
|
+
const scopedRewriteStartedAt = performance.now();
|
|
160
|
+
const scopedRewritePlanStartedAt = performance.now();
|
|
161
|
+
const scopedRewritePlan = buildScopedIdentifierRewrite(pageIr);
|
|
162
|
+
pagePhase.scopedRewritePlanMs = startupProfile.roundMs(performance.now() - scopedRewritePlanStartedAt);
|
|
163
|
+
const scopedRewriteApplyStartedAt = performance.now();
|
|
164
|
+
applyScopedIdentifierRewrites(pageIr, scopedRewritePlan, pageScopedRewriteBreakdown);
|
|
165
|
+
pagePhase.scopedRewriteApplyMs = startupProfile.roundMs(performance.now() - scopedRewriteApplyStartedAt);
|
|
166
|
+
pagePhase.scopedRewriteMs = startupProfile.roundMs(performance.now() - scopedRewriteStartedAt);
|
|
167
|
+
const normalizeStartedAt = performance.now();
|
|
168
|
+
synthesizeSignalBackedCompiledExpressions(pageIr);
|
|
169
|
+
normalizeExpressionPayload(pageIr);
|
|
170
|
+
normalizeHoistedSourcePayload(pageIr);
|
|
171
|
+
normalizeExpressionBindingDependencies(pageIr);
|
|
172
|
+
rewriteLegacyMarkupIdentifiers(pageIr);
|
|
173
|
+
rewriteRefBindingIdentifiers(pageIr, knownRefKeys);
|
|
174
|
+
pagePhase.normalizeMs = startupProfile.roundMs(performance.now() - normalizeStartedAt);
|
|
175
|
+
addBreakdown(pagePhaseTotals, pagePhase);
|
|
176
|
+
addBreakdown(occurrenceApplyPhaseTotals, pageOccurrenceApplyBreakdown);
|
|
177
|
+
addBreakdown(bindingResolutionTotals, pageBindingResolutionBreakdown);
|
|
178
|
+
addBreakdown(scopedRewritePhaseTotals, pageScopedRewriteBreakdown);
|
|
179
|
+
addBreakdown(mergePhaseTotals, pageMergeBreakdown);
|
|
180
|
+
addBreakdown(componentLoopPhaseTotals, pageComponentLoopBreakdown);
|
|
181
|
+
envelopes.push({
|
|
182
|
+
route: entry.path,
|
|
183
|
+
file: sourceFile,
|
|
184
|
+
ir: pageIr,
|
|
185
|
+
router: softNavigationEnabled
|
|
186
|
+
});
|
|
187
|
+
recordPageProfile({
|
|
188
|
+
pageProfiles,
|
|
189
|
+
entry,
|
|
190
|
+
componentOccurrences: componentOccurrences.length,
|
|
191
|
+
pageExpandMs,
|
|
192
|
+
pageCompileMs,
|
|
193
|
+
pageOwnerCompileMs,
|
|
194
|
+
pageComponentCompileMs,
|
|
195
|
+
pageComponentCacheHits,
|
|
196
|
+
pageComponentCacheMisses,
|
|
197
|
+
pagePhase,
|
|
198
|
+
startupProfile,
|
|
199
|
+
pageStartedAt
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
emitPageLoopSummary({
|
|
203
|
+
startupProfile,
|
|
204
|
+
manifest,
|
|
205
|
+
pageLoopStartedAt,
|
|
206
|
+
compilerTotals,
|
|
207
|
+
expressionRewriteMetrics,
|
|
208
|
+
pagePhaseTotals,
|
|
209
|
+
occurrenceApplyPhaseTotals,
|
|
210
|
+
bindingResolutionTotals,
|
|
211
|
+
scopedRewritePhaseTotals,
|
|
212
|
+
mergePhaseTotals,
|
|
213
|
+
componentLoopPhaseTotals,
|
|
214
|
+
pageProfiles
|
|
215
|
+
});
|
|
216
|
+
return { envelopes, expressionRewriteMetrics };
|
|
217
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {object | null | undefined} ir
|
|
3
|
+
* @returns {{ map: Map<string, string>, ambiguous: Set<string> }}
|
|
4
|
+
*/
|
|
5
|
+
export function buildScopedIdentifierRewrite(ir: object | null | undefined): {
|
|
6
|
+
map: Map<string, string>;
|
|
7
|
+
ambiguous: Set<string>;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* @param {string} expr
|
|
11
|
+
* @param {{
|
|
12
|
+
* expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
|
|
13
|
+
* scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
|
|
14
|
+
* } | null} rewriteContext
|
|
15
|
+
* @returns {string}
|
|
16
|
+
*/
|
|
17
|
+
export function rewritePropsExpression(expr: string, rewriteContext?: {
|
|
18
|
+
expressionRewrite?: {
|
|
19
|
+
map?: Map<string, string>;
|
|
20
|
+
ambiguous?: Set<string>;
|
|
21
|
+
} | null;
|
|
22
|
+
scopeRewrite?: {
|
|
23
|
+
map?: Map<string, string>;
|
|
24
|
+
ambiguous?: Set<string>;
|
|
25
|
+
} | null;
|
|
26
|
+
} | null): string;
|
|
27
|
+
/**
|
|
28
|
+
* @param {string | null | undefined} compiledExpr
|
|
29
|
+
* @param {{
|
|
30
|
+
* signals?: Array<{ state_index?: number }>,
|
|
31
|
+
* stateBindings?: Array<{ key?: string }>
|
|
32
|
+
* } | null | undefined} expressionRewrite
|
|
33
|
+
* @returns {string | null}
|
|
34
|
+
*/
|
|
35
|
+
export function resolveCompiledPropsExpression(compiledExpr: string | null | undefined, expressionRewrite?: {
|
|
36
|
+
signals?: Array<{
|
|
37
|
+
state_index?: number;
|
|
38
|
+
}>;
|
|
39
|
+
stateBindings?: Array<{
|
|
40
|
+
key?: string;
|
|
41
|
+
}>;
|
|
42
|
+
} | null | undefined): string | null;
|
|
43
|
+
/**
|
|
44
|
+
* @param {string} expr
|
|
45
|
+
* @param {{
|
|
46
|
+
* expressionRewrite?: {
|
|
47
|
+
* map?: Map<string, string>,
|
|
48
|
+
* bindings?: Map<string, { compiled_expr?: string | null }>,
|
|
49
|
+
* ambiguous?: Set<string>,
|
|
50
|
+
* signals?: Array<{ state_index?: number }>,
|
|
51
|
+
* stateBindings?: Array<{ key?: string }>
|
|
52
|
+
* } | null,
|
|
53
|
+
* scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
|
|
54
|
+
* } | null} rewriteContext
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
57
|
+
export function resolvePropsValueCode(expr: string, rewriteContext?: {
|
|
58
|
+
expressionRewrite?: {
|
|
59
|
+
map?: Map<string, string>;
|
|
60
|
+
bindings?: Map<string, {
|
|
61
|
+
compiled_expr?: string | null;
|
|
62
|
+
}>;
|
|
63
|
+
ambiguous?: Set<string>;
|
|
64
|
+
signals?: Array<{
|
|
65
|
+
state_index?: number;
|
|
66
|
+
}>;
|
|
67
|
+
stateBindings?: Array<{
|
|
68
|
+
key?: string;
|
|
69
|
+
}>;
|
|
70
|
+
} | null;
|
|
71
|
+
scopeRewrite?: {
|
|
72
|
+
map?: Map<string, string>;
|
|
73
|
+
ambiguous?: Set<string>;
|
|
74
|
+
} | null;
|
|
75
|
+
} | null): string;
|
|
76
|
+
/**
|
|
77
|
+
* @param {string} attrs
|
|
78
|
+
* @param {{
|
|
79
|
+
* expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
|
|
80
|
+
* scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
|
|
81
|
+
* } | null} rewriteContext
|
|
82
|
+
* @returns {string}
|
|
83
|
+
*/
|
|
84
|
+
export function renderPropsLiteralFromAttrs(attrs: string, rewriteContext?: {
|
|
85
|
+
expressionRewrite?: {
|
|
86
|
+
map?: Map<string, string>;
|
|
87
|
+
ambiguous?: Set<string>;
|
|
88
|
+
} | null;
|
|
89
|
+
scopeRewrite?: {
|
|
90
|
+
map?: Map<string, string>;
|
|
91
|
+
ambiguous?: Set<string>;
|
|
92
|
+
} | null;
|
|
93
|
+
} | null): string;
|
|
94
|
+
/**
|
|
95
|
+
* @param {string} source
|
|
96
|
+
* @param {string} attrs
|
|
97
|
+
* @param {{
|
|
98
|
+
* expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
|
|
99
|
+
* scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
|
|
100
|
+
* } | null} rewriteContext
|
|
101
|
+
* @returns {string}
|
|
102
|
+
*/
|
|
103
|
+
export function injectPropsPrelude(source: string, attrs: string, rewriteContext?: {
|
|
104
|
+
expressionRewrite?: {
|
|
105
|
+
map?: Map<string, string>;
|
|
106
|
+
ambiguous?: Set<string>;
|
|
107
|
+
} | null;
|
|
108
|
+
scopeRewrite?: {
|
|
109
|
+
map?: Map<string, string>;
|
|
110
|
+
ambiguous?: Set<string>;
|
|
111
|
+
} | null;
|
|
112
|
+
} | null): string;
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { extractDeclaredIdentifiers, normalizeTypeScriptExpression, renderObjectKey, rewriteIdentifiersWithinExpression } from './typescript-expression-utils.js';
|
|
2
|
+
/**
|
|
3
|
+
* @param {string} value
|
|
4
|
+
* @returns {string | null}
|
|
5
|
+
*/
|
|
6
|
+
function deriveScopedIdentifierAlias(value) {
|
|
7
|
+
const ident = String(value || '').trim();
|
|
8
|
+
if (!/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(ident)) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const parts = ident.split('_').filter(Boolean);
|
|
12
|
+
const candidate = parts.length > 1 ? parts[parts.length - 1] : ident;
|
|
13
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(candidate) ? candidate : ident;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @param {Map<string, string>} map
|
|
17
|
+
* @param {Set<string>} ambiguous
|
|
18
|
+
* @param {string | null} raw
|
|
19
|
+
* @param {string | null} rewritten
|
|
20
|
+
*/
|
|
21
|
+
function recordScopedIdentifierRewrite(map, ambiguous, raw, rewritten) {
|
|
22
|
+
if (typeof raw !== 'string' || raw.length === 0 || typeof rewritten !== 'string' || rewritten.length === 0) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const existing = map.get(raw);
|
|
26
|
+
if (existing && existing !== rewritten) {
|
|
27
|
+
map.delete(raw);
|
|
28
|
+
ambiguous.add(raw);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (!ambiguous.has(raw)) {
|
|
32
|
+
map.set(raw, rewritten);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* @param {object | null | undefined} ir
|
|
37
|
+
* @returns {{ map: Map<string, string>, ambiguous: Set<string> }}
|
|
38
|
+
*/
|
|
39
|
+
export function buildScopedIdentifierRewrite(ir) {
|
|
40
|
+
const out = { map: new Map(), ambiguous: new Set() };
|
|
41
|
+
if (!ir || typeof ir !== 'object') {
|
|
42
|
+
return out;
|
|
43
|
+
}
|
|
44
|
+
const stateBindings = Array.isArray(ir?.hoisted?.state) ? ir.hoisted.state : [];
|
|
45
|
+
for (const stateEntry of stateBindings) {
|
|
46
|
+
const key = typeof stateEntry?.key === 'string' ? stateEntry.key : null;
|
|
47
|
+
recordScopedIdentifierRewrite(out.map, out.ambiguous, deriveScopedIdentifierAlias(key), key);
|
|
48
|
+
}
|
|
49
|
+
const functionBindings = Array.isArray(ir?.hoisted?.functions) ? ir.hoisted.functions : [];
|
|
50
|
+
for (const fnName of functionBindings) {
|
|
51
|
+
if (typeof fnName !== 'string') {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
recordScopedIdentifierRewrite(out.map, out.ambiguous, deriveScopedIdentifierAlias(fnName), fnName);
|
|
55
|
+
}
|
|
56
|
+
const declarations = Array.isArray(ir?.hoisted?.declarations) ? ir.hoisted.declarations : [];
|
|
57
|
+
for (const declaration of declarations) {
|
|
58
|
+
if (typeof declaration !== 'string') {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
for (const identifier of extractDeclaredIdentifiers(declaration)) {
|
|
62
|
+
recordScopedIdentifierRewrite(out.map, out.ambiguous, deriveScopedIdentifierAlias(identifier), identifier);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* @param {string} expr
|
|
69
|
+
* @param {{
|
|
70
|
+
* expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
|
|
71
|
+
* scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
|
|
72
|
+
* } | null} rewriteContext
|
|
73
|
+
* @returns {string}
|
|
74
|
+
*/
|
|
75
|
+
export function rewritePropsExpression(expr, rewriteContext = null) {
|
|
76
|
+
const trimmed = String(expr || '').trim();
|
|
77
|
+
if (!trimmed) {
|
|
78
|
+
return trimmed;
|
|
79
|
+
}
|
|
80
|
+
const expressionMap = rewriteContext?.expressionRewrite?.map;
|
|
81
|
+
const expressionAmbiguous = rewriteContext?.expressionRewrite?.ambiguous;
|
|
82
|
+
if (expressionMap instanceof Map &&
|
|
83
|
+
!(expressionAmbiguous instanceof Set && expressionAmbiguous.has(trimmed))) {
|
|
84
|
+
const exact = expressionMap.get(trimmed);
|
|
85
|
+
if (typeof exact === 'string' && exact.length > 0) {
|
|
86
|
+
return normalizeTypeScriptExpression(exact);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const scopeMap = rewriteContext?.scopeRewrite?.map;
|
|
90
|
+
const scopeAmbiguous = rewriteContext?.scopeRewrite?.ambiguous;
|
|
91
|
+
const rootMatch = trimmed.match(/^([A-Za-z_$][A-Za-z0-9_$]*)([\s\S]*)$/);
|
|
92
|
+
if (!(scopeMap instanceof Map)) {
|
|
93
|
+
return normalizeTypeScriptExpression(trimmed);
|
|
94
|
+
}
|
|
95
|
+
if (!rootMatch) {
|
|
96
|
+
return rewriteIdentifiersWithinExpression(trimmed, scopeMap, scopeAmbiguous);
|
|
97
|
+
}
|
|
98
|
+
const root = rootMatch[1];
|
|
99
|
+
if (scopeAmbiguous instanceof Set && scopeAmbiguous.has(root)) {
|
|
100
|
+
return rewriteIdentifiersWithinExpression(trimmed, scopeMap, scopeAmbiguous);
|
|
101
|
+
}
|
|
102
|
+
const rewrittenRoot = scopeMap.get(root);
|
|
103
|
+
if (typeof rewrittenRoot !== 'string' || rewrittenRoot.length === 0 || rewrittenRoot === root) {
|
|
104
|
+
return rewriteIdentifiersWithinExpression(trimmed, scopeMap, scopeAmbiguous);
|
|
105
|
+
}
|
|
106
|
+
if (rootMatch[2].trim().length === 0) {
|
|
107
|
+
return normalizeTypeScriptExpression(rewrittenRoot);
|
|
108
|
+
}
|
|
109
|
+
const rewrittenExpr = rewriteIdentifiersWithinExpression(trimmed, scopeMap, scopeAmbiguous);
|
|
110
|
+
return typeof rewrittenExpr === 'string' && rewrittenExpr.length > 0
|
|
111
|
+
? rewrittenExpr
|
|
112
|
+
: normalizeTypeScriptExpression(`${rewrittenRoot}${rootMatch[2]}`);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* @param {string | null | undefined} compiledExpr
|
|
116
|
+
* @param {{
|
|
117
|
+
* signals?: Array<{ state_index?: number }>,
|
|
118
|
+
* stateBindings?: Array<{ key?: string }>
|
|
119
|
+
* } | null | undefined} expressionRewrite
|
|
120
|
+
* @returns {string | null}
|
|
121
|
+
*/
|
|
122
|
+
export function resolveCompiledPropsExpression(compiledExpr, expressionRewrite = null) {
|
|
123
|
+
const source = typeof compiledExpr === 'string' ? compiledExpr.trim() : '';
|
|
124
|
+
if (!source) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
const signals = Array.isArray(expressionRewrite?.signals) ? expressionRewrite.signals : [];
|
|
128
|
+
const stateBindings = Array.isArray(expressionRewrite?.stateBindings) ? expressionRewrite.stateBindings : [];
|
|
129
|
+
const resolved = source.replace(/signalMap\.get\((\d+)\)(?:\.get\(\))?/g, (full, rawIndex) => {
|
|
130
|
+
const signalIndex = Number.parseInt(rawIndex, 10);
|
|
131
|
+
if (!Number.isInteger(signalIndex)) {
|
|
132
|
+
return full;
|
|
133
|
+
}
|
|
134
|
+
const signal = signals[signalIndex];
|
|
135
|
+
const stateIndex = signal?.state_index;
|
|
136
|
+
const stateKey = Number.isInteger(stateIndex) ? stateBindings[stateIndex]?.key : null;
|
|
137
|
+
if (typeof stateKey !== 'string' || stateKey.length === 0) {
|
|
138
|
+
return full;
|
|
139
|
+
}
|
|
140
|
+
return full.endsWith('.get()') ? `${stateKey}.get()` : stateKey;
|
|
141
|
+
});
|
|
142
|
+
return normalizeTypeScriptExpression(resolved);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* @param {string} expr
|
|
146
|
+
* @param {{
|
|
147
|
+
* expressionRewrite?: {
|
|
148
|
+
* map?: Map<string, string>,
|
|
149
|
+
* bindings?: Map<string, { compiled_expr?: string | null }>,
|
|
150
|
+
* ambiguous?: Set<string>,
|
|
151
|
+
* signals?: Array<{ state_index?: number }>,
|
|
152
|
+
* stateBindings?: Array<{ key?: string }>
|
|
153
|
+
* } | null,
|
|
154
|
+
* scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
|
|
155
|
+
* } | null} rewriteContext
|
|
156
|
+
* @returns {string}
|
|
157
|
+
*/
|
|
158
|
+
export function resolvePropsValueCode(expr, rewriteContext = null) {
|
|
159
|
+
const trimmed = String(expr || '').trim();
|
|
160
|
+
if (!trimmed) {
|
|
161
|
+
return trimmed;
|
|
162
|
+
}
|
|
163
|
+
const expressionRewrite = rewriteContext?.expressionRewrite;
|
|
164
|
+
const expressionAmbiguous = expressionRewrite?.ambiguous;
|
|
165
|
+
if (!(expressionAmbiguous instanceof Set && expressionAmbiguous.has(trimmed))) {
|
|
166
|
+
const binding = expressionRewrite?.bindings instanceof Map
|
|
167
|
+
? expressionRewrite.bindings.get(trimmed)
|
|
168
|
+
: null;
|
|
169
|
+
const compiled = resolveCompiledPropsExpression(binding?.compiled_expr, expressionRewrite);
|
|
170
|
+
if (typeof compiled === 'string' && compiled.length > 0) {
|
|
171
|
+
return compiled;
|
|
172
|
+
}
|
|
173
|
+
const exact = expressionRewrite?.map instanceof Map
|
|
174
|
+
? expressionRewrite.map.get(trimmed)
|
|
175
|
+
: null;
|
|
176
|
+
if (typeof exact === 'string' && exact.length > 0) {
|
|
177
|
+
return normalizeTypeScriptExpression(exact);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return rewritePropsExpression(trimmed, rewriteContext);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* @param {string} attrs
|
|
184
|
+
* @param {{
|
|
185
|
+
* expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
|
|
186
|
+
* scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
|
|
187
|
+
* } | null} rewriteContext
|
|
188
|
+
* @returns {string}
|
|
189
|
+
*/
|
|
190
|
+
export function renderPropsLiteralFromAttrs(attrs, rewriteContext = null) {
|
|
191
|
+
const src = String(attrs || '').trim();
|
|
192
|
+
if (!src) {
|
|
193
|
+
return '{}';
|
|
194
|
+
}
|
|
195
|
+
const entries = [];
|
|
196
|
+
const attrRe = /([A-Za-z_$][A-Za-z0-9_$-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|\{([\s\S]*?)\}))?/g;
|
|
197
|
+
let match;
|
|
198
|
+
while ((match = attrRe.exec(src)) !== null) {
|
|
199
|
+
const rawName = match[1];
|
|
200
|
+
if (!rawName || rawName.startsWith('on:')) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const doubleQuoted = match[2];
|
|
204
|
+
const singleQuoted = match[3];
|
|
205
|
+
const expressionValue = match[4];
|
|
206
|
+
let valueCode = 'true';
|
|
207
|
+
if (doubleQuoted !== undefined) {
|
|
208
|
+
valueCode = JSON.stringify(doubleQuoted);
|
|
209
|
+
}
|
|
210
|
+
else if (singleQuoted !== undefined) {
|
|
211
|
+
valueCode = JSON.stringify(singleQuoted);
|
|
212
|
+
}
|
|
213
|
+
else if (expressionValue !== undefined) {
|
|
214
|
+
const trimmed = String(expressionValue).trim();
|
|
215
|
+
valueCode = trimmed.length > 0 ? resolvePropsValueCode(trimmed, rewriteContext) : 'undefined';
|
|
216
|
+
}
|
|
217
|
+
entries.push(`${renderObjectKey(rawName)}: ${valueCode}`);
|
|
218
|
+
}
|
|
219
|
+
if (entries.length === 0) {
|
|
220
|
+
return '{}';
|
|
221
|
+
}
|
|
222
|
+
return `{ ${entries.join(', ')} }`;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* @param {string} source
|
|
226
|
+
* @param {string} attrs
|
|
227
|
+
* @param {{
|
|
228
|
+
* expressionRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null,
|
|
229
|
+
* scopeRewrite?: { map?: Map<string, string>, ambiguous?: Set<string> } | null
|
|
230
|
+
* } | null} rewriteContext
|
|
231
|
+
* @returns {string}
|
|
232
|
+
*/
|
|
233
|
+
export function injectPropsPrelude(source, attrs, rewriteContext = null) {
|
|
234
|
+
if (typeof source !== 'string' || source.trim().length === 0) {
|
|
235
|
+
return source;
|
|
236
|
+
}
|
|
237
|
+
if (!/\bprops\b/.test(source)) {
|
|
238
|
+
return source;
|
|
239
|
+
}
|
|
240
|
+
if (/\b(?:const|let|var)\s+props\b/.test(source)) {
|
|
241
|
+
return source;
|
|
242
|
+
}
|
|
243
|
+
const propsLiteral = renderPropsLiteralFromAttrs(attrs, rewriteContext);
|
|
244
|
+
return `var props = ${propsLiteral};\n${source}`;
|
|
245
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {string} source
|
|
3
|
+
* @param {string} sourceFile
|
|
4
|
+
* @param {object} [compilerOpts]
|
|
5
|
+
* @returns {{ source: string, serverScript: { source: string, prerender: boolean, has_guard: boolean, has_load: boolean, source_path: string } | null }}
|
|
6
|
+
*/
|
|
7
|
+
export function extractServerScript(source: string, sourceFile: string, compilerOpts?: object): {
|
|
8
|
+
source: string;
|
|
9
|
+
serverScript: {
|
|
10
|
+
source: string;
|
|
11
|
+
prerender: boolean;
|
|
12
|
+
has_guard: boolean;
|
|
13
|
+
has_load: boolean;
|
|
14
|
+
source_path: string;
|
|
15
|
+
} | null;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* @param {string} source
|
|
19
|
+
* @param {Map<string, string>} registry
|
|
20
|
+
* @param {string | null} [ownerPath]
|
|
21
|
+
* @returns {Map<string, Array<{ attrs: string, ownerPath: string | null }>>}
|
|
22
|
+
*/
|
|
23
|
+
export function collectComponentUsageAttrs(source: string, registry: Map<string, string>, ownerPath?: string | null): Map<string, Array<{
|
|
24
|
+
attrs: string;
|
|
25
|
+
ownerPath: string | null;
|
|
26
|
+
}>>;
|
|
27
|
+
/**
|
|
28
|
+
* @param {string} source
|
|
29
|
+
* @param {Map<string, string>} registry
|
|
30
|
+
* @param {string | null} [ownerPath]
|
|
31
|
+
* @param {Set<string>} [visitedFiles]
|
|
32
|
+
* @param {Map<string, Array<{ attrs: string, ownerPath: string | null }>>} [out]
|
|
33
|
+
* @returns {Map<string, Array<{ attrs: string, ownerPath: string | null }>>}
|
|
34
|
+
*/
|
|
35
|
+
export function collectRecursiveComponentUsageAttrs(source: string, registry: Map<string, string>, ownerPath?: string | null, visitedFiles?: Set<string>, out?: Map<string, Array<{
|
|
36
|
+
attrs: string;
|
|
37
|
+
ownerPath: string | null;
|
|
38
|
+
}>>): Map<string, Array<{
|
|
39
|
+
attrs: string;
|
|
40
|
+
ownerPath: string | null;
|
|
41
|
+
}>>;
|