@zenithbuild/cli 0.6.6 → 0.6.9
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.d.ts +32 -0
- package/dist/build.js +193 -548
- package/dist/compiler-bridge-runner.d.ts +5 -0
- package/dist/compiler-bridge-runner.js +70 -0
- package/dist/component-instance-ir.d.ts +6 -0
- package/dist/component-instance-ir.js +0 -20
- package/dist/component-occurrences.d.ts +6 -0
- package/dist/component-occurrences.js +6 -28
- package/dist/dev-server.d.ts +18 -0
- package/dist/dev-server.js +65 -114
- package/dist/dev-watch.d.ts +1 -0
- package/dist/dev-watch.js +2 -2
- package/dist/index.d.ts +8 -0
- package/dist/index.js +6 -28
- package/dist/manifest.d.ts +23 -0
- package/dist/manifest.js +22 -48
- package/dist/preview.d.ts +100 -0
- package/dist/preview.js +418 -488
- package/dist/resolve-components.d.ts +39 -0
- package/dist/resolve-components.js +30 -104
- package/dist/server/resolve-request-route.d.ts +39 -0
- package/dist/server/resolve-request-route.js +104 -113
- package/dist/server-contract.d.ts +39 -0
- package/dist/server-contract.js +15 -67
- package/dist/toolchain-paths.d.ts +23 -0
- package/dist/toolchain-paths.js +139 -39
- package/dist/toolchain-runner.d.ts +33 -0
- package/dist/toolchain-runner.js +194 -0
- package/dist/types/generate-env-dts.d.ts +5 -0
- package/dist/types/generate-env-dts.js +4 -2
- package/dist/types/generate-routes-dts.d.ts +8 -0
- package/dist/types/generate-routes-dts.js +7 -5
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.js +16 -7
- package/dist/ui/env.d.ts +18 -0
- package/dist/ui/env.js +0 -12
- package/dist/ui/format.d.ts +33 -0
- package/dist/ui/format.js +8 -46
- package/dist/ui/logger.d.ts +59 -0
- package/dist/ui/logger.js +3 -32
- package/dist/version-check.d.ts +54 -0
- package/dist/version-check.js +41 -98
- package/package.json +6 -4
package/dist/build.js
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
// The CLI does not inspect IR fields and does not write output files.
|
|
11
11
|
// The bundler owns all asset and HTML emission.
|
|
12
12
|
// ---------------------------------------------------------------------------
|
|
13
|
-
|
|
14
13
|
import { spawn, spawnSync } from 'node:child_process';
|
|
15
14
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
16
15
|
import { mkdir, readdir, rm, stat } from 'node:fs/promises';
|
|
@@ -21,11 +20,10 @@ import { buildComponentRegistry, expandComponents, extractTemplate, isDocumentMo
|
|
|
21
20
|
import { collectExpandedComponentOccurrences } from './component-occurrences.js';
|
|
22
21
|
import { applyOccurrenceRewritePlans, cloneComponentIrForInstance } from './component-instance-ir.js';
|
|
23
22
|
import { resolveBundlerBin, resolveCompilerBin } from './toolchain-paths.js';
|
|
23
|
+
import { createBundlerToolchain, createCompilerToolchain, ensureToolchainCompatibility, getActiveToolchainCandidate, runToolchainSync } from './toolchain-runner.js';
|
|
24
24
|
import { maybeWarnAboutZenithVersionMismatch } from './version-check.js';
|
|
25
|
-
|
|
26
25
|
const require = createRequire(import.meta.url);
|
|
27
26
|
let cachedTypeScript = undefined;
|
|
28
|
-
|
|
29
27
|
/**
|
|
30
28
|
* @returns {import('typescript') | null}
|
|
31
29
|
*/
|
|
@@ -33,13 +31,13 @@ function loadTypeScriptApi() {
|
|
|
33
31
|
if (cachedTypeScript === undefined) {
|
|
34
32
|
try {
|
|
35
33
|
cachedTypeScript = require('typescript');
|
|
36
|
-
}
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
37
36
|
cachedTypeScript = null;
|
|
38
37
|
}
|
|
39
38
|
}
|
|
40
39
|
return cachedTypeScript;
|
|
41
40
|
}
|
|
42
|
-
|
|
43
41
|
/**
|
|
44
42
|
* Build a per-build warning emitter that deduplicates repeated compiler lines.
|
|
45
43
|
*
|
|
@@ -57,7 +55,6 @@ export function createCompilerWarningEmitter(sink = (line) => console.warn(line)
|
|
|
57
55
|
sink(text);
|
|
58
56
|
};
|
|
59
57
|
}
|
|
60
|
-
|
|
61
58
|
/**
|
|
62
59
|
* Forward child-process output line-by-line through the structured logger.
|
|
63
60
|
*
|
|
@@ -86,7 +83,6 @@ function forwardStreamLines(stream, onLine) {
|
|
|
86
83
|
}
|
|
87
84
|
});
|
|
88
85
|
}
|
|
89
|
-
|
|
90
86
|
/**
|
|
91
87
|
* Run the compiler process and parse its JSON stdout.
|
|
92
88
|
*
|
|
@@ -99,11 +95,18 @@ function forwardStreamLines(stream, onLine) {
|
|
|
99
95
|
* @param {object} compilerRunOptions
|
|
100
96
|
* @param {(warning: string) => void} [compilerRunOptions.onWarning]
|
|
101
97
|
* @param {boolean} [compilerRunOptions.suppressWarnings]
|
|
102
|
-
* @param {string} [compilerRunOptions.compilerBin]
|
|
98
|
+
* @param {string|object} [compilerRunOptions.compilerBin]
|
|
99
|
+
* @param {object} [compilerRunOptions.compilerToolchain]
|
|
103
100
|
* @returns {object}
|
|
104
101
|
*/
|
|
105
102
|
function runCompiler(filePath, stdinSource, compilerOpts = {}, compilerRunOptions = {}) {
|
|
106
|
-
const
|
|
103
|
+
const compilerToolchain = compilerRunOptions.compilerToolchain
|
|
104
|
+
|| (compilerRunOptions.compilerBin && typeof compilerRunOptions.compilerBin === 'object'
|
|
105
|
+
? compilerRunOptions.compilerBin
|
|
106
|
+
: null);
|
|
107
|
+
const compilerBin = !compilerToolchain && typeof compilerRunOptions.compilerBin === 'string'
|
|
108
|
+
? compilerRunOptions.compilerBin
|
|
109
|
+
: resolveCompilerBin();
|
|
107
110
|
const args = stdinSource !== undefined
|
|
108
111
|
? ['--stdin', filePath]
|
|
109
112
|
: [filePath];
|
|
@@ -117,18 +120,19 @@ function runCompiler(filePath, stdinSource, compilerOpts = {}, compilerRunOption
|
|
|
117
120
|
if (stdinSource !== undefined) {
|
|
118
121
|
opts.input = stdinSource;
|
|
119
122
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
const result = compilerToolchain
|
|
124
|
+
? runToolchainSync(compilerToolchain, args, opts).result
|
|
125
|
+
: (compilerBin
|
|
126
|
+
? spawnSync(compilerBin, args, opts)
|
|
127
|
+
: runToolchainSync(createCompilerToolchain({
|
|
128
|
+
logger: compilerRunOptions.logger || null
|
|
129
|
+
}), args, opts).result);
|
|
123
130
|
if (result.error) {
|
|
124
131
|
throw new Error(`Compiler spawn failed for ${filePath}: ${result.error.message}`);
|
|
125
132
|
}
|
|
126
133
|
if (result.status !== 0) {
|
|
127
|
-
throw new Error(
|
|
128
|
-
`Compiler failed for ${filePath} with exit code ${result.status}\n${result.stderr || ''}`
|
|
129
|
-
);
|
|
134
|
+
throw new Error(`Compiler failed for ${filePath} with exit code ${result.status}\n${result.stderr || ''}`);
|
|
130
135
|
}
|
|
131
|
-
|
|
132
136
|
if (result.stderr && result.stderr.trim().length > 0 && compilerRunOptions.suppressWarnings !== true) {
|
|
133
137
|
const lines = String(result.stderr)
|
|
134
138
|
.split('\n')
|
|
@@ -137,19 +141,19 @@ function runCompiler(filePath, stdinSource, compilerOpts = {}, compilerRunOption
|
|
|
137
141
|
for (const line of lines) {
|
|
138
142
|
if (typeof compilerRunOptions.onWarning === 'function') {
|
|
139
143
|
compilerRunOptions.onWarning(line);
|
|
140
|
-
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
141
146
|
console.warn(line);
|
|
142
147
|
}
|
|
143
148
|
}
|
|
144
149
|
}
|
|
145
|
-
|
|
146
150
|
try {
|
|
147
151
|
return JSON.parse(result.stdout);
|
|
148
|
-
}
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
149
154
|
throw new Error(`Compiler emitted invalid JSON: ${err.message}`);
|
|
150
155
|
}
|
|
151
156
|
}
|
|
152
|
-
|
|
153
157
|
/**
|
|
154
158
|
* Strip component <style> blocks before script-only component IR compilation.
|
|
155
159
|
* Component style emission is handled by page compilation/bundler paths.
|
|
@@ -160,7 +164,6 @@ function runCompiler(filePath, stdinSource, compilerOpts = {}, compilerRunOption
|
|
|
160
164
|
function stripStyleBlocks(source) {
|
|
161
165
|
return String(source || '').replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, '');
|
|
162
166
|
}
|
|
163
|
-
|
|
164
167
|
/**
|
|
165
168
|
* Build a deterministic raw->rewritten expression map for a component by
|
|
166
169
|
* comparing template-only expressions with script-aware expressions.
|
|
@@ -169,7 +172,7 @@ function stripStyleBlocks(source) {
|
|
|
169
172
|
* @param {string} componentSource
|
|
170
173
|
* @param {object} compIr
|
|
171
174
|
* @param {object} compilerOpts
|
|
172
|
-
* @param {string} compilerBin
|
|
175
|
+
* @param {string|object} compilerBin
|
|
173
176
|
* @returns {{
|
|
174
177
|
* map: Map<string, string>,
|
|
175
178
|
* bindings: Map<string, {
|
|
@@ -199,22 +202,20 @@ function buildComponentExpressionRewrite(compPath, componentSource, compIr, comp
|
|
|
199
202
|
if (rewrittenExpressions.length === 0) {
|
|
200
203
|
return out;
|
|
201
204
|
}
|
|
202
|
-
|
|
203
205
|
const templateOnly = extractTemplate(componentSource);
|
|
204
206
|
if (!templateOnly.trim()) {
|
|
205
207
|
return out;
|
|
206
208
|
}
|
|
207
|
-
|
|
208
209
|
let templateIr;
|
|
209
210
|
try {
|
|
210
211
|
templateIr = runCompiler(compPath, templateOnly, compilerOpts, {
|
|
211
212
|
suppressWarnings: true,
|
|
212
|
-
compilerBin
|
|
213
|
+
compilerToolchain: compilerBin
|
|
213
214
|
});
|
|
214
|
-
}
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
215
217
|
return out;
|
|
216
218
|
}
|
|
217
|
-
|
|
218
219
|
const rawExpressions = Array.isArray(templateIr?.expressions) ? templateIr.expressions : [];
|
|
219
220
|
const count = Math.min(rawExpressions.length, rewrittenExpressions.length);
|
|
220
221
|
for (let i = 0; i < count; i++) {
|
|
@@ -223,7 +224,6 @@ function buildComponentExpressionRewrite(compPath, componentSource, compIr, comp
|
|
|
223
224
|
if (typeof raw !== 'string' || typeof rewritten !== 'string') {
|
|
224
225
|
continue;
|
|
225
226
|
}
|
|
226
|
-
|
|
227
227
|
const binding = rewrittenBindings[i];
|
|
228
228
|
const normalizedBinding = binding && typeof binding === 'object'
|
|
229
229
|
? {
|
|
@@ -237,13 +237,11 @@ function buildComponentExpressionRewrite(compPath, componentSource, compIr, comp
|
|
|
237
237
|
component_binding: typeof binding.component_binding === 'string' ? binding.component_binding : null
|
|
238
238
|
}
|
|
239
239
|
: null;
|
|
240
|
-
|
|
241
240
|
out.sequence.push({
|
|
242
241
|
raw,
|
|
243
242
|
rewritten,
|
|
244
243
|
binding: normalizedBinding
|
|
245
244
|
});
|
|
246
|
-
|
|
247
245
|
if (!out.ambiguous.has(raw) && normalizedBinding) {
|
|
248
246
|
const existingBinding = out.bindings.get(raw);
|
|
249
247
|
if (existingBinding) {
|
|
@@ -253,11 +251,11 @@ function buildComponentExpressionRewrite(compPath, componentSource, compIr, comp
|
|
|
253
251
|
out.ambiguous.add(raw);
|
|
254
252
|
continue;
|
|
255
253
|
}
|
|
256
|
-
}
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
257
256
|
out.bindings.set(raw, normalizedBinding);
|
|
258
257
|
}
|
|
259
258
|
}
|
|
260
|
-
|
|
261
259
|
if (raw !== rewritten) {
|
|
262
260
|
const existing = out.map.get(raw);
|
|
263
261
|
if (existing && existing !== rewritten) {
|
|
@@ -271,15 +269,12 @@ function buildComponentExpressionRewrite(compPath, componentSource, compIr, comp
|
|
|
271
269
|
}
|
|
272
270
|
}
|
|
273
271
|
}
|
|
274
|
-
|
|
275
272
|
return out;
|
|
276
273
|
}
|
|
277
|
-
|
|
278
274
|
function remapCompiledExpressionSignals(compiledExpr, componentSignals, componentStateBindings, pageSignalIndexByStateKey) {
|
|
279
275
|
if (typeof compiledExpr !== 'string' || compiledExpr.length === 0) {
|
|
280
276
|
return null;
|
|
281
277
|
}
|
|
282
|
-
|
|
283
278
|
return compiledExpr.replace(/signalMap\.get\((\d+)\)/g, (full, rawIndex) => {
|
|
284
279
|
const localIndex = Number.parseInt(rawIndex, 10);
|
|
285
280
|
if (!Number.isInteger(localIndex)) {
|
|
@@ -300,24 +295,20 @@ function remapCompiledExpressionSignals(compiledExpr, componentSignals, componen
|
|
|
300
295
|
return `signalMap.get(${pageIndex})`;
|
|
301
296
|
});
|
|
302
297
|
}
|
|
303
|
-
|
|
304
298
|
function resolveRewrittenBindingMetadata(pageIr, componentRewrite, binding) {
|
|
305
299
|
if (!binding || typeof binding !== 'object') {
|
|
306
300
|
return null;
|
|
307
301
|
}
|
|
308
|
-
|
|
309
302
|
const pageStateBindings = Array.isArray(pageIr?.hoisted?.state) ? pageIr.hoisted.state : [];
|
|
310
303
|
const pageSignals = Array.isArray(pageIr?.signals) ? pageIr.signals : [];
|
|
311
304
|
const pageStateIndexByKey = new Map();
|
|
312
305
|
const pageSignalIndexByStateKey = new Map();
|
|
313
|
-
|
|
314
306
|
for (let index = 0; index < pageStateBindings.length; index++) {
|
|
315
307
|
const key = pageStateBindings[index]?.key;
|
|
316
308
|
if (typeof key === 'string' && key.length > 0 && !pageStateIndexByKey.has(key)) {
|
|
317
309
|
pageStateIndexByKey.set(key, index);
|
|
318
310
|
}
|
|
319
311
|
}
|
|
320
|
-
|
|
321
312
|
for (let index = 0; index < pageSignals.length; index++) {
|
|
322
313
|
const stateIndex = pageSignals[index]?.state_index;
|
|
323
314
|
if (!Number.isInteger(stateIndex)) {
|
|
@@ -328,32 +319,27 @@ function resolveRewrittenBindingMetadata(pageIr, componentRewrite, binding) {
|
|
|
328
319
|
pageSignalIndexByStateKey.set(stateKey, index);
|
|
329
320
|
}
|
|
330
321
|
}
|
|
331
|
-
|
|
332
322
|
const componentSignals = Array.isArray(componentRewrite?.signals) ? componentRewrite.signals : [];
|
|
333
323
|
const componentStateBindings = Array.isArray(componentRewrite?.stateBindings) ? componentRewrite.stateBindings : [];
|
|
334
|
-
|
|
335
324
|
let signalIndices = Array.isArray(binding.signal_indices)
|
|
336
|
-
? [...new Set(
|
|
337
|
-
binding.signal_indices
|
|
325
|
+
? [...new Set(binding.signal_indices
|
|
338
326
|
.map((signalIndex) => {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
.filter((value) => Number.isInteger(value))
|
|
354
|
-
)].sort((a, b) => a - b)
|
|
327
|
+
if (!Number.isInteger(signalIndex)) {
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
330
|
+
const signal = componentSignals[signalIndex];
|
|
331
|
+
if (!signal || !Number.isInteger(signal.state_index)) {
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
const stateKey = componentStateBindings[signal.state_index]?.key;
|
|
335
|
+
if (typeof stateKey !== 'string' || stateKey.length === 0) {
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
const pageIndex = pageSignalIndexByStateKey.get(stateKey);
|
|
339
|
+
return Number.isInteger(pageIndex) ? pageIndex : null;
|
|
340
|
+
})
|
|
341
|
+
.filter((value) => Number.isInteger(value)))].sort((a, b) => a - b)
|
|
355
342
|
: [];
|
|
356
|
-
|
|
357
343
|
let signalIndex = null;
|
|
358
344
|
if (Number.isInteger(binding.signal_index)) {
|
|
359
345
|
const signal = componentSignals[binding.signal_index];
|
|
@@ -366,47 +352,32 @@ function resolveRewrittenBindingMetadata(pageIr, componentRewrite, binding) {
|
|
|
366
352
|
if (signalIndex === null && signalIndices.length === 1) {
|
|
367
353
|
signalIndex = signalIndices[0];
|
|
368
354
|
}
|
|
369
|
-
|
|
370
355
|
let stateIndex = null;
|
|
371
356
|
if (Number.isInteger(binding.state_index)) {
|
|
372
357
|
const stateKey = componentStateBindings[binding.state_index]?.key;
|
|
373
358
|
const pageIndex = typeof stateKey === 'string' ? pageStateIndexByKey.get(stateKey) : null;
|
|
374
359
|
stateIndex = Number.isInteger(pageIndex) ? pageIndex : null;
|
|
375
360
|
}
|
|
376
|
-
|
|
377
361
|
if (Number.isInteger(stateIndex)) {
|
|
378
362
|
const fallbackSignalIndices = pageSignals
|
|
379
363
|
.map((signal, index) => signal?.state_index === stateIndex ? index : null)
|
|
380
364
|
.filter((value) => Number.isInteger(value));
|
|
381
|
-
const signalIndicesMatchState = signalIndices.every(
|
|
382
|
-
(index) => pageSignals[index]?.state_index === stateIndex
|
|
383
|
-
);
|
|
365
|
+
const signalIndicesMatchState = signalIndices.every((index) => pageSignals[index]?.state_index === stateIndex);
|
|
384
366
|
if ((!signalIndicesMatchState || signalIndices.length === 0) && fallbackSignalIndices.length > 0) {
|
|
385
367
|
signalIndices = fallbackSignalIndices;
|
|
386
368
|
}
|
|
387
|
-
if (
|
|
388
|
-
|
|
389
|
-
fallbackSignalIndices.length === 1
|
|
390
|
-
) {
|
|
369
|
+
if ((signalIndex === null || pageSignals[signalIndex]?.state_index !== stateIndex) &&
|
|
370
|
+
fallbackSignalIndices.length === 1) {
|
|
391
371
|
signalIndex = fallbackSignalIndices[0];
|
|
392
372
|
}
|
|
393
373
|
}
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
binding.compiled_expr,
|
|
397
|
-
componentSignals,
|
|
398
|
-
componentStateBindings,
|
|
399
|
-
pageSignalIndexByStateKey
|
|
400
|
-
);
|
|
401
|
-
if (
|
|
402
|
-
typeof compiledExpr === 'string' &&
|
|
374
|
+
let compiledExpr = remapCompiledExpressionSignals(binding.compiled_expr, componentSignals, componentStateBindings, pageSignalIndexByStateKey);
|
|
375
|
+
if (typeof compiledExpr === 'string' &&
|
|
403
376
|
signalIndices.length === 1 &&
|
|
404
377
|
Array.isArray(binding.signal_indices) &&
|
|
405
|
-
binding.signal_indices.length <= 1
|
|
406
|
-
) {
|
|
378
|
+
binding.signal_indices.length <= 1) {
|
|
407
379
|
compiledExpr = compiledExpr.replace(/signalMap\.get\(\d+\)/g, `signalMap.get(${signalIndices[0]})`);
|
|
408
380
|
}
|
|
409
|
-
|
|
410
381
|
return {
|
|
411
382
|
compiled_expr: compiledExpr,
|
|
412
383
|
signal_index: signalIndex,
|
|
@@ -416,7 +387,6 @@ function resolveRewrittenBindingMetadata(pageIr, componentRewrite, binding) {
|
|
|
416
387
|
component_binding: typeof binding.component_binding === 'string' ? binding.component_binding : null
|
|
417
388
|
};
|
|
418
389
|
}
|
|
419
|
-
|
|
420
390
|
/**
|
|
421
391
|
* Merge a per-component rewrite table into the page-level rewrite table.
|
|
422
392
|
*
|
|
@@ -452,7 +422,6 @@ function mergeExpressionRewriteMaps(pageMap, pageBindingMap, pageAmbiguous, comp
|
|
|
452
422
|
pageMap.delete(raw);
|
|
453
423
|
pageBindingMap.delete(raw);
|
|
454
424
|
}
|
|
455
|
-
|
|
456
425
|
for (const [raw, binding] of componentRewrite.bindings.entries()) {
|
|
457
426
|
if (pageAmbiguous.has(raw)) {
|
|
458
427
|
continue;
|
|
@@ -467,7 +436,6 @@ function mergeExpressionRewriteMaps(pageMap, pageBindingMap, pageAmbiguous, comp
|
|
|
467
436
|
}
|
|
468
437
|
pageBindingMap.set(raw, resolved);
|
|
469
438
|
}
|
|
470
|
-
|
|
471
439
|
for (const [raw, rewritten] of componentRewrite.map.entries()) {
|
|
472
440
|
if (pageAmbiguous.has(raw)) {
|
|
473
441
|
continue;
|
|
@@ -482,47 +450,38 @@ function mergeExpressionRewriteMaps(pageMap, pageBindingMap, pageAmbiguous, comp
|
|
|
482
450
|
pageMap.set(raw, rewritten);
|
|
483
451
|
}
|
|
484
452
|
}
|
|
485
|
-
|
|
486
453
|
function resolveStateKeyFromBindings(identifier, stateBindings, preferredKeys = null) {
|
|
487
454
|
const ident = String(identifier || '').trim();
|
|
488
455
|
if (!ident) {
|
|
489
456
|
return null;
|
|
490
457
|
}
|
|
491
|
-
|
|
492
458
|
const exact = stateBindings.find((entry) => String(entry?.key || '') === ident);
|
|
493
459
|
if (exact && typeof exact.key === 'string') {
|
|
494
460
|
return exact.key;
|
|
495
461
|
}
|
|
496
|
-
|
|
497
462
|
const suffix = `_${ident}`;
|
|
498
463
|
const matches = stateBindings
|
|
499
464
|
.map((entry) => String(entry?.key || ''))
|
|
500
465
|
.filter((key) => key.endsWith(suffix));
|
|
501
|
-
|
|
502
466
|
if (preferredKeys instanceof Set && preferredKeys.size > 0) {
|
|
503
467
|
const preferredMatches = matches.filter((key) => preferredKeys.has(key));
|
|
504
468
|
if (preferredMatches.length === 1) {
|
|
505
469
|
return preferredMatches[0];
|
|
506
470
|
}
|
|
507
471
|
}
|
|
508
|
-
|
|
509
472
|
if (matches.length === 1) {
|
|
510
473
|
return matches[0];
|
|
511
474
|
}
|
|
512
|
-
|
|
513
475
|
return null;
|
|
514
476
|
}
|
|
515
|
-
|
|
516
477
|
function rewriteRefBindingIdentifiers(pageIr, preferredKeys = null) {
|
|
517
478
|
if (!Array.isArray(pageIr?.ref_bindings) || pageIr.ref_bindings.length === 0) {
|
|
518
479
|
return;
|
|
519
480
|
}
|
|
520
|
-
|
|
521
481
|
const stateBindings = Array.isArray(pageIr?.hoisted?.state) ? pageIr.hoisted.state : [];
|
|
522
482
|
if (stateBindings.length === 0) {
|
|
523
483
|
return;
|
|
524
484
|
}
|
|
525
|
-
|
|
526
485
|
for (const binding of pageIr.ref_bindings) {
|
|
527
486
|
if (!binding || typeof binding !== 'object' || typeof binding.identifier !== 'string') {
|
|
528
487
|
continue;
|
|
@@ -533,7 +492,6 @@ function rewriteRefBindingIdentifiers(pageIr, preferredKeys = null) {
|
|
|
533
492
|
}
|
|
534
493
|
}
|
|
535
494
|
}
|
|
536
|
-
|
|
537
495
|
/**
|
|
538
496
|
* Rewrite unresolved page expressions using component script-aware mappings.
|
|
539
497
|
*
|
|
@@ -554,7 +512,6 @@ function applyExpressionRewrites(pageIr, expressionMap, bindingMap, ambiguous) {
|
|
|
554
512
|
return;
|
|
555
513
|
}
|
|
556
514
|
const bindings = Array.isArray(pageIr.expression_bindings) ? pageIr.expression_bindings : [];
|
|
557
|
-
|
|
558
515
|
for (let index = 0; index < pageIr.expressions.length; index++) {
|
|
559
516
|
const current = pageIr.expressions[index];
|
|
560
517
|
if (typeof current !== 'string') {
|
|
@@ -563,21 +520,17 @@ function applyExpressionRewrites(pageIr, expressionMap, bindingMap, ambiguous) {
|
|
|
563
520
|
if (ambiguous.has(current)) {
|
|
564
521
|
continue;
|
|
565
522
|
}
|
|
566
|
-
|
|
567
523
|
const rewritten = expressionMap.get(current);
|
|
568
524
|
const rewrittenBinding = bindingMap.get(current);
|
|
569
525
|
if (rewritten && rewritten !== current) {
|
|
570
526
|
pageIr.expressions[index] = rewritten;
|
|
571
527
|
}
|
|
572
|
-
|
|
573
528
|
if (!bindings[index] || typeof bindings[index] !== 'object') {
|
|
574
529
|
continue;
|
|
575
530
|
}
|
|
576
|
-
|
|
577
531
|
if (rewritten && rewritten !== current && bindings[index].literal === current) {
|
|
578
532
|
bindings[index].literal = rewritten;
|
|
579
533
|
}
|
|
580
|
-
|
|
581
534
|
if (rewrittenBinding) {
|
|
582
535
|
bindings[index].compiled_expr = rewrittenBinding.compiled_expr;
|
|
583
536
|
bindings[index].signal_index = rewrittenBinding.signal_index;
|
|
@@ -585,21 +538,18 @@ function applyExpressionRewrites(pageIr, expressionMap, bindingMap, ambiguous) {
|
|
|
585
538
|
bindings[index].state_index = rewrittenBinding.state_index;
|
|
586
539
|
bindings[index].component_instance = rewrittenBinding.component_instance;
|
|
587
540
|
bindings[index].component_binding = rewrittenBinding.component_binding;
|
|
588
|
-
}
|
|
541
|
+
}
|
|
542
|
+
else if (rewritten && rewritten !== current && bindings[index].compiled_expr === current) {
|
|
589
543
|
bindings[index].compiled_expr = rewritten;
|
|
590
544
|
}
|
|
591
|
-
|
|
592
|
-
if (
|
|
593
|
-
!rewrittenBinding &&
|
|
545
|
+
if (!rewrittenBinding &&
|
|
594
546
|
(!rewritten || rewritten === current) &&
|
|
595
547
|
bindings[index].literal === current &&
|
|
596
|
-
bindings[index].compiled_expr === current
|
|
597
|
-
) {
|
|
548
|
+
bindings[index].compiled_expr === current) {
|
|
598
549
|
bindings[index].compiled_expr = current;
|
|
599
550
|
}
|
|
600
551
|
}
|
|
601
552
|
}
|
|
602
|
-
|
|
603
553
|
function applyScopedIdentifierRewrites(pageIr, scopeRewrite) {
|
|
604
554
|
if (!Array.isArray(pageIr?.expressions) || pageIr.expressions.length === 0) {
|
|
605
555
|
return;
|
|
@@ -608,17 +558,14 @@ function applyScopedIdentifierRewrites(pageIr, scopeRewrite) {
|
|
|
608
558
|
const rewriteContext = {
|
|
609
559
|
scopeRewrite
|
|
610
560
|
};
|
|
611
|
-
|
|
612
561
|
for (let index = 0; index < pageIr.expressions.length; index++) {
|
|
613
562
|
const current = pageIr.expressions[index];
|
|
614
563
|
if (typeof current === 'string') {
|
|
615
564
|
pageIr.expressions[index] = rewritePropsExpression(current, rewriteContext);
|
|
616
565
|
}
|
|
617
|
-
|
|
618
566
|
if (!bindings[index] || typeof bindings[index] !== 'object') {
|
|
619
567
|
continue;
|
|
620
568
|
}
|
|
621
|
-
|
|
622
569
|
if (typeof bindings[index].literal === 'string') {
|
|
623
570
|
bindings[index].literal = rewritePropsExpression(bindings[index].literal, rewriteContext);
|
|
624
571
|
}
|
|
@@ -627,18 +574,15 @@ function applyScopedIdentifierRewrites(pageIr, scopeRewrite) {
|
|
|
627
574
|
}
|
|
628
575
|
}
|
|
629
576
|
}
|
|
630
|
-
|
|
631
577
|
function synthesizeSignalBackedCompiledExpressions(pageIr) {
|
|
632
578
|
if (!Array.isArray(pageIr?.expression_bindings) || pageIr.expression_bindings.length === 0) {
|
|
633
579
|
return;
|
|
634
580
|
}
|
|
635
|
-
|
|
636
581
|
const stateBindings = Array.isArray(pageIr?.hoisted?.state) ? pageIr.hoisted.state : [];
|
|
637
582
|
const signals = Array.isArray(pageIr?.signals) ? pageIr.signals : [];
|
|
638
583
|
if (stateBindings.length === 0 || signals.length === 0) {
|
|
639
584
|
return;
|
|
640
585
|
}
|
|
641
|
-
|
|
642
586
|
const signalIndexByStateKey = new Map();
|
|
643
587
|
for (let index = 0; index < signals.length; index++) {
|
|
644
588
|
const stateIndex = signals[index]?.state_index;
|
|
@@ -650,7 +594,6 @@ function synthesizeSignalBackedCompiledExpressions(pageIr) {
|
|
|
650
594
|
if (signalIndexByStateKey.size === 0) {
|
|
651
595
|
return;
|
|
652
596
|
}
|
|
653
|
-
|
|
654
597
|
for (let index = 0; index < pageIr.expression_bindings.length; index++) {
|
|
655
598
|
const binding = pageIr.expression_bindings[index];
|
|
656
599
|
if (!binding || typeof binding !== 'object') {
|
|
@@ -659,7 +602,6 @@ function synthesizeSignalBackedCompiledExpressions(pageIr) {
|
|
|
659
602
|
if (typeof binding.compiled_expr === 'string' && binding.compiled_expr.includes('signalMap.get(')) {
|
|
660
603
|
continue;
|
|
661
604
|
}
|
|
662
|
-
|
|
663
605
|
const candidate = typeof binding.literal === 'string' && binding.literal.trim().length > 0
|
|
664
606
|
? binding.literal
|
|
665
607
|
: typeof pageIr.expressions?.[index] === 'string'
|
|
@@ -668,7 +610,6 @@ function synthesizeSignalBackedCompiledExpressions(pageIr) {
|
|
|
668
610
|
if (typeof candidate !== 'string' || candidate.trim().length === 0) {
|
|
669
611
|
continue;
|
|
670
612
|
}
|
|
671
|
-
|
|
672
613
|
let rewritten = candidate;
|
|
673
614
|
const signalIndices = [];
|
|
674
615
|
for (const [stateKey, signalIndex] of signalIndexByStateKey.entries()) {
|
|
@@ -683,11 +624,9 @@ function synthesizeSignalBackedCompiledExpressions(pageIr) {
|
|
|
683
624
|
rewritten = rewritten.replace(pattern, `signalMap.get(${signalIndex}).get()`);
|
|
684
625
|
signalIndices.push(signalIndex);
|
|
685
626
|
}
|
|
686
|
-
|
|
687
627
|
if (rewritten === candidate || signalIndices.length === 0) {
|
|
688
628
|
continue;
|
|
689
629
|
}
|
|
690
|
-
|
|
691
630
|
const uniqueSignalIndices = [...new Set(signalIndices)].sort((a, b) => a - b);
|
|
692
631
|
binding.compiled_expr = rewritten;
|
|
693
632
|
binding.signal_indices = uniqueSignalIndices;
|
|
@@ -700,20 +639,16 @@ function synthesizeSignalBackedCompiledExpressions(pageIr) {
|
|
|
700
639
|
}
|
|
701
640
|
}
|
|
702
641
|
}
|
|
703
|
-
|
|
704
642
|
function normalizeExpressionBindingDependencies(pageIr) {
|
|
705
643
|
if (!Array.isArray(pageIr?.expression_bindings) || pageIr.expression_bindings.length === 0) {
|
|
706
644
|
return;
|
|
707
645
|
}
|
|
708
|
-
|
|
709
646
|
const signals = Array.isArray(pageIr.signals) ? pageIr.signals : [];
|
|
710
647
|
const dependencyRe = /signalMap\.get\((\d+)\)/g;
|
|
711
|
-
|
|
712
648
|
for (const binding of pageIr.expression_bindings) {
|
|
713
649
|
if (!binding || typeof binding !== 'object' || typeof binding.compiled_expr !== 'string') {
|
|
714
650
|
continue;
|
|
715
651
|
}
|
|
716
|
-
|
|
717
652
|
const indices = [];
|
|
718
653
|
dependencyRe.lastIndex = 0;
|
|
719
654
|
let match;
|
|
@@ -723,36 +658,28 @@ function normalizeExpressionBindingDependencies(pageIr) {
|
|
|
723
658
|
indices.push(index);
|
|
724
659
|
}
|
|
725
660
|
}
|
|
726
|
-
|
|
727
661
|
if (indices.length === 0) {
|
|
728
662
|
continue;
|
|
729
663
|
}
|
|
730
|
-
|
|
731
664
|
let signalIndices = [...new Set(indices)].sort((a, b) => a - b);
|
|
732
665
|
if (Number.isInteger(binding.state_index)) {
|
|
733
666
|
const owningSignalIndices = signals
|
|
734
667
|
.map((signal, index) => signal?.state_index === binding.state_index ? index : null)
|
|
735
668
|
.filter((value) => Number.isInteger(value));
|
|
736
|
-
const extractedMatchState =
|
|
737
|
-
signalIndices.length > 0 &&
|
|
669
|
+
const extractedMatchState = signalIndices.length > 0 &&
|
|
738
670
|
signalIndices.every((index) => signals[index]?.state_index === binding.state_index);
|
|
739
671
|
if (owningSignalIndices.length > 0 && !extractedMatchState) {
|
|
740
672
|
signalIndices = owningSignalIndices;
|
|
741
673
|
}
|
|
742
674
|
}
|
|
743
|
-
|
|
744
|
-
if (
|
|
745
|
-
!Array.isArray(binding.signal_indices) ||
|
|
675
|
+
if (!Array.isArray(binding.signal_indices) ||
|
|
746
676
|
binding.signal_indices.length === 0 ||
|
|
747
|
-
binding.signal_indices.some((index) => signals[index]?.state_index !== binding.state_index)
|
|
748
|
-
) {
|
|
677
|
+
binding.signal_indices.some((index) => signals[index]?.state_index !== binding.state_index)) {
|
|
749
678
|
binding.signal_indices = signalIndices;
|
|
750
679
|
}
|
|
751
|
-
if (
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
signalIndices.length === 1
|
|
755
|
-
) {
|
|
680
|
+
if ((!Number.isInteger(binding.signal_index) ||
|
|
681
|
+
signals[binding.signal_index]?.state_index !== binding.state_index) &&
|
|
682
|
+
signalIndices.length === 1) {
|
|
756
683
|
binding.signal_index = signalIndices[0];
|
|
757
684
|
}
|
|
758
685
|
if (!Number.isInteger(binding.state_index) && Number.isInteger(binding.signal_index)) {
|
|
@@ -762,14 +689,10 @@ function normalizeExpressionBindingDependencies(pageIr) {
|
|
|
762
689
|
}
|
|
763
690
|
}
|
|
764
691
|
if (signalIndices.length === 1) {
|
|
765
|
-
binding.compiled_expr = binding.compiled_expr.replace(
|
|
766
|
-
/signalMap\.get\(\d+\)/g,
|
|
767
|
-
`signalMap.get(${signalIndices[0]})`
|
|
768
|
-
);
|
|
692
|
+
binding.compiled_expr = binding.compiled_expr.replace(/signalMap\.get\(\d+\)/g, `signalMap.get(${signalIndices[0]})`);
|
|
769
693
|
}
|
|
770
694
|
}
|
|
771
695
|
}
|
|
772
|
-
|
|
773
696
|
/**
|
|
774
697
|
* Rewrite legacy markup-literal identifiers in expression literals to the
|
|
775
698
|
* internal `__ZENITH_INTERNAL_ZENHTML` binding used by the runtime.
|
|
@@ -784,39 +707,32 @@ function normalizeExpressionBindingDependencies(pageIr) {
|
|
|
784
707
|
// Stored as concatenation so the drift gate scanner does not flag build.js itself.
|
|
785
708
|
const _LEGACY_MARKUP_IDENT = 'zen' + 'html';
|
|
786
709
|
const _LEGACY_MARKUP_RE = new RegExp(`\\b${_LEGACY_MARKUP_IDENT}\\b`, 'g');
|
|
787
|
-
|
|
788
710
|
function rewriteLegacyMarkupIdentifiers(pageIr) {
|
|
789
711
|
if (!Array.isArray(pageIr?.expressions) || pageIr.expressions.length === 0) {
|
|
790
712
|
return;
|
|
791
713
|
}
|
|
792
714
|
const bindings = Array.isArray(pageIr.expression_bindings) ? pageIr.expression_bindings : [];
|
|
793
|
-
|
|
794
715
|
for (let i = 0; i < pageIr.expressions.length; i++) {
|
|
795
716
|
if (typeof pageIr.expressions[i] === 'string' && pageIr.expressions[i].includes(_LEGACY_MARKUP_IDENT)) {
|
|
796
717
|
_LEGACY_MARKUP_RE.lastIndex = 0;
|
|
797
718
|
pageIr.expressions[i] = pageIr.expressions[i].replace(_LEGACY_MARKUP_RE, '__ZENITH_INTERNAL_ZENHTML');
|
|
798
719
|
}
|
|
799
|
-
if (
|
|
800
|
-
bindings[i] &&
|
|
720
|
+
if (bindings[i] &&
|
|
801
721
|
typeof bindings[i] === 'object' &&
|
|
802
722
|
typeof bindings[i].literal === 'string' &&
|
|
803
|
-
bindings[i].literal.includes(_LEGACY_MARKUP_IDENT)
|
|
804
|
-
) {
|
|
723
|
+
bindings[i].literal.includes(_LEGACY_MARKUP_IDENT)) {
|
|
805
724
|
_LEGACY_MARKUP_RE.lastIndex = 0;
|
|
806
725
|
bindings[i].literal = bindings[i].literal.replace(_LEGACY_MARKUP_RE, '__ZENITH_INTERNAL_ZENHTML');
|
|
807
726
|
}
|
|
808
|
-
if (
|
|
809
|
-
bindings[i] &&
|
|
727
|
+
if (bindings[i] &&
|
|
810
728
|
typeof bindings[i] === 'object' &&
|
|
811
729
|
typeof bindings[i].compiled_expr === 'string' &&
|
|
812
|
-
bindings[i].compiled_expr.includes(_LEGACY_MARKUP_IDENT)
|
|
813
|
-
) {
|
|
730
|
+
bindings[i].compiled_expr.includes(_LEGACY_MARKUP_IDENT)) {
|
|
814
731
|
_LEGACY_MARKUP_RE.lastIndex = 0;
|
|
815
732
|
bindings[i].compiled_expr = bindings[i].compiled_expr.replace(_LEGACY_MARKUP_RE, '__ZENITH_INTERNAL_ZENHTML');
|
|
816
733
|
}
|
|
817
734
|
}
|
|
818
735
|
}
|
|
819
|
-
|
|
820
736
|
/**
|
|
821
737
|
* @param {string} targetPath
|
|
822
738
|
* @param {string} next
|
|
@@ -828,7 +744,6 @@ function writeIfChanged(targetPath, next) {
|
|
|
828
744
|
}
|
|
829
745
|
writeFileSync(targetPath, next, 'utf8');
|
|
830
746
|
}
|
|
831
|
-
|
|
832
747
|
/**
|
|
833
748
|
* @param {string} routePath
|
|
834
749
|
* @returns {string}
|
|
@@ -852,7 +767,6 @@ function routeParamsType(routePath) {
|
|
|
852
767
|
}
|
|
853
768
|
return `{ ${fields.join(', ')} }`;
|
|
854
769
|
}
|
|
855
|
-
|
|
856
770
|
/**
|
|
857
771
|
* @param {Array<{ path: string, file: string }>} manifest
|
|
858
772
|
* @returns {string}
|
|
@@ -866,13 +780,10 @@ function renderZenithRouteDts(manifest) {
|
|
|
866
780
|
' namespace Zenith {',
|
|
867
781
|
' interface RouteParamsMap {'
|
|
868
782
|
];
|
|
869
|
-
|
|
870
783
|
const sortedManifest = [...manifest].sort((a, b) => a.path.localeCompare(b.path));
|
|
871
|
-
|
|
872
784
|
for (const entry of sortedManifest) {
|
|
873
785
|
lines.push(` ${JSON.stringify(entry.path)}: ${routeParamsType(entry.path)};`);
|
|
874
786
|
}
|
|
875
|
-
|
|
876
787
|
lines.push(' }');
|
|
877
788
|
lines.push('');
|
|
878
789
|
lines.push(' type ParamsFor<P extends keyof RouteParamsMap> = RouteParamsMap[P];');
|
|
@@ -881,7 +792,6 @@ function renderZenithRouteDts(manifest) {
|
|
|
881
792
|
lines.push('');
|
|
882
793
|
return `${lines.join('\n')}\n`;
|
|
883
794
|
}
|
|
884
|
-
|
|
885
795
|
/**
|
|
886
796
|
* @returns {string}
|
|
887
797
|
*/
|
|
@@ -936,7 +846,6 @@ function renderZenithEnvDts() {
|
|
|
936
846
|
''
|
|
937
847
|
].join('\n');
|
|
938
848
|
}
|
|
939
|
-
|
|
940
849
|
/**
|
|
941
850
|
* @param {string} pagesDir
|
|
942
851
|
* @returns {string}
|
|
@@ -949,7 +858,6 @@ function deriveProjectRootFromPagesDir(pagesDir) {
|
|
|
949
858
|
}
|
|
950
859
|
return parent;
|
|
951
860
|
}
|
|
952
|
-
|
|
953
861
|
/**
|
|
954
862
|
* @param {{ manifest: Array<{ path: string, file: string }>, pagesDir: string }} input
|
|
955
863
|
* @returns {Promise<void>}
|
|
@@ -958,12 +866,10 @@ async function ensureZenithTypeDeclarations(input) {
|
|
|
958
866
|
const projectRoot = deriveProjectRootFromPagesDir(input.pagesDir);
|
|
959
867
|
const zenithDir = resolve(projectRoot, '.zenith');
|
|
960
868
|
await mkdir(zenithDir, { recursive: true });
|
|
961
|
-
|
|
962
869
|
const envPath = join(zenithDir, 'zenith-env.d.ts');
|
|
963
870
|
const routesPath = join(zenithDir, 'zenith-routes.d.ts');
|
|
964
871
|
writeIfChanged(envPath, renderZenithEnvDts());
|
|
965
872
|
writeIfChanged(routesPath, renderZenithRouteDts(input.manifest));
|
|
966
|
-
|
|
967
873
|
const tsconfigPath = resolve(projectRoot, 'tsconfig.json');
|
|
968
874
|
if (!existsSync(tsconfigPath)) {
|
|
969
875
|
return;
|
|
@@ -977,11 +883,11 @@ async function ensureZenithTypeDeclarations(input) {
|
|
|
977
883
|
parsed.include = include;
|
|
978
884
|
writeIfChanged(tsconfigPath, `${JSON.stringify(parsed, null, 2)}\n`);
|
|
979
885
|
}
|
|
980
|
-
}
|
|
886
|
+
}
|
|
887
|
+
catch {
|
|
981
888
|
// Non-JSON tsconfig variants are left untouched.
|
|
982
889
|
}
|
|
983
890
|
}
|
|
984
|
-
|
|
985
891
|
/**
|
|
986
892
|
* Extract one optional `<script server>` block from a page source.
|
|
987
893
|
* Returns source with the block removed plus normalized server metadata.
|
|
@@ -994,131 +900,94 @@ async function ensureZenithTypeDeclarations(input) {
|
|
|
994
900
|
function extractServerScript(source, sourceFile, compilerOpts = {}) {
|
|
995
901
|
const scriptRe = /<script\b([^>]*)>([\s\S]*?)<\/script>/gi;
|
|
996
902
|
const serverMatches = [];
|
|
997
|
-
const reservedServerExportRe =
|
|
998
|
-
/\bexport\s+const\s+(?:data|prerender|guard|load)\b|\bexport\s+(?:async\s+)?function\s+(?:load|guard)\s*\(|\bexport\s+const\s+(?:load|guard)\s*=/;
|
|
999
|
-
|
|
903
|
+
const reservedServerExportRe = /\bexport\s+const\s+(?:data|prerender|guard|load)\b|\bexport\s+(?:async\s+)?function\s+(?:load|guard)\s*\(|\bexport\s+const\s+(?:load|guard)\s*=/;
|
|
1000
904
|
for (const match of source.matchAll(scriptRe)) {
|
|
1001
905
|
const attrs = String(match[1] || '');
|
|
1002
906
|
const body = String(match[2] || '');
|
|
1003
907
|
const isServer = /\bserver\b/i.test(attrs);
|
|
1004
|
-
|
|
1005
908
|
if (!isServer && reservedServerExportRe.test(body)) {
|
|
1006
|
-
throw new Error(
|
|
1007
|
-
`Zenith server script contract violation:\n` +
|
|
909
|
+
throw new Error(`Zenith server script contract violation:\n` +
|
|
1008
910
|
` File: ${sourceFile}\n` +
|
|
1009
911
|
` Reason: guard/load/data exports are only allowed in <script server lang="ts"> or adjacent .guard.ts / .load.ts files\n` +
|
|
1010
|
-
` Example: move the export into <script server lang="ts">`
|
|
1011
|
-
);
|
|
912
|
+
` Example: move the export into <script server lang="ts">`);
|
|
1012
913
|
}
|
|
1013
|
-
|
|
1014
914
|
if (isServer) {
|
|
1015
915
|
serverMatches.push(match);
|
|
1016
916
|
}
|
|
1017
917
|
}
|
|
1018
|
-
|
|
1019
918
|
if (serverMatches.length === 0) {
|
|
1020
919
|
return { source, serverScript: null };
|
|
1021
920
|
}
|
|
1022
|
-
|
|
1023
921
|
if (serverMatches.length > 1) {
|
|
1024
|
-
throw new Error(
|
|
1025
|
-
`Zenith server script contract violation:\n` +
|
|
922
|
+
throw new Error(`Zenith server script contract violation:\n` +
|
|
1026
923
|
` File: ${sourceFile}\n` +
|
|
1027
924
|
` Reason: multiple <script server> blocks are not supported\n` +
|
|
1028
|
-
` Example: keep exactly one <script server>...</script> block`
|
|
1029
|
-
);
|
|
925
|
+
` Example: keep exactly one <script server>...</script> block`);
|
|
1030
926
|
}
|
|
1031
|
-
|
|
1032
927
|
const match = serverMatches[0];
|
|
1033
928
|
const full = match[0] || '';
|
|
1034
929
|
const attrs = String(match[1] || '');
|
|
1035
|
-
|
|
1036
930
|
const hasLangTs = /\blang\s*=\s*["']ts["']/i.test(attrs);
|
|
1037
931
|
const hasLangJs = /\blang\s*=\s*["'](?:js|javascript)["']/i.test(attrs);
|
|
1038
932
|
const hasAnyLang = /\blang\s*=/i.test(attrs);
|
|
1039
933
|
const isTypescriptDefault = compilerOpts && compilerOpts.typescriptDefault === true;
|
|
1040
|
-
|
|
1041
934
|
if (!hasLangTs) {
|
|
1042
935
|
if (!isTypescriptDefault || hasLangJs || hasAnyLang) {
|
|
1043
|
-
throw new Error(
|
|
1044
|
-
`Zenith server script contract violation:\n` +
|
|
936
|
+
throw new Error(`Zenith server script contract violation:\n` +
|
|
1045
937
|
` File: ${sourceFile}\n` +
|
|
1046
938
|
` Reason: Zenith requires TypeScript server scripts. Add lang="ts" (or enable typescriptDefault).\n` +
|
|
1047
|
-
` Example: <script server lang="ts">`
|
|
1048
|
-
);
|
|
939
|
+
` Example: <script server lang="ts">`);
|
|
1049
940
|
}
|
|
1050
941
|
}
|
|
1051
|
-
|
|
1052
942
|
const serverSource = String(match[2] || '').trim();
|
|
1053
943
|
if (!serverSource) {
|
|
1054
|
-
throw new Error(
|
|
1055
|
-
`Zenith server script contract violation:\n` +
|
|
944
|
+
throw new Error(`Zenith server script contract violation:\n` +
|
|
1056
945
|
` File: ${sourceFile}\n` +
|
|
1057
946
|
` Reason: <script server> block is empty\n` +
|
|
1058
|
-
` Example: export const data = { ... }`
|
|
1059
|
-
);
|
|
947
|
+
` Example: export const data = { ... }`);
|
|
1060
948
|
}
|
|
1061
|
-
|
|
1062
949
|
const loadFnMatch = serverSource.match(/\bexport\s+(?:async\s+)?function\s+load\s*\(([^)]*)\)/);
|
|
1063
950
|
const loadConstParenMatch = serverSource.match(/\bexport\s+const\s+load\s*=\s*(?:async\s*)?\(([^)]*)\)\s*=>/);
|
|
1064
|
-
const loadConstSingleArgMatch = serverSource.match(
|
|
1065
|
-
/\bexport\s+const\s+load\s*=\s*(?:async\s*)?([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=>/
|
|
1066
|
-
);
|
|
951
|
+
const loadConstSingleArgMatch = serverSource.match(/\bexport\s+const\s+load\s*=\s*(?:async\s*)?([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=>/);
|
|
1067
952
|
const hasLoad = Boolean(loadFnMatch || loadConstParenMatch || loadConstSingleArgMatch);
|
|
1068
|
-
const loadMatchCount =
|
|
1069
|
-
Number(Boolean(loadFnMatch)) +
|
|
953
|
+
const loadMatchCount = Number(Boolean(loadFnMatch)) +
|
|
1070
954
|
Number(Boolean(loadConstParenMatch)) +
|
|
1071
955
|
Number(Boolean(loadConstSingleArgMatch));
|
|
1072
956
|
if (loadMatchCount > 1) {
|
|
1073
|
-
throw new Error(
|
|
1074
|
-
`Zenith server script contract violation:\n` +
|
|
957
|
+
throw new Error(`Zenith server script contract violation:\n` +
|
|
1075
958
|
` File: ${sourceFile}\n` +
|
|
1076
959
|
` Reason: multiple load exports detected\n` +
|
|
1077
|
-
` Example: keep exactly one export const load = async (ctx) => ({ ... })`
|
|
1078
|
-
);
|
|
960
|
+
` Example: keep exactly one export const load = async (ctx) => ({ ... })`);
|
|
1079
961
|
}
|
|
1080
|
-
|
|
1081
962
|
const guardFnMatch = serverSource.match(/\bexport\s+(?:async\s+)?function\s+guard\s*\(([^)]*)\)/);
|
|
1082
963
|
const guardConstParenMatch = serverSource.match(/\bexport\s+const\s+guard\s*=\s*(?:async\s*)?\(([^)]*)\)\s*=>/);
|
|
1083
|
-
const guardConstSingleArgMatch = serverSource.match(
|
|
1084
|
-
/\bexport\s+const\s+guard\s*=\s*(?:async\s*)?([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=>/
|
|
1085
|
-
);
|
|
964
|
+
const guardConstSingleArgMatch = serverSource.match(/\bexport\s+const\s+guard\s*=\s*(?:async\s*)?([a-zA-Z_$][a-zA-Z0-9_$]*)\s*=>/);
|
|
1086
965
|
const hasGuard = Boolean(guardFnMatch || guardConstParenMatch || guardConstSingleArgMatch);
|
|
1087
|
-
const guardMatchCount =
|
|
1088
|
-
Number(Boolean(guardFnMatch)) +
|
|
966
|
+
const guardMatchCount = Number(Boolean(guardFnMatch)) +
|
|
1089
967
|
Number(Boolean(guardConstParenMatch)) +
|
|
1090
968
|
Number(Boolean(guardConstSingleArgMatch));
|
|
1091
969
|
if (guardMatchCount > 1) {
|
|
1092
|
-
throw new Error(
|
|
1093
|
-
`Zenith server script contract violation:\n` +
|
|
970
|
+
throw new Error(`Zenith server script contract violation:\n` +
|
|
1094
971
|
` File: ${sourceFile}\n` +
|
|
1095
972
|
` Reason: multiple guard exports detected\n` +
|
|
1096
|
-
` Example: keep exactly one export const guard = async (ctx) => ({ ... })`
|
|
1097
|
-
);
|
|
973
|
+
` Example: keep exactly one export const guard = async (ctx) => ({ ... })`);
|
|
1098
974
|
}
|
|
1099
|
-
|
|
1100
975
|
const hasData = /\bexport\s+const\s+data\b/.test(serverSource);
|
|
1101
976
|
const hasSsrData = /\bexport\s+const\s+ssr_data\b/.test(serverSource);
|
|
1102
977
|
const hasSsr = /\bexport\s+const\s+ssr\b/.test(serverSource);
|
|
1103
978
|
const hasProps = /\bexport\s+const\s+props\b/.test(serverSource);
|
|
1104
|
-
|
|
1105
979
|
if (hasData && hasLoad) {
|
|
1106
|
-
throw new Error(
|
|
1107
|
-
`Zenith server script contract violation:\n` +
|
|
980
|
+
throw new Error(`Zenith server script contract violation:\n` +
|
|
1108
981
|
` File: ${sourceFile}\n` +
|
|
1109
982
|
` Reason: export either data or load(ctx), not both\n` +
|
|
1110
|
-
` Example: remove data and return payload from load(ctx)`
|
|
1111
|
-
);
|
|
983
|
+
` Example: remove data and return payload from load(ctx)`);
|
|
1112
984
|
}
|
|
1113
985
|
if ((hasData || hasLoad) && (hasSsrData || hasSsr || hasProps)) {
|
|
1114
|
-
throw new Error(
|
|
1115
|
-
`Zenith server script contract violation:\n` +
|
|
986
|
+
throw new Error(`Zenith server script contract violation:\n` +
|
|
1116
987
|
` File: ${sourceFile}\n` +
|
|
1117
988
|
` Reason: data/load cannot be combined with legacy ssr_data/ssr/props exports\n` +
|
|
1118
|
-
` Example: use only export const data or export const load`
|
|
1119
|
-
);
|
|
989
|
+
` Example: use only export const data or export const load`);
|
|
1120
990
|
}
|
|
1121
|
-
|
|
1122
991
|
if (hasLoad) {
|
|
1123
992
|
const singleArg = String(loadConstSingleArgMatch?.[1] || '').trim();
|
|
1124
993
|
const paramsText = String((loadFnMatch || loadConstParenMatch)?.[1] || '').trim();
|
|
@@ -1128,15 +997,12 @@ function extractServerScript(source, sourceFile, compilerOpts = {}) {
|
|
|
1128
997
|
? 0
|
|
1129
998
|
: paramsText.split(',').length;
|
|
1130
999
|
if (arity !== 1) {
|
|
1131
|
-
throw new Error(
|
|
1132
|
-
`Zenith server script contract violation:\n` +
|
|
1000
|
+
throw new Error(`Zenith server script contract violation:\n` +
|
|
1133
1001
|
` File: ${sourceFile}\n` +
|
|
1134
1002
|
` Reason: load(ctx) must accept exactly one argument\n` +
|
|
1135
|
-
` Example: export const load = async (ctx) => ({ ... })`
|
|
1136
|
-
);
|
|
1003
|
+
` Example: export const load = async (ctx) => ({ ... })`);
|
|
1137
1004
|
}
|
|
1138
1005
|
}
|
|
1139
|
-
|
|
1140
1006
|
if (hasGuard) {
|
|
1141
1007
|
const singleArg = String(guardConstSingleArgMatch?.[1] || '').trim();
|
|
1142
1008
|
const paramsText = String((guardFnMatch || guardConstParenMatch)?.[1] || '').trim();
|
|
@@ -1146,26 +1012,21 @@ function extractServerScript(source, sourceFile, compilerOpts = {}) {
|
|
|
1146
1012
|
? 0
|
|
1147
1013
|
: paramsText.split(',').length;
|
|
1148
1014
|
if (arity !== 1) {
|
|
1149
|
-
throw new Error(
|
|
1150
|
-
`Zenith server script contract violation:\n` +
|
|
1015
|
+
throw new Error(`Zenith server script contract violation:\n` +
|
|
1151
1016
|
` File: ${sourceFile}\n` +
|
|
1152
1017
|
` Reason: guard(ctx) must accept exactly one argument\n` +
|
|
1153
|
-
` Example: export const guard = async (ctx) => ({ ... })`
|
|
1154
|
-
);
|
|
1018
|
+
` Example: export const guard = async (ctx) => ({ ... })`);
|
|
1155
1019
|
}
|
|
1156
1020
|
}
|
|
1157
|
-
|
|
1158
1021
|
const prerenderMatch = serverSource.match(/\bexport\s+const\s+prerender\s*=\s*([^\n;]+)/);
|
|
1159
1022
|
let prerender = false;
|
|
1160
1023
|
if (prerenderMatch) {
|
|
1161
1024
|
const rawValue = String(prerenderMatch[1] || '').trim();
|
|
1162
1025
|
if (!/^(true|false)\b/.test(rawValue)) {
|
|
1163
|
-
throw new Error(
|
|
1164
|
-
`Zenith server script contract violation:\n` +
|
|
1026
|
+
throw new Error(`Zenith server script contract violation:\n` +
|
|
1165
1027
|
` File: ${sourceFile}\n` +
|
|
1166
1028
|
` Reason: prerender must be a boolean literal\n` +
|
|
1167
|
-
` Example: export const prerender = true`
|
|
1168
|
-
);
|
|
1029
|
+
` Example: export const prerender = true`);
|
|
1169
1030
|
}
|
|
1170
1031
|
prerender = rawValue.startsWith('true');
|
|
1171
1032
|
}
|
|
@@ -1182,10 +1043,8 @@ function extractServerScript(source, sourceFile, compilerOpts = {}) {
|
|
|
1182
1043
|
}
|
|
1183
1044
|
};
|
|
1184
1045
|
}
|
|
1185
|
-
|
|
1186
1046
|
const end = start + full.length;
|
|
1187
1047
|
const stripped = `${source.slice(0, start)}${source.slice(end)}`;
|
|
1188
|
-
|
|
1189
1048
|
return {
|
|
1190
1049
|
source: stripped,
|
|
1191
1050
|
serverScript: {
|
|
@@ -1197,9 +1056,7 @@ function extractServerScript(source, sourceFile, compilerOpts = {}) {
|
|
|
1197
1056
|
}
|
|
1198
1057
|
};
|
|
1199
1058
|
}
|
|
1200
|
-
|
|
1201
1059
|
const OPEN_COMPONENT_TAG_RE = /<([A-Z][a-zA-Z0-9]*)(\s[^<>]*?)?\s*(\/?)>/g;
|
|
1202
|
-
|
|
1203
1060
|
/**
|
|
1204
1061
|
* Collect original attribute strings for component usages in a page source.
|
|
1205
1062
|
*
|
|
@@ -1225,7 +1082,6 @@ function collectComponentUsageAttrs(source, registry, ownerPath = null) {
|
|
|
1225
1082
|
}
|
|
1226
1083
|
return out;
|
|
1227
1084
|
}
|
|
1228
|
-
|
|
1229
1085
|
/**
|
|
1230
1086
|
* Collect component usage attrs recursively so nested component callsites
|
|
1231
1087
|
* receive deterministic props preludes during page-hoist merging.
|
|
@@ -1248,7 +1104,6 @@ function collectRecursiveComponentUsageAttrs(source, registry, ownerPath = null,
|
|
|
1248
1104
|
}
|
|
1249
1105
|
out.get(name).push(...attrsList);
|
|
1250
1106
|
}
|
|
1251
|
-
|
|
1252
1107
|
for (const name of local.keys()) {
|
|
1253
1108
|
const compPath = registry.get(name);
|
|
1254
1109
|
if (!compPath || visitedFiles.has(compPath)) {
|
|
@@ -1258,10 +1113,8 @@ function collectRecursiveComponentUsageAttrs(source, registry, ownerPath = null,
|
|
|
1258
1113
|
const componentSource = readFileSync(compPath, 'utf8');
|
|
1259
1114
|
collectRecursiveComponentUsageAttrs(componentSource, registry, compPath, visitedFiles, out);
|
|
1260
1115
|
}
|
|
1261
|
-
|
|
1262
1116
|
return out;
|
|
1263
1117
|
}
|
|
1264
|
-
|
|
1265
1118
|
/**
|
|
1266
1119
|
* Merge a component's IR into the page IR.
|
|
1267
1120
|
*
|
|
@@ -1293,12 +1146,10 @@ function mergeComponentIr(pageIr, compIr, compPath, pageFile, options, seenStati
|
|
|
1293
1146
|
}
|
|
1294
1147
|
}
|
|
1295
1148
|
}
|
|
1296
|
-
|
|
1297
1149
|
// Merge component_instances
|
|
1298
1150
|
if (compIr.component_instances?.length) {
|
|
1299
1151
|
pageIr.component_instances.push(...compIr.component_instances);
|
|
1300
1152
|
}
|
|
1301
|
-
|
|
1302
1153
|
if (knownRefKeys instanceof Set && Array.isArray(compIr.ref_bindings)) {
|
|
1303
1154
|
const componentStateBindings = Array.isArray(compIr?.hoisted?.state) ? compIr.hoisted.state : [];
|
|
1304
1155
|
for (const binding of compIr.ref_bindings) {
|
|
@@ -1309,7 +1160,6 @@ function mergeComponentIr(pageIr, compIr, compPath, pageFile, options, seenStati
|
|
|
1309
1160
|
knownRefKeys.add(resolved || binding.identifier);
|
|
1310
1161
|
}
|
|
1311
1162
|
}
|
|
1312
|
-
|
|
1313
1163
|
// Merge hoisted imports (deduplicated, rebased to the page file path)
|
|
1314
1164
|
if (compIr.hoisted?.imports?.length) {
|
|
1315
1165
|
for (const imp of compIr.hoisted.imports) {
|
|
@@ -1325,7 +1175,6 @@ function mergeComponentIr(pageIr, compIr, compPath, pageFile, options, seenStati
|
|
|
1325
1175
|
}
|
|
1326
1176
|
}
|
|
1327
1177
|
}
|
|
1328
|
-
|
|
1329
1178
|
// Merge hoisted symbol/state tables for runtime literal evaluation.
|
|
1330
1179
|
// Component-expanded expressions can reference rewritten component symbols,
|
|
1331
1180
|
// so state keys/values must be present in the page envelope.
|
|
@@ -1352,11 +1201,9 @@ function mergeComponentIr(pageIr, compIr, compPath, pageFile, options, seenStati
|
|
|
1352
1201
|
}
|
|
1353
1202
|
}
|
|
1354
1203
|
if (Array.isArray(compIr.hoisted.state)) {
|
|
1355
|
-
const existingKeys = new Set(
|
|
1356
|
-
(
|
|
1357
|
-
|
|
1358
|
-
.filter(Boolean)
|
|
1359
|
-
);
|
|
1204
|
+
const existingKeys = new Set((pageIr.hoisted.state || [])
|
|
1205
|
+
.map((entry) => entry && typeof entry === 'object' ? entry.key : null)
|
|
1206
|
+
.filter(Boolean));
|
|
1360
1207
|
for (const stateEntry of compIr.hoisted.state) {
|
|
1361
1208
|
if (!stateEntry || typeof stateEntry !== 'object') {
|
|
1362
1209
|
continue;
|
|
@@ -1372,18 +1219,14 @@ function mergeComponentIr(pageIr, compIr, compPath, pageFile, options, seenStati
|
|
|
1372
1219
|
}
|
|
1373
1220
|
}
|
|
1374
1221
|
}
|
|
1375
|
-
|
|
1376
1222
|
if (options.includeCode && Array.isArray(compIr.signals)) {
|
|
1377
1223
|
pageIr.signals = Array.isArray(pageIr.signals) ? pageIr.signals : [];
|
|
1378
|
-
const existingSignalStateKeys = new Set(
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
.filter(Boolean)
|
|
1385
|
-
);
|
|
1386
|
-
|
|
1224
|
+
const existingSignalStateKeys = new Set(pageIr.signals
|
|
1225
|
+
.map((signal) => {
|
|
1226
|
+
const stateIndex = signal?.state_index;
|
|
1227
|
+
return Number.isInteger(stateIndex) ? pageIr.hoisted.state?.[stateIndex]?.key : null;
|
|
1228
|
+
})
|
|
1229
|
+
.filter(Boolean));
|
|
1387
1230
|
for (const signal of compIr.signals) {
|
|
1388
1231
|
if (!signal || !Number.isInteger(signal.state_index)) {
|
|
1389
1232
|
continue;
|
|
@@ -1407,7 +1250,6 @@ function mergeComponentIr(pageIr, compIr, compPath, pageFile, options, seenStati
|
|
|
1407
1250
|
});
|
|
1408
1251
|
}
|
|
1409
1252
|
}
|
|
1410
|
-
|
|
1411
1253
|
// Merge hoisted code blocks (rebased to the page file path)
|
|
1412
1254
|
if (options.includeCode && compIr.hoisted?.code?.length) {
|
|
1413
1255
|
for (const block of compIr.hoisted.code) {
|
|
@@ -1415,11 +1257,7 @@ function mergeComponentIr(pageIr, compIr, compPath, pageFile, options, seenStati
|
|
|
1415
1257
|
const filteredImports = options.cssImportsOnly
|
|
1416
1258
|
? stripNonCssStaticImportsInSource(rebased)
|
|
1417
1259
|
: rebased;
|
|
1418
|
-
const withPropsPrelude = injectPropsPrelude(
|
|
1419
|
-
filteredImports,
|
|
1420
|
-
options.componentAttrs || '',
|
|
1421
|
-
options.componentAttrsRewrite || null
|
|
1422
|
-
);
|
|
1260
|
+
const withPropsPrelude = injectPropsPrelude(filteredImports, options.componentAttrs || '', options.componentAttrsRewrite || null);
|
|
1423
1261
|
const transpiled = transpileTypeScriptToJs(withPropsPrelude, compPath);
|
|
1424
1262
|
const deduped = dedupeStaticImportsInSource(transpiled, seenStaticImports);
|
|
1425
1263
|
const deferred = deferComponentRuntimeBlock(deduped);
|
|
@@ -1429,7 +1267,6 @@ function mergeComponentIr(pageIr, compIr, compPath, pageFile, options, seenStati
|
|
|
1429
1267
|
}
|
|
1430
1268
|
}
|
|
1431
1269
|
}
|
|
1432
|
-
|
|
1433
1270
|
/**
|
|
1434
1271
|
* @param {string} spec
|
|
1435
1272
|
* @returns {boolean}
|
|
@@ -1437,7 +1274,6 @@ function mergeComponentIr(pageIr, compIr, compPath, pageFile, options, seenStati
|
|
|
1437
1274
|
function isRelativeSpecifier(spec) {
|
|
1438
1275
|
return spec.startsWith('./') || spec.startsWith('../');
|
|
1439
1276
|
}
|
|
1440
|
-
|
|
1441
1277
|
/**
|
|
1442
1278
|
* @param {string} spec
|
|
1443
1279
|
* @param {string} fromFile
|
|
@@ -1448,7 +1284,6 @@ function rebaseRelativeSpecifier(spec, fromFile, toFile) {
|
|
|
1448
1284
|
if (!isRelativeSpecifier(spec)) {
|
|
1449
1285
|
return spec;
|
|
1450
1286
|
}
|
|
1451
|
-
|
|
1452
1287
|
const absoluteTarget = resolve(dirname(fromFile), spec);
|
|
1453
1288
|
let rebased = relative(dirname(toFile), absoluteTarget).replaceAll('\\', '/');
|
|
1454
1289
|
if (!rebased.startsWith('.')) {
|
|
@@ -1456,7 +1291,6 @@ function rebaseRelativeSpecifier(spec, fromFile, toFile) {
|
|
|
1456
1291
|
}
|
|
1457
1292
|
return rebased;
|
|
1458
1293
|
}
|
|
1459
|
-
|
|
1460
1294
|
/**
|
|
1461
1295
|
* @param {string} line
|
|
1462
1296
|
* @param {string} fromFile
|
|
@@ -1468,16 +1302,13 @@ function rewriteStaticImportLine(line, fromFile, toFile) {
|
|
|
1468
1302
|
if (!match) {
|
|
1469
1303
|
return line;
|
|
1470
1304
|
}
|
|
1471
|
-
|
|
1472
1305
|
const spec = match[1];
|
|
1473
1306
|
if (!isRelativeSpecifier(spec)) {
|
|
1474
1307
|
return line;
|
|
1475
1308
|
}
|
|
1476
|
-
|
|
1477
1309
|
const rebased = rebaseRelativeSpecifier(spec, fromFile, toFile);
|
|
1478
1310
|
return replaceImportSpecifierLiteral(line, spec, rebased);
|
|
1479
1311
|
}
|
|
1480
|
-
|
|
1481
1312
|
/**
|
|
1482
1313
|
* @param {string} line
|
|
1483
1314
|
* @returns {string | null}
|
|
@@ -1486,7 +1317,6 @@ function extractStaticImportSpecifier(line) {
|
|
|
1486
1317
|
const match = line.match(/^\s*import(?:\s+[^'"]+?\s+from)?\s*['"]([^'"]+)['"]\s*;?\s*$/);
|
|
1487
1318
|
return match ? match[1] : null;
|
|
1488
1319
|
}
|
|
1489
|
-
|
|
1490
1320
|
/**
|
|
1491
1321
|
* @param {string} spec
|
|
1492
1322
|
* @returns {boolean}
|
|
@@ -1494,7 +1324,6 @@ function extractStaticImportSpecifier(line) {
|
|
|
1494
1324
|
function isCssSpecifier(spec) {
|
|
1495
1325
|
return /\.css(?:[?#].*)?$/i.test(spec);
|
|
1496
1326
|
}
|
|
1497
|
-
|
|
1498
1327
|
/**
|
|
1499
1328
|
* @param {string} source
|
|
1500
1329
|
* @param {string} fromFile
|
|
@@ -1502,12 +1331,8 @@ function isCssSpecifier(spec) {
|
|
|
1502
1331
|
* @returns {string}
|
|
1503
1332
|
*/
|
|
1504
1333
|
function rewriteStaticImportsInSource(source, fromFile, toFile) {
|
|
1505
|
-
return source.replace(
|
|
1506
|
-
/(^\s*import(?:\s+[^'"]+?\s+from)?\s*['"])([^'"]+)(['"]\s*;?\s*$)/gm,
|
|
1507
|
-
(_full, prefix, spec, suffix) => `${prefix}${rebaseRelativeSpecifier(spec, fromFile, toFile)}${suffix}`
|
|
1508
|
-
);
|
|
1334
|
+
return source.replace(/(^\s*import(?:\s+[^'"]+?\s+from)?\s*['"])([^'"]+)(['"]\s*;?\s*$)/gm, (_full, prefix, spec, suffix) => `${prefix}${rebaseRelativeSpecifier(spec, fromFile, toFile)}${suffix}`);
|
|
1509
1335
|
}
|
|
1510
|
-
|
|
1511
1336
|
/**
|
|
1512
1337
|
* @param {string} line
|
|
1513
1338
|
* @param {string} oldSpec
|
|
@@ -1519,15 +1344,12 @@ function replaceImportSpecifierLiteral(line, oldSpec, newSpec) {
|
|
|
1519
1344
|
if (line.includes(single)) {
|
|
1520
1345
|
return line.replace(single, `'${newSpec}'`);
|
|
1521
1346
|
}
|
|
1522
|
-
|
|
1523
1347
|
const dbl = `"${oldSpec}"`;
|
|
1524
1348
|
if (line.includes(dbl)) {
|
|
1525
1349
|
return line.replace(dbl, `"${newSpec}"`);
|
|
1526
1350
|
}
|
|
1527
|
-
|
|
1528
1351
|
return line;
|
|
1529
1352
|
}
|
|
1530
|
-
|
|
1531
1353
|
/**
|
|
1532
1354
|
* @param {string} source
|
|
1533
1355
|
* @param {string} sourceFile
|
|
@@ -1538,7 +1360,6 @@ function transpileTypeScriptToJs(source, sourceFile) {
|
|
|
1538
1360
|
if (!ts) {
|
|
1539
1361
|
return source;
|
|
1540
1362
|
}
|
|
1541
|
-
|
|
1542
1363
|
try {
|
|
1543
1364
|
const output = ts.transpileModule(source, {
|
|
1544
1365
|
fileName: sourceFile,
|
|
@@ -1552,13 +1373,12 @@ function transpileTypeScriptToJs(source, sourceFile) {
|
|
|
1552
1373
|
reportDiagnostics: false,
|
|
1553
1374
|
});
|
|
1554
1375
|
return output.outputText;
|
|
1555
|
-
}
|
|
1376
|
+
}
|
|
1377
|
+
catch {
|
|
1556
1378
|
return source;
|
|
1557
1379
|
}
|
|
1558
1380
|
}
|
|
1559
|
-
|
|
1560
1381
|
const DEFERRED_RUNTIME_CALLS = new Set(['zenMount', 'zenEffect', 'zeneffect']);
|
|
1561
|
-
|
|
1562
1382
|
/**
|
|
1563
1383
|
* Split top-level runtime side-effect calls from hoistable declarations.
|
|
1564
1384
|
*
|
|
@@ -1574,27 +1394,18 @@ function splitDeferredRuntimeCalls(body) {
|
|
|
1574
1394
|
if (!ts || typeof body !== 'string' || body.trim().length === 0) {
|
|
1575
1395
|
return { hoisted: body, deferred: '' };
|
|
1576
1396
|
}
|
|
1577
|
-
|
|
1578
1397
|
let sourceFile;
|
|
1579
1398
|
try {
|
|
1580
|
-
sourceFile = ts.createSourceFile(
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
ts.ScriptTarget.Latest,
|
|
1584
|
-
true,
|
|
1585
|
-
ts.ScriptKind.TS
|
|
1586
|
-
);
|
|
1587
|
-
} catch {
|
|
1399
|
+
sourceFile = ts.createSourceFile('zenith-component-runtime.ts', body, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
1400
|
+
}
|
|
1401
|
+
catch {
|
|
1588
1402
|
return { hoisted: body, deferred: '' };
|
|
1589
1403
|
}
|
|
1590
|
-
|
|
1591
1404
|
if (!sourceFile || !Array.isArray(sourceFile.statements) || sourceFile.statements.length === 0) {
|
|
1592
1405
|
return { hoisted: body, deferred: '' };
|
|
1593
1406
|
}
|
|
1594
|
-
|
|
1595
1407
|
/** @type {Array<{ start: number, end: number }>} */
|
|
1596
1408
|
const ranges = [];
|
|
1597
|
-
|
|
1598
1409
|
for (const statement of sourceFile.statements) {
|
|
1599
1410
|
if (!ts.isExpressionStatement(statement)) {
|
|
1600
1411
|
continue;
|
|
@@ -1602,16 +1413,13 @@ function splitDeferredRuntimeCalls(body) {
|
|
|
1602
1413
|
if (!ts.isCallExpression(statement.expression)) {
|
|
1603
1414
|
continue;
|
|
1604
1415
|
}
|
|
1605
|
-
|
|
1606
1416
|
let callee = statement.expression.expression;
|
|
1607
1417
|
while (ts.isParenthesizedExpression(callee)) {
|
|
1608
1418
|
callee = callee.expression;
|
|
1609
1419
|
}
|
|
1610
|
-
|
|
1611
1420
|
if (!ts.isIdentifier(callee) || !DEFERRED_RUNTIME_CALLS.has(callee.text)) {
|
|
1612
1421
|
continue;
|
|
1613
1422
|
}
|
|
1614
|
-
|
|
1615
1423
|
const start = typeof statement.getFullStart === 'function'
|
|
1616
1424
|
? statement.getFullStart()
|
|
1617
1425
|
: statement.pos;
|
|
@@ -1621,11 +1429,9 @@ function splitDeferredRuntimeCalls(body) {
|
|
|
1621
1429
|
}
|
|
1622
1430
|
ranges.push({ start, end });
|
|
1623
1431
|
}
|
|
1624
|
-
|
|
1625
1432
|
if (ranges.length === 0) {
|
|
1626
1433
|
return { hoisted: body, deferred: '' };
|
|
1627
1434
|
}
|
|
1628
|
-
|
|
1629
1435
|
ranges.sort((a, b) => a.start - b.start);
|
|
1630
1436
|
/** @type {Array<{ start: number, end: number }>} */
|
|
1631
1437
|
const merged = [];
|
|
@@ -1639,11 +1445,9 @@ function splitDeferredRuntimeCalls(body) {
|
|
|
1639
1445
|
last.end = range.end;
|
|
1640
1446
|
}
|
|
1641
1447
|
}
|
|
1642
|
-
|
|
1643
1448
|
let cursor = 0;
|
|
1644
1449
|
let hoisted = '';
|
|
1645
1450
|
let deferred = '';
|
|
1646
|
-
|
|
1647
1451
|
for (const range of merged) {
|
|
1648
1452
|
if (range.start > cursor) {
|
|
1649
1453
|
hoisted += body.slice(cursor, range.start);
|
|
@@ -1654,14 +1458,11 @@ function splitDeferredRuntimeCalls(body) {
|
|
|
1654
1458
|
}
|
|
1655
1459
|
cursor = range.end;
|
|
1656
1460
|
}
|
|
1657
|
-
|
|
1658
1461
|
if (cursor < body.length) {
|
|
1659
1462
|
hoisted += body.slice(cursor);
|
|
1660
1463
|
}
|
|
1661
|
-
|
|
1662
1464
|
return { hoisted, deferred };
|
|
1663
1465
|
}
|
|
1664
|
-
|
|
1665
1466
|
/**
|
|
1666
1467
|
* @param {string} source
|
|
1667
1468
|
* @param {Set<string>} seenStaticImports
|
|
@@ -1670,14 +1471,12 @@ function splitDeferredRuntimeCalls(body) {
|
|
|
1670
1471
|
function dedupeStaticImportsInSource(source, seenStaticImports) {
|
|
1671
1472
|
const lines = source.split('\n');
|
|
1672
1473
|
const kept = [];
|
|
1673
|
-
|
|
1674
1474
|
for (const line of lines) {
|
|
1675
1475
|
const spec = extractStaticImportSpecifier(line);
|
|
1676
1476
|
if (!spec) {
|
|
1677
1477
|
kept.push(line);
|
|
1678
1478
|
continue;
|
|
1679
1479
|
}
|
|
1680
|
-
|
|
1681
1480
|
const key = line.trim();
|
|
1682
1481
|
if (seenStaticImports.has(key)) {
|
|
1683
1482
|
continue;
|
|
@@ -1685,10 +1484,8 @@ function dedupeStaticImportsInSource(source, seenStaticImports) {
|
|
|
1685
1484
|
seenStaticImports.add(key);
|
|
1686
1485
|
kept.push(line);
|
|
1687
1486
|
}
|
|
1688
|
-
|
|
1689
1487
|
return kept.join('\n');
|
|
1690
1488
|
}
|
|
1691
|
-
|
|
1692
1489
|
/**
|
|
1693
1490
|
* @param {string} source
|
|
1694
1491
|
* @returns {string}
|
|
@@ -1708,7 +1505,6 @@ function stripNonCssStaticImportsInSource(source) {
|
|
|
1708
1505
|
}
|
|
1709
1506
|
return kept.join('\n');
|
|
1710
1507
|
}
|
|
1711
|
-
|
|
1712
1508
|
/**
|
|
1713
1509
|
* @param {string} key
|
|
1714
1510
|
* @returns {string}
|
|
@@ -1719,7 +1515,6 @@ function renderObjectKey(key) {
|
|
|
1719
1515
|
}
|
|
1720
1516
|
return JSON.stringify(key);
|
|
1721
1517
|
}
|
|
1722
|
-
|
|
1723
1518
|
/**
|
|
1724
1519
|
* @param {string} value
|
|
1725
1520
|
* @returns {string | null}
|
|
@@ -1733,7 +1528,6 @@ function deriveScopedIdentifierAlias(value) {
|
|
|
1733
1528
|
const candidate = parts.length > 1 ? parts[parts.length - 1] : ident;
|
|
1734
1529
|
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(candidate) ? candidate : ident;
|
|
1735
1530
|
}
|
|
1736
|
-
|
|
1737
1531
|
/**
|
|
1738
1532
|
* @param {string} source
|
|
1739
1533
|
* @returns {string[]}
|
|
@@ -1743,7 +1537,6 @@ function extractDeclaredIdentifiers(source) {
|
|
|
1743
1537
|
if (!text) {
|
|
1744
1538
|
return [];
|
|
1745
1539
|
}
|
|
1746
|
-
|
|
1747
1540
|
const ts = loadTypeScriptApi();
|
|
1748
1541
|
if (ts) {
|
|
1749
1542
|
const sourceFile = ts.createSourceFile('zenith-hoisted-declaration.ts', text, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
@@ -1761,7 +1554,6 @@ function extractDeclaredIdentifiers(source) {
|
|
|
1761
1554
|
}
|
|
1762
1555
|
}
|
|
1763
1556
|
};
|
|
1764
|
-
|
|
1765
1557
|
for (const statement of sourceFile.statements) {
|
|
1766
1558
|
if (!ts.isVariableStatement(statement)) {
|
|
1767
1559
|
continue;
|
|
@@ -1770,12 +1562,10 @@ function extractDeclaredIdentifiers(source) {
|
|
|
1770
1562
|
collectBindingNames(declaration.name);
|
|
1771
1563
|
}
|
|
1772
1564
|
}
|
|
1773
|
-
|
|
1774
1565
|
if (identifiers.length > 0) {
|
|
1775
1566
|
return identifiers;
|
|
1776
1567
|
}
|
|
1777
1568
|
}
|
|
1778
|
-
|
|
1779
1569
|
const fallback = [];
|
|
1780
1570
|
const match = text.match(/^\s*(?:const|let|var)\s+([\s\S]+?);?\s*$/);
|
|
1781
1571
|
if (!match) {
|
|
@@ -1789,7 +1579,6 @@ function extractDeclaredIdentifiers(source) {
|
|
|
1789
1579
|
}
|
|
1790
1580
|
return fallback;
|
|
1791
1581
|
}
|
|
1792
|
-
|
|
1793
1582
|
/**
|
|
1794
1583
|
* @param {Map<string, string>} map
|
|
1795
1584
|
* @param {Set<string>} ambiguous
|
|
@@ -1810,7 +1599,6 @@ function recordScopedIdentifierRewrite(map, ambiguous, raw, rewritten) {
|
|
|
1810
1599
|
map.set(raw, rewritten);
|
|
1811
1600
|
}
|
|
1812
1601
|
}
|
|
1813
|
-
|
|
1814
1602
|
/**
|
|
1815
1603
|
* @param {object | null | undefined} ir
|
|
1816
1604
|
* @returns {{ map: Map<string, string>, ambiguous: Set<string> }}
|
|
@@ -1820,13 +1608,11 @@ function buildScopedIdentifierRewrite(ir) {
|
|
|
1820
1608
|
if (!ir || typeof ir !== 'object') {
|
|
1821
1609
|
return out;
|
|
1822
1610
|
}
|
|
1823
|
-
|
|
1824
1611
|
const stateBindings = Array.isArray(ir?.hoisted?.state) ? ir.hoisted.state : [];
|
|
1825
1612
|
for (const stateEntry of stateBindings) {
|
|
1826
1613
|
const key = typeof stateEntry?.key === 'string' ? stateEntry.key : null;
|
|
1827
1614
|
recordScopedIdentifierRewrite(out.map, out.ambiguous, deriveScopedIdentifierAlias(key), key);
|
|
1828
1615
|
}
|
|
1829
|
-
|
|
1830
1616
|
const functionBindings = Array.isArray(ir?.hoisted?.functions) ? ir.hoisted.functions : [];
|
|
1831
1617
|
for (const fnName of functionBindings) {
|
|
1832
1618
|
if (typeof fnName !== 'string') {
|
|
@@ -1834,7 +1620,6 @@ function buildScopedIdentifierRewrite(ir) {
|
|
|
1834
1620
|
}
|
|
1835
1621
|
recordScopedIdentifierRewrite(out.map, out.ambiguous, deriveScopedIdentifierAlias(fnName), fnName);
|
|
1836
1622
|
}
|
|
1837
|
-
|
|
1838
1623
|
const declarations = Array.isArray(ir?.hoisted?.declarations) ? ir.hoisted.declarations : [];
|
|
1839
1624
|
for (const declaration of declarations) {
|
|
1840
1625
|
if (typeof declaration !== 'string') {
|
|
@@ -1844,24 +1629,21 @@ function buildScopedIdentifierRewrite(ir) {
|
|
|
1844
1629
|
recordScopedIdentifierRewrite(out.map, out.ambiguous, deriveScopedIdentifierAlias(identifier), identifier);
|
|
1845
1630
|
}
|
|
1846
1631
|
}
|
|
1847
|
-
|
|
1848
1632
|
return out;
|
|
1849
1633
|
}
|
|
1850
|
-
|
|
1851
1634
|
function rewriteIdentifiersWithinExpression(expr, scopeMap, scopeAmbiguous) {
|
|
1852
1635
|
const ts = loadTypeScriptApi();
|
|
1853
1636
|
if (!(scopeMap instanceof Map) || !ts) {
|
|
1854
1637
|
return expr;
|
|
1855
1638
|
}
|
|
1856
|
-
|
|
1857
1639
|
const wrapped = `const __zenith_expr__ = (${expr});`;
|
|
1858
1640
|
let sourceFile;
|
|
1859
1641
|
try {
|
|
1860
1642
|
sourceFile = ts.createSourceFile('zenith-expression.ts', wrapped, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
1861
|
-
}
|
|
1643
|
+
}
|
|
1644
|
+
catch {
|
|
1862
1645
|
return expr;
|
|
1863
1646
|
}
|
|
1864
|
-
|
|
1865
1647
|
const statement = sourceFile.statements[0];
|
|
1866
1648
|
if (!statement || !ts.isVariableStatement(statement)) {
|
|
1867
1649
|
return expr;
|
|
@@ -1871,7 +1653,6 @@ function rewriteIdentifiersWithinExpression(expr, scopeMap, scopeAmbiguous) {
|
|
|
1871
1653
|
if (!root) {
|
|
1872
1654
|
return expr;
|
|
1873
1655
|
}
|
|
1874
|
-
|
|
1875
1656
|
const replacements = [];
|
|
1876
1657
|
const collectBoundNames = (name, target) => {
|
|
1877
1658
|
if (ts.isIdentifier(name)) {
|
|
@@ -1922,15 +1703,12 @@ function rewriteIdentifiersWithinExpression(expr, scopeMap, scopeAmbiguous) {
|
|
|
1922
1703
|
collectBoundNames(param.name, nextBindings);
|
|
1923
1704
|
}
|
|
1924
1705
|
}
|
|
1925
|
-
|
|
1926
1706
|
if (ts.isIdentifier(node) && !shouldSkipIdentifier(node, nextBindings)) {
|
|
1927
1707
|
const rewritten = scopeMap.get(node.text);
|
|
1928
|
-
if (
|
|
1929
|
-
typeof rewritten === 'string' &&
|
|
1708
|
+
if (typeof rewritten === 'string' &&
|
|
1930
1709
|
rewritten.length > 0 &&
|
|
1931
1710
|
rewritten !== node.text &&
|
|
1932
|
-
!(scopeAmbiguous instanceof Set && scopeAmbiguous.has(node.text))
|
|
1933
|
-
) {
|
|
1711
|
+
!(scopeAmbiguous instanceof Set && scopeAmbiguous.has(node.text))) {
|
|
1934
1712
|
replacements.push({
|
|
1935
1713
|
start: node.getStart(sourceFile),
|
|
1936
1714
|
end: node.getEnd(),
|
|
@@ -1938,20 +1716,16 @@ function rewriteIdentifiersWithinExpression(expr, scopeMap, scopeAmbiguous) {
|
|
|
1938
1716
|
});
|
|
1939
1717
|
}
|
|
1940
1718
|
}
|
|
1941
|
-
|
|
1942
1719
|
ts.forEachChild(node, (child) => visit(child, nextBindings));
|
|
1943
1720
|
};
|
|
1944
|
-
|
|
1945
1721
|
visit(root, new Set());
|
|
1946
1722
|
if (replacements.length === 0) {
|
|
1947
1723
|
return expr;
|
|
1948
1724
|
}
|
|
1949
|
-
|
|
1950
1725
|
let rewritten = wrapped;
|
|
1951
1726
|
for (const replacement of replacements.sort((a, b) => b.start - a.start)) {
|
|
1952
1727
|
rewritten = `${rewritten.slice(0, replacement.start)}${replacement.text}${rewritten.slice(replacement.end)}`;
|
|
1953
1728
|
}
|
|
1954
|
-
|
|
1955
1729
|
const prefix = 'const __zenith_expr__ = (';
|
|
1956
1730
|
const suffix = ');';
|
|
1957
1731
|
if (!rewritten.startsWith(prefix) || !rewritten.endsWith(suffix)) {
|
|
@@ -1959,7 +1733,6 @@ function rewriteIdentifiersWithinExpression(expr, scopeMap, scopeAmbiguous) {
|
|
|
1959
1733
|
}
|
|
1960
1734
|
return rewritten.slice(prefix.length, rewritten.length - suffix.length);
|
|
1961
1735
|
}
|
|
1962
|
-
|
|
1963
1736
|
/**
|
|
1964
1737
|
* @param {string} expr
|
|
1965
1738
|
* @param {{
|
|
@@ -1973,19 +1746,15 @@ function rewritePropsExpression(expr, rewriteContext = null) {
|
|
|
1973
1746
|
if (!trimmed) {
|
|
1974
1747
|
return trimmed;
|
|
1975
1748
|
}
|
|
1976
|
-
|
|
1977
1749
|
const expressionMap = rewriteContext?.expressionRewrite?.map;
|
|
1978
1750
|
const expressionAmbiguous = rewriteContext?.expressionRewrite?.ambiguous;
|
|
1979
|
-
if (
|
|
1980
|
-
|
|
1981
|
-
!(expressionAmbiguous instanceof Set && expressionAmbiguous.has(trimmed))
|
|
1982
|
-
) {
|
|
1751
|
+
if (expressionMap instanceof Map &&
|
|
1752
|
+
!(expressionAmbiguous instanceof Set && expressionAmbiguous.has(trimmed))) {
|
|
1983
1753
|
const exact = expressionMap.get(trimmed);
|
|
1984
1754
|
if (typeof exact === 'string' && exact.length > 0) {
|
|
1985
1755
|
return exact;
|
|
1986
1756
|
}
|
|
1987
1757
|
}
|
|
1988
|
-
|
|
1989
1758
|
const scopeMap = rewriteContext?.scopeRewrite?.map;
|
|
1990
1759
|
const scopeAmbiguous = rewriteContext?.scopeRewrite?.ambiguous;
|
|
1991
1760
|
const rootMatch = trimmed.match(/^([A-Za-z_$][A-Za-z0-9_$]*)([\s\S]*)$/);
|
|
@@ -1995,20 +1764,16 @@ function rewritePropsExpression(expr, rewriteContext = null) {
|
|
|
1995
1764
|
if (!rootMatch) {
|
|
1996
1765
|
return rewriteIdentifiersWithinExpression(trimmed, scopeMap, scopeAmbiguous);
|
|
1997
1766
|
}
|
|
1998
|
-
|
|
1999
1767
|
const root = rootMatch[1];
|
|
2000
1768
|
if (scopeAmbiguous instanceof Set && scopeAmbiguous.has(root)) {
|
|
2001
1769
|
return rewriteIdentifiersWithinExpression(trimmed, scopeMap, scopeAmbiguous);
|
|
2002
1770
|
}
|
|
2003
|
-
|
|
2004
1771
|
const rewrittenRoot = scopeMap.get(root);
|
|
2005
1772
|
if (typeof rewrittenRoot !== 'string' || rewrittenRoot.length === 0 || rewrittenRoot === root) {
|
|
2006
1773
|
return rewriteIdentifiersWithinExpression(trimmed, scopeMap, scopeAmbiguous);
|
|
2007
1774
|
}
|
|
2008
|
-
|
|
2009
1775
|
return `${rewrittenRoot}${rootMatch[2]}`;
|
|
2010
1776
|
}
|
|
2011
|
-
|
|
2012
1777
|
/**
|
|
2013
1778
|
* @param {string} attrs
|
|
2014
1779
|
* @param {{
|
|
@@ -2022,7 +1787,6 @@ function renderPropsLiteralFromAttrs(attrs, rewriteContext = null) {
|
|
|
2022
1787
|
if (!src) {
|
|
2023
1788
|
return '{}';
|
|
2024
1789
|
}
|
|
2025
|
-
|
|
2026
1790
|
const entries = [];
|
|
2027
1791
|
const attrRe = /([A-Za-z_$][A-Za-z0-9_$-]*)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|\{([\s\S]*?)\}))?/g;
|
|
2028
1792
|
let match;
|
|
@@ -2031,30 +1795,27 @@ function renderPropsLiteralFromAttrs(attrs, rewriteContext = null) {
|
|
|
2031
1795
|
if (!rawName || rawName.startsWith('on:')) {
|
|
2032
1796
|
continue;
|
|
2033
1797
|
}
|
|
2034
|
-
|
|
2035
1798
|
const doubleQuoted = match[2];
|
|
2036
1799
|
const singleQuoted = match[3];
|
|
2037
1800
|
const expressionValue = match[4];
|
|
2038
1801
|
let valueCode = 'true';
|
|
2039
1802
|
if (doubleQuoted !== undefined) {
|
|
2040
1803
|
valueCode = JSON.stringify(doubleQuoted);
|
|
2041
|
-
}
|
|
1804
|
+
}
|
|
1805
|
+
else if (singleQuoted !== undefined) {
|
|
2042
1806
|
valueCode = JSON.stringify(singleQuoted);
|
|
2043
|
-
}
|
|
1807
|
+
}
|
|
1808
|
+
else if (expressionValue !== undefined) {
|
|
2044
1809
|
const trimmed = String(expressionValue).trim();
|
|
2045
1810
|
valueCode = trimmed.length > 0 ? rewritePropsExpression(trimmed, rewriteContext) : 'undefined';
|
|
2046
1811
|
}
|
|
2047
|
-
|
|
2048
1812
|
entries.push(`${renderObjectKey(rawName)}: ${valueCode}`);
|
|
2049
1813
|
}
|
|
2050
|
-
|
|
2051
1814
|
if (entries.length === 0) {
|
|
2052
1815
|
return '{}';
|
|
2053
1816
|
}
|
|
2054
|
-
|
|
2055
1817
|
return `{ ${entries.join(', ')} }`;
|
|
2056
1818
|
}
|
|
2057
|
-
|
|
2058
1819
|
/**
|
|
2059
1820
|
* @param {string} source
|
|
2060
1821
|
* @param {string} attrs
|
|
@@ -2074,11 +1835,9 @@ function injectPropsPrelude(source, attrs, rewriteContext = null) {
|
|
|
2074
1835
|
if (/\b(?:const|let|var)\s+props\b/.test(source)) {
|
|
2075
1836
|
return source;
|
|
2076
1837
|
}
|
|
2077
|
-
|
|
2078
1838
|
const propsLiteral = renderPropsLiteralFromAttrs(attrs, rewriteContext);
|
|
2079
1839
|
return `var props = ${propsLiteral};\n${source}`;
|
|
2080
1840
|
}
|
|
2081
|
-
|
|
2082
1841
|
/**
|
|
2083
1842
|
* @param {string} source
|
|
2084
1843
|
* @returns {string}
|
|
@@ -2088,7 +1847,6 @@ function deferComponentRuntimeBlock(source) {
|
|
|
2088
1847
|
const importLines = [];
|
|
2089
1848
|
const bodyLines = [];
|
|
2090
1849
|
let inImportPrefix = true;
|
|
2091
|
-
|
|
2092
1850
|
for (const line of lines) {
|
|
2093
1851
|
if (inImportPrefix && extractStaticImportSpecifier(line)) {
|
|
2094
1852
|
importLines.push(line);
|
|
@@ -2097,19 +1855,16 @@ function deferComponentRuntimeBlock(source) {
|
|
|
2097
1855
|
inImportPrefix = false;
|
|
2098
1856
|
bodyLines.push(line);
|
|
2099
1857
|
}
|
|
2100
|
-
|
|
2101
1858
|
const body = bodyLines.join('\n');
|
|
2102
1859
|
if (body.trim().length === 0) {
|
|
2103
1860
|
return importLines.join('\n');
|
|
2104
1861
|
}
|
|
2105
|
-
|
|
2106
1862
|
const { hoisted, deferred } = splitDeferredRuntimeCalls(body);
|
|
2107
1863
|
if (deferred.trim().length === 0) {
|
|
2108
1864
|
return [importLines.join('\n').trim(), hoisted.trim()]
|
|
2109
1865
|
.filter((segment) => segment.length > 0)
|
|
2110
1866
|
.join('\n');
|
|
2111
1867
|
}
|
|
2112
|
-
|
|
2113
1868
|
const indentedBody = deferred
|
|
2114
1869
|
.trim()
|
|
2115
1870
|
.split('\n')
|
|
@@ -2124,10 +1879,8 @@ function deferComponentRuntimeBlock(source) {
|
|
|
2124
1879
|
]
|
|
2125
1880
|
.filter((segment) => segment.length > 0)
|
|
2126
1881
|
.join('\n');
|
|
2127
|
-
|
|
2128
1882
|
return wrapped;
|
|
2129
1883
|
}
|
|
2130
|
-
|
|
2131
1884
|
/**
|
|
2132
1885
|
* Run bundler process for one page envelope.
|
|
2133
1886
|
*
|
|
@@ -2136,28 +1889,28 @@ function deferComponentRuntimeBlock(source) {
|
|
|
2136
1889
|
* @param {string} projectRoot
|
|
2137
1890
|
* @param {object | null} [logger]
|
|
2138
1891
|
* @param {boolean} [showInfo]
|
|
2139
|
-
* @param {string} [bundlerBin]
|
|
1892
|
+
* @param {string|object} [bundlerBin]
|
|
2140
1893
|
* @returns {Promise<void>}
|
|
2141
1894
|
*/
|
|
2142
|
-
function runBundler(
|
|
2143
|
-
envelope,
|
|
2144
|
-
outDir,
|
|
2145
|
-
projectRoot,
|
|
2146
|
-
logger = null,
|
|
2147
|
-
showInfo = true,
|
|
2148
|
-
bundlerBin = resolveBundlerBin(projectRoot)
|
|
2149
|
-
) {
|
|
1895
|
+
function runBundler(envelope, outDir, projectRoot, logger = null, showInfo = true, bundlerBin = resolveBundlerBin(projectRoot)) {
|
|
2150
1896
|
return new Promise((resolvePromise, rejectPromise) => {
|
|
2151
1897
|
const useStructuredLogger = Boolean(logger && typeof logger.childLine === 'function');
|
|
2152
|
-
const
|
|
2153
|
-
bundlerBin
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
1898
|
+
const bundlerToolchain = bundlerBin && typeof bundlerBin === 'object'
|
|
1899
|
+
? bundlerBin
|
|
1900
|
+
: null;
|
|
1901
|
+
const bundlerCandidate = bundlerToolchain
|
|
1902
|
+
? getActiveToolchainCandidate(bundlerToolchain)
|
|
1903
|
+
: null;
|
|
1904
|
+
const bundlerPath = bundlerCandidate?.command || bundlerBin;
|
|
1905
|
+
const bundlerArgs = [
|
|
1906
|
+
...(Array.isArray(bundlerCandidate?.argsPrefix) ? bundlerCandidate.argsPrefix : []),
|
|
1907
|
+
'--out-dir',
|
|
1908
|
+
outDir
|
|
1909
|
+
];
|
|
1910
|
+
const child = spawn(bundlerPath, bundlerArgs, {
|
|
1911
|
+
cwd: projectRoot,
|
|
1912
|
+
stdio: useStructuredLogger ? ['pipe', 'pipe', 'pipe'] : ['pipe', 'inherit', 'inherit']
|
|
1913
|
+
});
|
|
2161
1914
|
if (useStructuredLogger) {
|
|
2162
1915
|
forwardStreamLines(child.stdout, (line) => {
|
|
2163
1916
|
logger.childLine('bundler', line, { stream: 'stdout', showInfo });
|
|
@@ -2166,11 +1919,9 @@ function runBundler(
|
|
|
2166
1919
|
logger.childLine('bundler', line, { stream: 'stderr', showInfo: true });
|
|
2167
1920
|
});
|
|
2168
1921
|
}
|
|
2169
|
-
|
|
2170
1922
|
child.on('error', (err) => {
|
|
2171
1923
|
rejectPromise(new Error(`Bundler spawn failed: ${err.message}`));
|
|
2172
1924
|
});
|
|
2173
|
-
|
|
2174
1925
|
child.on('close', (code) => {
|
|
2175
1926
|
if (code === 0) {
|
|
2176
1927
|
resolvePromise();
|
|
@@ -2178,12 +1929,10 @@ function runBundler(
|
|
|
2178
1929
|
}
|
|
2179
1930
|
rejectPromise(new Error(`Bundler failed with exit code ${code}`));
|
|
2180
1931
|
});
|
|
2181
|
-
|
|
2182
1932
|
child.stdin.write(JSON.stringify(envelope));
|
|
2183
1933
|
child.stdin.end();
|
|
2184
1934
|
});
|
|
2185
1935
|
}
|
|
2186
|
-
|
|
2187
1936
|
/**
|
|
2188
1937
|
* Collect generated assets for reporting.
|
|
2189
1938
|
*
|
|
@@ -2192,15 +1941,14 @@ function runBundler(
|
|
|
2192
1941
|
*/
|
|
2193
1942
|
async function collectAssets(rootDir) {
|
|
2194
1943
|
const files = [];
|
|
2195
|
-
|
|
2196
1944
|
async function walk(dir) {
|
|
2197
1945
|
let entries = [];
|
|
2198
1946
|
try {
|
|
2199
1947
|
entries = await readdir(dir);
|
|
2200
|
-
}
|
|
1948
|
+
}
|
|
1949
|
+
catch {
|
|
2201
1950
|
return;
|
|
2202
1951
|
}
|
|
2203
|
-
|
|
2204
1952
|
entries.sort((a, b) => a.localeCompare(b));
|
|
2205
1953
|
for (const name of entries) {
|
|
2206
1954
|
const fullPath = join(dir, name);
|
|
@@ -2214,12 +1962,10 @@ async function collectAssets(rootDir) {
|
|
|
2214
1962
|
}
|
|
2215
1963
|
}
|
|
2216
1964
|
}
|
|
2217
|
-
|
|
2218
1965
|
await walk(rootDir);
|
|
2219
1966
|
files.sort((a, b) => a.localeCompare(b));
|
|
2220
1967
|
return files;
|
|
2221
1968
|
}
|
|
2222
|
-
|
|
2223
1969
|
/**
|
|
2224
1970
|
* Build all pages by orchestrating compiler and bundler binaries.
|
|
2225
1971
|
*
|
|
@@ -2238,30 +1984,28 @@ async function collectAssets(rootDir) {
|
|
|
2238
1984
|
export async function build(options) {
|
|
2239
1985
|
const { pagesDir, outDir, config = {}, logger = null, showBundlerInfo = true } = options;
|
|
2240
1986
|
const projectRoot = deriveProjectRootFromPagesDir(pagesDir);
|
|
2241
|
-
const compilerBin =
|
|
2242
|
-
const bundlerBin =
|
|
1987
|
+
const compilerBin = createCompilerToolchain({ projectRoot, logger });
|
|
1988
|
+
const bundlerBin = createBundlerToolchain({ projectRoot, logger });
|
|
2243
1989
|
const softNavigationEnabled = config.softNavigation === true || config.router === true;
|
|
2244
1990
|
const compilerOpts = {
|
|
2245
1991
|
typescriptDefault: config.typescriptDefault === true,
|
|
2246
1992
|
experimentalEmbeddedMarkup: config.embeddedMarkupExpressions === true || config.experimental?.embeddedMarkupExpressions === true,
|
|
2247
1993
|
strictDomLints: config.strictDomLints === true
|
|
2248
1994
|
};
|
|
2249
|
-
|
|
2250
1995
|
await rm(outDir, { recursive: true, force: true });
|
|
2251
1996
|
await mkdir(outDir, { recursive: true });
|
|
2252
|
-
|
|
1997
|
+
ensureToolchainCompatibility(bundlerBin);
|
|
1998
|
+
const resolvedBundlerCandidate = getActiveToolchainCandidate(bundlerBin);
|
|
2253
1999
|
if (logger) {
|
|
2254
2000
|
await maybeWarnAboutZenithVersionMismatch({
|
|
2255
2001
|
projectRoot,
|
|
2256
2002
|
logger,
|
|
2257
2003
|
command: 'build',
|
|
2258
|
-
bundlerBinPath:
|
|
2004
|
+
bundlerBinPath: resolvedBundlerCandidate?.path || resolveBundlerBin(projectRoot)
|
|
2259
2005
|
});
|
|
2260
2006
|
}
|
|
2261
|
-
|
|
2262
2007
|
// Derive src/ directory from pages/ directory
|
|
2263
2008
|
const srcDir = resolve(pagesDir, '..');
|
|
2264
|
-
|
|
2265
2009
|
// 1. Build component registry
|
|
2266
2010
|
const registry = buildComponentRegistry(srcDir);
|
|
2267
2011
|
if (registry.size > 0) {
|
|
@@ -2269,14 +2013,13 @@ export async function build(options) {
|
|
|
2269
2013
|
logger.build(`registry=${registry.size} components`, {
|
|
2270
2014
|
onceKey: `component-registry:${registry.size}`
|
|
2271
2015
|
});
|
|
2272
|
-
}
|
|
2016
|
+
}
|
|
2017
|
+
else {
|
|
2273
2018
|
console.log(`[zenith] Component registry: ${registry.size} components`);
|
|
2274
2019
|
}
|
|
2275
2020
|
}
|
|
2276
|
-
|
|
2277
2021
|
const manifest = await generateManifest(pagesDir);
|
|
2278
2022
|
await ensureZenithTypeDeclarations({ manifest, pagesDir });
|
|
2279
|
-
|
|
2280
2023
|
// Cache: avoid re-compiling the same component for multiple pages
|
|
2281
2024
|
/** @type {Map<string, object>} */
|
|
2282
2025
|
const componentIrCache = new Map();
|
|
@@ -2291,42 +2034,31 @@ export async function build(options) {
|
|
|
2291
2034
|
}
|
|
2292
2035
|
console.warn(line);
|
|
2293
2036
|
});
|
|
2294
|
-
|
|
2295
2037
|
const envelopes = [];
|
|
2296
2038
|
for (const entry of manifest) {
|
|
2297
2039
|
const sourceFile = join(pagesDir, entry.file);
|
|
2298
2040
|
const rawSource = readFileSync(sourceFile, 'utf8');
|
|
2299
2041
|
const componentOccurrences = collectExpandedComponentOccurrences(rawSource, registry, sourceFile);
|
|
2300
|
-
|
|
2301
2042
|
const baseName = sourceFile.slice(0, -extname(sourceFile).length);
|
|
2302
2043
|
let adjacentGuard = null;
|
|
2303
2044
|
let adjacentLoad = null;
|
|
2304
2045
|
for (const ext of ['.ts', '.js']) {
|
|
2305
|
-
if (!adjacentGuard && existsSync(`${baseName}.guard${ext}`))
|
|
2306
|
-
|
|
2046
|
+
if (!adjacentGuard && existsSync(`${baseName}.guard${ext}`))
|
|
2047
|
+
adjacentGuard = `${baseName}.guard${ext}`;
|
|
2048
|
+
if (!adjacentLoad && existsSync(`${baseName}.load${ext}`))
|
|
2049
|
+
adjacentLoad = `${baseName}.load${ext}`;
|
|
2307
2050
|
}
|
|
2308
|
-
|
|
2309
2051
|
// 2a. Expand PascalCase component tags
|
|
2310
|
-
const { expandedSource } = expandComponents(
|
|
2311
|
-
rawSource, registry, sourceFile
|
|
2312
|
-
);
|
|
2052
|
+
const { expandedSource } = expandComponents(rawSource, registry, sourceFile);
|
|
2313
2053
|
const extractedServer = extractServerScript(expandedSource, sourceFile, compilerOpts);
|
|
2314
2054
|
const compileSource = extractedServer.source;
|
|
2315
|
-
|
|
2316
2055
|
// 2b. Compile expanded page source via --stdin
|
|
2317
|
-
const pageIr = runCompiler(
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
{
|
|
2322
|
-
compilerBin,
|
|
2323
|
-
onWarning: emitCompilerWarning
|
|
2324
|
-
}
|
|
2325
|
-
);
|
|
2326
|
-
|
|
2056
|
+
const pageIr = runCompiler(sourceFile, compileSource, compilerOpts, {
|
|
2057
|
+
compilerToolchain: compilerBin,
|
|
2058
|
+
onWarning: emitCompilerWarning
|
|
2059
|
+
});
|
|
2327
2060
|
const hasGuard = (extractedServer.serverScript && extractedServer.serverScript.has_guard) || adjacentGuard !== null;
|
|
2328
2061
|
const hasLoad = (extractedServer.serverScript && extractedServer.serverScript.has_load) || adjacentLoad !== null;
|
|
2329
|
-
|
|
2330
2062
|
if (extractedServer.serverScript) {
|
|
2331
2063
|
pageIr.server_script = extractedServer.serverScript;
|
|
2332
2064
|
pageIr.prerender = extractedServer.serverScript.prerender === true;
|
|
@@ -2334,21 +2066,16 @@ export async function build(options) {
|
|
|
2334
2066
|
pageIr.ssr_data = null;
|
|
2335
2067
|
}
|
|
2336
2068
|
}
|
|
2337
|
-
|
|
2338
2069
|
// Static Build Route Protection Policy
|
|
2339
2070
|
if (pageIr.prerender === true && (hasGuard || hasLoad)) {
|
|
2340
|
-
throw new Error(
|
|
2341
|
-
`
|
|
2342
|
-
`Cannot prerender a static route with a \`guard\` or \`load\` function.`
|
|
2343
|
-
);
|
|
2071
|
+
throw new Error(`[zenith] Build failed for ${entry.file}: protected routes require SSR/runtime. ` +
|
|
2072
|
+
`Cannot prerender a static route with a \`guard\` or \`load\` function.`);
|
|
2344
2073
|
}
|
|
2345
|
-
|
|
2346
2074
|
// Apply metadata to IR
|
|
2347
2075
|
pageIr.has_guard = hasGuard;
|
|
2348
2076
|
pageIr.has_load = hasLoad;
|
|
2349
2077
|
pageIr.guard_module_ref = adjacentGuard ? relative(srcDir, adjacentGuard).replaceAll('\\', '/') : null;
|
|
2350
2078
|
pageIr.load_module_ref = adjacentLoad ? relative(srcDir, adjacentLoad).replaceAll('\\', '/') : null;
|
|
2351
|
-
|
|
2352
2079
|
// Ensure IR has required array fields for merging
|
|
2353
2080
|
pageIr.components_scripts = pageIr.components_scripts || {};
|
|
2354
2081
|
pageIr.component_instances = pageIr.component_instances || [];
|
|
@@ -2366,189 +2093,109 @@ export async function build(options) {
|
|
|
2366
2093
|
const key = occurrence.componentPath || occurrence.name;
|
|
2367
2094
|
occurrenceCountByPath.set(key, (occurrenceCountByPath.get(key) || 0) + 1);
|
|
2368
2095
|
}
|
|
2369
|
-
|
|
2370
2096
|
const pageExpressionRewriteMap = new Map();
|
|
2371
2097
|
const pageExpressionBindingMap = new Map();
|
|
2372
2098
|
const pageAmbiguousExpressionMap = new Set();
|
|
2373
2099
|
const knownRefKeys = new Set();
|
|
2374
2100
|
const componentOccurrencePlans = [];
|
|
2375
2101
|
const pageScopeRewrite = buildScopedIdentifierRewrite(pageIr);
|
|
2376
|
-
const pageSelfExpressionRewrite = buildComponentExpressionRewrite(
|
|
2377
|
-
|
|
2378
|
-
compileSource,
|
|
2379
|
-
pageIr,
|
|
2380
|
-
compilerOpts,
|
|
2381
|
-
compilerBin
|
|
2382
|
-
);
|
|
2383
|
-
mergeExpressionRewriteMaps(
|
|
2384
|
-
pageExpressionRewriteMap,
|
|
2385
|
-
pageExpressionBindingMap,
|
|
2386
|
-
pageAmbiguousExpressionMap,
|
|
2387
|
-
pageSelfExpressionRewrite,
|
|
2388
|
-
pageIr
|
|
2389
|
-
);
|
|
2102
|
+
const pageSelfExpressionRewrite = buildComponentExpressionRewrite(sourceFile, compileSource, pageIr, compilerOpts, compilerBin);
|
|
2103
|
+
mergeExpressionRewriteMaps(pageExpressionRewriteMap, pageExpressionBindingMap, pageAmbiguousExpressionMap, pageSelfExpressionRewrite, pageIr);
|
|
2390
2104
|
const componentScopeRewriteCache = new Map();
|
|
2391
2105
|
let componentInstanceCounter = 0;
|
|
2392
|
-
|
|
2393
2106
|
// 2c. Compile each used component separately for its script IR
|
|
2394
2107
|
for (const occurrence of componentOccurrences) {
|
|
2395
2108
|
const compName = occurrence.name;
|
|
2396
2109
|
const compPath = occurrence.componentPath || registry.get(compName);
|
|
2397
|
-
if (!compPath)
|
|
2110
|
+
if (!compPath)
|
|
2111
|
+
continue;
|
|
2398
2112
|
const componentSource = readFileSync(compPath, 'utf8');
|
|
2399
2113
|
const occurrenceCount = occurrenceCountByPath.get(compPath) || 0;
|
|
2400
|
-
|
|
2401
2114
|
let compIr;
|
|
2402
2115
|
if (componentIrCache.has(compPath)) {
|
|
2403
2116
|
compIr = componentIrCache.get(compPath);
|
|
2404
|
-
}
|
|
2117
|
+
}
|
|
2118
|
+
else {
|
|
2405
2119
|
const componentCompileSource = stripStyleBlocks(componentSource);
|
|
2406
|
-
compIr = runCompiler(
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
{
|
|
2411
|
-
compilerBin,
|
|
2412
|
-
onWarning: emitCompilerWarning
|
|
2413
|
-
}
|
|
2414
|
-
);
|
|
2120
|
+
compIr = runCompiler(compPath, componentCompileSource, compilerOpts, {
|
|
2121
|
+
compilerToolchain: compilerBin,
|
|
2122
|
+
onWarning: emitCompilerWarning
|
|
2123
|
+
});
|
|
2415
2124
|
componentIrCache.set(compPath, compIr);
|
|
2416
2125
|
}
|
|
2417
|
-
|
|
2418
2126
|
let isDocMode = componentDocumentModeCache.get(compPath);
|
|
2419
2127
|
if (isDocMode === undefined) {
|
|
2420
2128
|
isDocMode = isDocumentMode(extractTemplate(componentSource));
|
|
2421
2129
|
componentDocumentModeCache.set(compPath, isDocMode);
|
|
2422
2130
|
}
|
|
2423
|
-
|
|
2424
2131
|
let expressionRewrite = componentExpressionRewriteCache.get(compPath);
|
|
2425
2132
|
if (!expressionRewrite) {
|
|
2426
|
-
expressionRewrite = buildComponentExpressionRewrite(
|
|
2427
|
-
compPath,
|
|
2428
|
-
componentSource,
|
|
2429
|
-
compIr,
|
|
2430
|
-
compilerOpts,
|
|
2431
|
-
compilerBin
|
|
2432
|
-
);
|
|
2133
|
+
expressionRewrite = buildComponentExpressionRewrite(compPath, componentSource, compIr, compilerOpts, compilerBin);
|
|
2433
2134
|
componentExpressionRewriteCache.set(compPath, expressionRewrite);
|
|
2434
2135
|
}
|
|
2435
|
-
|
|
2436
2136
|
let attrExpressionRewrite = pageSelfExpressionRewrite;
|
|
2437
2137
|
let attrScopeRewrite = pageScopeRewrite;
|
|
2438
2138
|
const ownerPath = typeof occurrence.ownerPath === 'string' && occurrence.ownerPath.length > 0
|
|
2439
2139
|
? occurrence.ownerPath
|
|
2440
2140
|
: sourceFile;
|
|
2441
|
-
|
|
2442
2141
|
if (ownerPath !== sourceFile) {
|
|
2443
2142
|
let ownerIr = componentIrCache.get(ownerPath);
|
|
2444
2143
|
if (!ownerIr) {
|
|
2445
2144
|
const ownerSource = readFileSync(ownerPath, 'utf8');
|
|
2446
|
-
ownerIr = runCompiler(
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
{
|
|
2451
|
-
compilerBin,
|
|
2452
|
-
onWarning: emitCompilerWarning
|
|
2453
|
-
}
|
|
2454
|
-
);
|
|
2145
|
+
ownerIr = runCompiler(ownerPath, stripStyleBlocks(ownerSource), compilerOpts, {
|
|
2146
|
+
compilerToolchain: compilerBin,
|
|
2147
|
+
onWarning: emitCompilerWarning
|
|
2148
|
+
});
|
|
2455
2149
|
componentIrCache.set(ownerPath, ownerIr);
|
|
2456
2150
|
}
|
|
2457
|
-
|
|
2458
2151
|
attrExpressionRewrite = componentExpressionRewriteCache.get(ownerPath);
|
|
2459
2152
|
if (!attrExpressionRewrite) {
|
|
2460
2153
|
const ownerSource = readFileSync(ownerPath, 'utf8');
|
|
2461
|
-
attrExpressionRewrite = buildComponentExpressionRewrite(
|
|
2462
|
-
ownerPath,
|
|
2463
|
-
ownerSource,
|
|
2464
|
-
ownerIr,
|
|
2465
|
-
compilerOpts,
|
|
2466
|
-
compilerBin
|
|
2467
|
-
);
|
|
2154
|
+
attrExpressionRewrite = buildComponentExpressionRewrite(ownerPath, ownerSource, ownerIr, compilerOpts, compilerBin);
|
|
2468
2155
|
componentExpressionRewriteCache.set(ownerPath, attrExpressionRewrite);
|
|
2469
2156
|
}
|
|
2470
|
-
|
|
2471
2157
|
attrScopeRewrite = componentScopeRewriteCache.get(ownerPath);
|
|
2472
2158
|
if (!attrScopeRewrite) {
|
|
2473
2159
|
attrScopeRewrite = buildScopedIdentifierRewrite(ownerIr);
|
|
2474
2160
|
componentScopeRewriteCache.set(ownerPath, attrScopeRewrite);
|
|
2475
2161
|
}
|
|
2476
2162
|
}
|
|
2477
|
-
|
|
2478
2163
|
const useIsolatedInstance = occurrenceCount > 1;
|
|
2479
2164
|
const { ir: instanceIr, refIdentifierPairs } = useIsolatedInstance
|
|
2480
|
-
? cloneComponentIrForInstance(
|
|
2481
|
-
compIr,
|
|
2482
|
-
componentInstanceCounter++,
|
|
2483
|
-
extractDeclaredIdentifiers,
|
|
2484
|
-
resolveStateKeyFromBindings
|
|
2485
|
-
)
|
|
2165
|
+
? cloneComponentIrForInstance(compIr, componentInstanceCounter++, extractDeclaredIdentifiers, resolveStateKeyFromBindings)
|
|
2486
2166
|
: { ir: compIr, refIdentifierPairs: [] };
|
|
2487
2167
|
const instanceRewrite = useIsolatedInstance
|
|
2488
|
-
? buildComponentExpressionRewrite(
|
|
2489
|
-
compPath,
|
|
2490
|
-
componentSource,
|
|
2491
|
-
instanceIr,
|
|
2492
|
-
compilerOpts,
|
|
2493
|
-
compilerBin
|
|
2494
|
-
)
|
|
2168
|
+
? buildComponentExpressionRewrite(compPath, componentSource, instanceIr, compilerOpts, compilerBin)
|
|
2495
2169
|
: expressionRewrite;
|
|
2496
|
-
|
|
2497
2170
|
// 2d. Merge component IR into page IR
|
|
2498
|
-
mergeComponentIr(
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
{
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
componentAttrsRewrite: {
|
|
2509
|
-
expressionRewrite: attrExpressionRewrite,
|
|
2510
|
-
scopeRewrite: attrScopeRewrite
|
|
2511
|
-
}
|
|
2512
|
-
},
|
|
2513
|
-
seenStaticImports,
|
|
2514
|
-
knownRefKeys
|
|
2515
|
-
);
|
|
2516
|
-
|
|
2171
|
+
mergeComponentIr(pageIr, instanceIr, compPath, sourceFile, {
|
|
2172
|
+
includeCode: true,
|
|
2173
|
+
cssImportsOnly: isDocMode,
|
|
2174
|
+
documentMode: isDocMode,
|
|
2175
|
+
componentAttrs: typeof occurrence.attrs === 'string' ? occurrence.attrs : '',
|
|
2176
|
+
componentAttrsRewrite: {
|
|
2177
|
+
expressionRewrite: attrExpressionRewrite,
|
|
2178
|
+
scopeRewrite: attrScopeRewrite
|
|
2179
|
+
}
|
|
2180
|
+
}, seenStaticImports, knownRefKeys);
|
|
2517
2181
|
if (useIsolatedInstance) {
|
|
2518
2182
|
componentOccurrencePlans.push({
|
|
2519
2183
|
rewrite: instanceRewrite,
|
|
2520
2184
|
expressionSequence: instanceRewrite.sequence,
|
|
2521
2185
|
refSequence: refIdentifierPairs
|
|
2522
2186
|
});
|
|
2523
|
-
}
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
pageExpressionBindingMap,
|
|
2527
|
-
pageAmbiguousExpressionMap,
|
|
2528
|
-
expressionRewrite,
|
|
2529
|
-
pageIr
|
|
2530
|
-
);
|
|
2187
|
+
}
|
|
2188
|
+
else {
|
|
2189
|
+
mergeExpressionRewriteMaps(pageExpressionRewriteMap, pageExpressionBindingMap, pageAmbiguousExpressionMap, expressionRewrite, pageIr);
|
|
2531
2190
|
}
|
|
2532
2191
|
}
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
pageIr,
|
|
2536
|
-
componentOccurrencePlans,
|
|
2537
|
-
(rewrite, binding) => resolveRewrittenBindingMetadata(pageIr, rewrite, binding)
|
|
2538
|
-
);
|
|
2539
|
-
applyExpressionRewrites(
|
|
2540
|
-
pageIr,
|
|
2541
|
-
pageExpressionRewriteMap,
|
|
2542
|
-
pageExpressionBindingMap,
|
|
2543
|
-
pageAmbiguousExpressionMap
|
|
2544
|
-
);
|
|
2192
|
+
applyOccurrenceRewritePlans(pageIr, componentOccurrencePlans, (rewrite, binding) => resolveRewrittenBindingMetadata(pageIr, rewrite, binding));
|
|
2193
|
+
applyExpressionRewrites(pageIr, pageExpressionRewriteMap, pageExpressionBindingMap, pageAmbiguousExpressionMap);
|
|
2545
2194
|
applyScopedIdentifierRewrites(pageIr, buildScopedIdentifierRewrite(pageIr));
|
|
2546
2195
|
synthesizeSignalBackedCompiledExpressions(pageIr);
|
|
2547
2196
|
normalizeExpressionBindingDependencies(pageIr);
|
|
2548
|
-
|
|
2549
2197
|
rewriteLegacyMarkupIdentifiers(pageIr);
|
|
2550
2198
|
rewriteRefBindingIdentifiers(pageIr, knownRefKeys);
|
|
2551
|
-
|
|
2552
2199
|
envelopes.push({
|
|
2553
2200
|
route: entry.path,
|
|
2554
2201
|
file: sourceFile,
|
|
@@ -2556,11 +2203,9 @@ export async function build(options) {
|
|
|
2556
2203
|
router: softNavigationEnabled
|
|
2557
2204
|
});
|
|
2558
2205
|
}
|
|
2559
|
-
|
|
2560
2206
|
if (envelopes.length > 0) {
|
|
2561
2207
|
await runBundler(envelopes, outDir, projectRoot, logger, showBundlerInfo, bundlerBin);
|
|
2562
2208
|
}
|
|
2563
|
-
|
|
2564
2209
|
const assets = await collectAssets(outDir);
|
|
2565
2210
|
return { pages: manifest.length, assets };
|
|
2566
2211
|
}
|