@vesk/compiler 0.2.93 → 0.2.94
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/client-codegen.d.ts.map +1 -1
- package/dist/client-codegen.js +119 -23
- package/dist/module-imports.d.ts +9 -2
- package/dist/module-imports.d.ts.map +1 -1
- package/dist/module-imports.js +163 -38
- package/dist/precompile.d.ts.map +1 -1
- package/dist/precompile.js +40 -2
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-codegen.d.ts","sourceRoot":"","sources":["../src/client-codegen.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAGL,cAAc,EAQd,gBAAgB,EAUjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAkGxD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;CAC1B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI1D;AAiDD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAgJlI;AAID,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAI5E;AAyCD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,EAAE,CAuB9F;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAY5F;AAoFD,qDAAqD;AACrD,MAAM,MAAM,SAAS,GAAG;IAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,SAAS,CAQtE;
|
|
1
|
+
{"version":3,"file":"client-codegen.d.ts","sourceRoot":"","sources":["../src/client-codegen.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAGL,cAAc,EAQd,gBAAgB,EAUjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAkGxD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;CAC1B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI1D;AAiDD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAgJlI;AAID,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAI5E;AAyCD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,EAAE,CAuB9F;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAY5F;AAoFD,qDAAqD;AACrD,MAAM,MAAM,SAAS,GAAG;IAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,SAAS,CAQtE;AA0uED,iBAAS,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAe3C;AAuKD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO9C;AAwED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,SAAS,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAOpQ;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,MAAM,GAAG,IAAI,EAC7B,UAAU,CAAC,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,MAAM,EAAE,CAAA;CAAE,CAyC5J;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAG/E;AAED,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
package/dist/client-codegen.js
CHANGED
|
@@ -685,6 +685,7 @@ function emitNode(ctx, node, tracked, effectsVar, parentVar, compPrefix = '__com
|
|
|
685
685
|
ctx.push(` const __slot = createLayoutSlot(${ctx.walker}, ${parentVar});`);
|
|
686
686
|
ctx.push(` const __child = props.children(__slot.walker);`);
|
|
687
687
|
ctx.push(` if (__child && typeof __child.then === 'function') __pendingChild = __slot.track(__child);`);
|
|
688
|
+
ctx.push(` else if (__child && __child.nodeType === 11) ${parentVar}.appendChild(__child);`);
|
|
688
689
|
ctx.push(` } else {`);
|
|
689
690
|
ctx.push(` ${parentVar}.appendChild(props.children);`);
|
|
690
691
|
ctx.push(` }`);
|
|
@@ -1269,6 +1270,65 @@ function emitFragment(ctx, nodes, tracked, effectsVar) {
|
|
|
1269
1270
|
ctx.push(`return $f; })();`);
|
|
1270
1271
|
return frag;
|
|
1271
1272
|
}
|
|
1273
|
+
/**
|
|
1274
|
+
* True when any node in the subtree is a layout `{props.children}` slot.
|
|
1275
|
+
*
|
|
1276
|
+
* A slot must be hydrated on the walker scoped to the element that will
|
|
1277
|
+
* actually contain it. Building the children fragment eagerly on the caller's
|
|
1278
|
+
* walker is only correct when the callee appends that fragment to its own
|
|
1279
|
+
* mount point. A component that forwards children through a scoped container
|
|
1280
|
+
* (e.g. a shell that renders `{props.children}` inside `<main>`) invokes the
|
|
1281
|
+
* child hydrator with a sub-walker; passing an eagerly-built fragment skips
|
|
1282
|
+
* that scope and lets the page claim the shell's own SSR root.
|
|
1283
|
+
*/
|
|
1284
|
+
function containsSlot(nodes) {
|
|
1285
|
+
for (const node of nodes) {
|
|
1286
|
+
if (node instanceof SlotNode)
|
|
1287
|
+
return true;
|
|
1288
|
+
if (node instanceof StaticNode) {
|
|
1289
|
+
if (containsSlot(node.children))
|
|
1290
|
+
return true;
|
|
1291
|
+
}
|
|
1292
|
+
else if (node instanceof ComponentCall) {
|
|
1293
|
+
if (containsSlot(node.children))
|
|
1294
|
+
return true;
|
|
1295
|
+
}
|
|
1296
|
+
else if (node instanceof OpaqueDynamicRegion) {
|
|
1297
|
+
if (containsSlot(node.consequentNodes) || containsSlot(node.alternateNodes))
|
|
1298
|
+
return true;
|
|
1299
|
+
}
|
|
1300
|
+
else if (node instanceof MapRegion) {
|
|
1301
|
+
if (containsSlot(node.bodyTemplate) || containsSlot(node.alternateNodes))
|
|
1302
|
+
return true;
|
|
1303
|
+
}
|
|
1304
|
+
else if (node instanceof WhileLoop) {
|
|
1305
|
+
if (containsSlot(node.bodyTemplate))
|
|
1306
|
+
return true;
|
|
1307
|
+
}
|
|
1308
|
+
else if (node instanceof ForLoop) {
|
|
1309
|
+
if (containsSlot(node.bodyTemplate))
|
|
1310
|
+
return true;
|
|
1311
|
+
}
|
|
1312
|
+
else if (node instanceof SwitchBlock) {
|
|
1313
|
+
for (const c of node.cases)
|
|
1314
|
+
if (containsSlot(c.body))
|
|
1315
|
+
return true;
|
|
1316
|
+
}
|
|
1317
|
+
else if (node instanceof TryCatch) {
|
|
1318
|
+
if (containsSlot(node.bodyTemplate) || containsSlot(node.catchBody))
|
|
1319
|
+
return true;
|
|
1320
|
+
}
|
|
1321
|
+
else if (node instanceof ServerBlock || node instanceof ClientBlock || node instanceof HeadBlock) {
|
|
1322
|
+
if (containsSlot(node.children))
|
|
1323
|
+
return true;
|
|
1324
|
+
}
|
|
1325
|
+
else if (node instanceof PropSlot) {
|
|
1326
|
+
if (containsSlot(node.body))
|
|
1327
|
+
return true;
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
return false;
|
|
1331
|
+
}
|
|
1272
1332
|
function emitComponentCall(ctx, node, tracked, effectsVar, parentVar, compPrefix = '__components', skipK = 0, regionBudget) {
|
|
1273
1333
|
const propsEntries = node.props.map((p) => {
|
|
1274
1334
|
if (typeof p.value === 'string')
|
|
@@ -1406,20 +1466,56 @@ function emitComponentCall(ctx, node, tracked, effectsVar, parentVar, compPrefix
|
|
|
1406
1466
|
// fresh and let the runtime component adopt the existing root.
|
|
1407
1467
|
if (wipeMount || ctx.selfClaimNames.has(node.componentName))
|
|
1408
1468
|
ctx.hydrate = false;
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1469
|
+
// A slot nested under a compiled component must be built by that
|
|
1470
|
+
// component's scoped walker, not the caller's. Pass children as a lazy
|
|
1471
|
+
// hydrator so the callee can invoke it with the walker for the element
|
|
1472
|
+
// that actually contains the slot (e.g. `<main>` in a shell). Eagerly
|
|
1473
|
+
// building the fragment here hydrates the page against the shell's own
|
|
1474
|
+
// SSR root, which detaches the shell on hydration.
|
|
1475
|
+
const lazySlotChildren = ctx.hydrate && !plainTarget && !ctx.selfClaimNames.has(node.componentName) && containsSlot(regChildren);
|
|
1476
|
+
if (lazySlotChildren) {
|
|
1477
|
+
const fnVar = ctx.n();
|
|
1478
|
+
const savedLines = ctx.lines;
|
|
1479
|
+
const savedEffects = ctx.effects;
|
|
1480
|
+
const savedWalker = ctx.walker;
|
|
1481
|
+
ctx.lines = [];
|
|
1482
|
+
ctx.effects = [];
|
|
1483
|
+
ctx.walker = '__childWalker';
|
|
1484
|
+
ctx.push(`const $f = document.createDocumentFragment();`);
|
|
1485
|
+
for (const child of regChildren) {
|
|
1486
|
+
const childVar = emitNode(ctx, child, tracked, effectsVar, '$f');
|
|
1487
|
+
if (childVar)
|
|
1488
|
+
ctx.push(`$f.appendChild(${childVar});`);
|
|
1489
|
+
}
|
|
1490
|
+
for (const eff of ctx.effects)
|
|
1491
|
+
ctx.push(effectsVar ? `${effectsVar}.push(${effectBlockToHandlerExpr(eff)});` : eff);
|
|
1492
|
+
ctx.push(`return $f;`);
|
|
1493
|
+
const body = ctx.lines.join('\n');
|
|
1494
|
+
ctx.lines = savedLines;
|
|
1495
|
+
ctx.effects = savedEffects;
|
|
1496
|
+
ctx.walker = savedWalker;
|
|
1497
|
+
const asyncKw = ctx.isAsyncScope ? 'async ' : '';
|
|
1498
|
+
ctx.push(`const ${fnVar} = ${asyncKw}(__childWalker) => {`);
|
|
1499
|
+
ctx.push(indent(body));
|
|
1500
|
+
ctx.push(`};`);
|
|
1501
|
+
propsEntries.push(`children: ${fnVar}`);
|
|
1502
|
+
}
|
|
1503
|
+
else {
|
|
1504
|
+
ctx.push(`const ${frag} = (() => { const $f = document.createDocumentFragment();`);
|
|
1505
|
+
const savedEffects = ctx.effects;
|
|
1506
|
+
ctx.effects = [];
|
|
1507
|
+
for (const child of regChildren) {
|
|
1508
|
+
const childVar = emitNode(ctx, child, tracked, effectsVar, '$f');
|
|
1509
|
+
if (childVar)
|
|
1510
|
+
ctx.push(`$f.appendChild(${childVar});`);
|
|
1511
|
+
}
|
|
1512
|
+
for (const eff of ctx.effects)
|
|
1513
|
+
ctx.push(effectsVar ? `${effectsVar}.push(${effectBlockToHandlerExpr(eff)});` : eff);
|
|
1514
|
+
ctx.effects = savedEffects;
|
|
1515
|
+
ctx.push(`return $f; })();`);
|
|
1516
|
+
propsEntries.push(`children: ${frag}`);
|
|
1416
1517
|
}
|
|
1417
|
-
for (const eff of ctx.effects)
|
|
1418
|
-
ctx.push(effectsVar ? `${effectsVar}.push(${effectBlockToHandlerExpr(eff)});` : eff);
|
|
1419
|
-
ctx.effects = savedEffects;
|
|
1420
1518
|
ctx.hydrate = savedHydrate;
|
|
1421
|
-
ctx.push(`return $f; })();`);
|
|
1422
|
-
propsEntries.push(`children: ${frag}`);
|
|
1423
1519
|
}
|
|
1424
1520
|
// Deposit the residue for the child's first top-level claim (it runs on
|
|
1425
1521
|
// this same walker with its own zero `topPendingSkip`). A region budget is
|
|
@@ -1667,7 +1763,7 @@ function emitTryCatch(ctx, node, tracked, effectsVar, parentVar, skipK = 0, regi
|
|
|
1667
1763
|
${effArr}.length = 0;
|
|
1668
1764
|
__cleanup(${anchor}, ${endAnchor});
|
|
1669
1765
|
try { ${asyncKw}${tryRenderComp}(); } catch(${catchParam}) { ${hasCatch ? `${asyncKw}${catchRenderComp}(${catchParam});` : 'throw ${catchParam};'} }
|
|
1670
|
-
});
|
|
1766
|
+
}, true);
|
|
1671
1767
|
}`);
|
|
1672
1768
|
return null;
|
|
1673
1769
|
}
|
|
@@ -1766,7 +1862,7 @@ function emitOpaque(ctx, node, tracked, effTarget, parentVar, skipK = 0, regionB
|
|
|
1766
1862
|
${effInner}
|
|
1767
1863
|
__iv = __new;
|
|
1768
1864
|
}
|
|
1769
|
-
});`;
|
|
1865
|
+
}, true);`;
|
|
1770
1866
|
if (effTarget) {
|
|
1771
1867
|
ctx.push(`${effTarget}.push((() => {
|
|
1772
1868
|
let __iv = ${branchInit};
|
|
@@ -1867,7 +1963,7 @@ function emitOpaque(ctx, node, tracked, effTarget, parentVar, skipK = 0, regionB
|
|
|
1867
1963
|
${renderBranch}
|
|
1868
1964
|
__iv = __nv;
|
|
1869
1965
|
}
|
|
1870
|
-
});`;
|
|
1966
|
+
}, true);`;
|
|
1871
1967
|
// A static condition renders once; an effect referencing it would only ever
|
|
1872
1968
|
// reference statement/loop-local bindings that are out of scope at the flush
|
|
1873
1969
|
// site (e.g. `const pages = …; if (pages.length > 0)` inside a for-of body).
|
|
@@ -1973,7 +2069,7 @@ function emitWhileLoop(ctx, node, tracked, parentVar, skipK = 0, regionBudget) {
|
|
|
1973
2069
|
__busy = false;
|
|
1974
2070
|
__iv = (${condExpr});
|
|
1975
2071
|
}
|
|
1976
|
-
});
|
|
2072
|
+
}, true);
|
|
1977
2073
|
}`);
|
|
1978
2074
|
return null;
|
|
1979
2075
|
}
|
|
@@ -2087,7 +2183,7 @@ function emitForLoop(ctx, node, tracked, parentVar, skipK = 0, regionBudget) {
|
|
|
2087
2183
|
__busy = false;
|
|
2088
2184
|
__iv = (${srcExpr});
|
|
2089
2185
|
}
|
|
2090
|
-
});
|
|
2186
|
+
}, true);
|
|
2091
2187
|
}`);
|
|
2092
2188
|
}
|
|
2093
2189
|
else {
|
|
@@ -2156,7 +2252,7 @@ function emitForLoop(ctx, node, tracked, parentVar, skipK = 0, regionBudget) {
|
|
|
2156
2252
|
__cleanup(${anchor}, ${endAnchor});
|
|
2157
2253
|
${ctx.isAsyncScope ? 'await ' : ''}${renderLoop}();
|
|
2158
2254
|
__busy = false;
|
|
2159
|
-
});
|
|
2255
|
+
}, true);
|
|
2160
2256
|
}`);
|
|
2161
2257
|
}
|
|
2162
2258
|
}
|
|
@@ -2233,7 +2329,7 @@ function emitSwitchBlock(ctx, node, tracked, parentVar, skipK = 0, regionBudget)
|
|
|
2233
2329
|
__busy = false;
|
|
2234
2330
|
__iv = (${discExpr});
|
|
2235
2331
|
}
|
|
2236
|
-
});
|
|
2332
|
+
}, true);
|
|
2237
2333
|
}`);
|
|
2238
2334
|
return null;
|
|
2239
2335
|
}
|
|
@@ -2456,7 +2552,7 @@ function emitMap(ctx, node, tracked, effTarget, parentVar, skipK = 0, regionBudg
|
|
|
2456
2552
|
${effectsVar}.length = 0;
|
|
2457
2553
|
__cleanup(${anchor}, ${endAnchor});
|
|
2458
2554
|
if (__new) { ${initList}(); } else { ${aw}${emptyRenderName}(); }
|
|
2459
|
-
})`);
|
|
2555
|
+
}, true)`);
|
|
2460
2556
|
}
|
|
2461
2557
|
else {
|
|
2462
2558
|
ctx.push(`${initList}();`);
|
|
@@ -2466,7 +2562,7 @@ function emitMap(ctx, node, tracked, effTarget, parentVar, skipK = 0, regionBudg
|
|
|
2466
2562
|
const __nv = ${arrExpr};
|
|
2467
2563
|
if (__first) { __first = false; __nv; ${breakReset}${reconciler}(${arrExpr}); return; }
|
|
2468
2564
|
${breakVar ? `if (${breakVar}) ${breakVar} = false;` : ''}${reconciler}(${arrExpr});
|
|
2469
|
-
})`);
|
|
2565
|
+
}, true)`);
|
|
2470
2566
|
}
|
|
2471
2567
|
}
|
|
2472
2568
|
else {
|
|
@@ -2524,7 +2620,7 @@ ${renderAllItems(' ', null)}
|
|
|
2524
2620
|
if (__new) {
|
|
2525
2621
|
${renderAllItems(' ', null)}
|
|
2526
2622
|
} else { ${aw}${emptyRenderName}(${collectVar ? collectVar : ''}); }
|
|
2527
|
-
})`);
|
|
2623
|
+
}, true)`);
|
|
2528
2624
|
}
|
|
2529
2625
|
else {
|
|
2530
2626
|
const collectVar = hyd ? ctx.n() : null;
|
|
@@ -2542,7 +2638,7 @@ ${renderAllItems(' ', null)}
|
|
|
2542
2638
|
${effectsVar}.length = 0;
|
|
2543
2639
|
__cleanup(${anchor}, ${endAnchor});
|
|
2544
2640
|
${renderAllItems(' ', null)}
|
|
2545
|
-
})`);
|
|
2641
|
+
}, true)`);
|
|
2546
2642
|
}
|
|
2547
2643
|
}
|
|
2548
2644
|
return null;
|
package/dist/module-imports.d.ts
CHANGED
|
@@ -106,7 +106,7 @@ export declare function resolveViaPackageExports(specifier: string, fromDir: str
|
|
|
106
106
|
/** Rewrites an ESM program body (imports/exports removed) into CJS statements. */
|
|
107
107
|
export declare function esmToCjs(body: Array<{
|
|
108
108
|
type: string;
|
|
109
|
-
} & Record<string, unknown
|
|
109
|
+
} & Record<string, unknown>>, rewriteImports?: ReadonlySet<string>): string;
|
|
110
110
|
export interface BundledModuleData {
|
|
111
111
|
/** Synthetic loader key (e.g. `__veskMod0`), referenced by deps/bindings. */
|
|
112
112
|
key: string;
|
|
@@ -142,6 +142,13 @@ export interface ModuleEntry {
|
|
|
142
142
|
dir: string;
|
|
143
143
|
/** Relative specifier (as written) -> sibling module key. */
|
|
144
144
|
deps: Record<string, string>;
|
|
145
|
+
/**
|
|
146
|
+
* Absolute path the entry was registered under. Kept so a plan can be
|
|
147
|
+
* replayed into a fresh registry (see `precompile.ts`), where the module
|
|
148
|
+
* key is derived from this path. Never emitted into the deployment
|
|
149
|
+
* registry (which only serializes code/dir/deps).
|
|
150
|
+
*/
|
|
151
|
+
absPath?: string;
|
|
145
152
|
}
|
|
146
153
|
/**
|
|
147
154
|
* Global registry of bundled module source code, shared across every SSR
|
|
@@ -159,7 +166,7 @@ export declare class ModuleRegistry {
|
|
|
159
166
|
has(absPath: string): boolean;
|
|
160
167
|
getKey(absPath: string): string | undefined;
|
|
161
168
|
get size(): number;
|
|
162
|
-
/** Register a module's transpiled body, returning its
|
|
169
|
+
/** Register a module's transpiled body, returning its stable key. */
|
|
163
170
|
register(absPath: string, entry: ModuleEntry): string;
|
|
164
171
|
getModule(key: string): ModuleEntry | undefined;
|
|
165
172
|
/** All registered modules as a plain object keyed by synthetic key, for
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-imports.d.ts","sourceRoot":"","sources":["../src/module-imports.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAGlD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAyEtD,gFAAgF;AAChF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAM7D;AAED,gEAAgE;AAChE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAOzD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgC1F;AAED,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAQpE;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAIvD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,UAAU,EAAE,MAAM,EAAE,EACpB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,IAAI,CAuBN;AAiBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CA8E7E;AAmFD,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,GAAG,IAAI,CAAC;IACrC,mEAAmE;IACnE,UAAU,CAAC,EAAE,SAAS,CAAC;CACxB;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CA+B/D;AAgbD,8DAA8D;AAC9D,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAU/D;AAgDD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiB/E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAoBvE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA+ClF;AA6DD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAwCpF;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA8B9F;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiC1F;
|
|
1
|
+
{"version":3,"file":"module-imports.d.ts","sourceRoot":"","sources":["../src/module-imports.ts"],"names":[],"mappings":"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"}
|
package/dist/module-imports.js
CHANGED
|
@@ -1345,10 +1345,82 @@ function exportGetter(lines, key, valueExpr) {
|
|
|
1345
1345
|
lines.push(`Object.defineProperty(exports, ${JSON.stringify(key)}, { get: () => ${valueExpr}, enumerable: true });`);
|
|
1346
1346
|
}
|
|
1347
1347
|
let exportCounter = 0;
|
|
1348
|
+
/**
|
|
1349
|
+
* `Promise.resolve().then(() => require("<spec>"))` as an AST expression.
|
|
1350
|
+
* Reusing the original literal node keeps its raw quoting.
|
|
1351
|
+
*/
|
|
1352
|
+
function promiseOfRequire(sourceNode) {
|
|
1353
|
+
return {
|
|
1354
|
+
type: 'CallExpression',
|
|
1355
|
+
optional: false,
|
|
1356
|
+
callee: {
|
|
1357
|
+
type: 'MemberExpression',
|
|
1358
|
+
optional: false,
|
|
1359
|
+
computed: false,
|
|
1360
|
+
object: {
|
|
1361
|
+
type: 'CallExpression',
|
|
1362
|
+
optional: false,
|
|
1363
|
+
callee: {
|
|
1364
|
+
type: 'MemberExpression',
|
|
1365
|
+
optional: false,
|
|
1366
|
+
computed: false,
|
|
1367
|
+
object: { type: 'Identifier', name: 'Promise' },
|
|
1368
|
+
property: { type: 'Identifier', name: 'resolve' },
|
|
1369
|
+
},
|
|
1370
|
+
arguments: [],
|
|
1371
|
+
},
|
|
1372
|
+
property: { type: 'Identifier', name: 'then' },
|
|
1373
|
+
},
|
|
1374
|
+
arguments: [
|
|
1375
|
+
{
|
|
1376
|
+
type: 'ArrowFunctionExpression',
|
|
1377
|
+
id: null,
|
|
1378
|
+
expression: true,
|
|
1379
|
+
generator: false,
|
|
1380
|
+
async: false,
|
|
1381
|
+
params: [],
|
|
1382
|
+
body: {
|
|
1383
|
+
type: 'CallExpression',
|
|
1384
|
+
optional: false,
|
|
1385
|
+
callee: { type: 'Identifier', name: 'require' },
|
|
1386
|
+
arguments: [sourceNode],
|
|
1387
|
+
},
|
|
1388
|
+
},
|
|
1389
|
+
],
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
/**
|
|
1393
|
+
* Rewrites `import("<spec>")` for specifiers the SSR module bundle resolved
|
|
1394
|
+
* (those present in the module's `deps`) into a promise of the same
|
|
1395
|
+
* `require` the static-import rewrite emits.
|
|
1396
|
+
*
|
|
1397
|
+
* Registry bodies run inside `new Function`, where a native dynamic `import()`
|
|
1398
|
+
* has no referrer and Node resolves it against the generated function's
|
|
1399
|
+
* location (`/var/task` on Vercel). That directory ships no node_modules, so
|
|
1400
|
+
* e.g. vesk-qr's lazy `import("qrcode-generator")` fails even though the
|
|
1401
|
+
* encoder is already in the bundle. Routing it through the require shim makes
|
|
1402
|
+
* it use `entry.deps`, exactly like a static import.
|
|
1403
|
+
*
|
|
1404
|
+
* Specifiers that were not bundled (framework-owned, `.vsk`, builtins) keep
|
|
1405
|
+
* their original form: the shim and the host loader know how to handle them.
|
|
1406
|
+
*/
|
|
1407
|
+
function rewriteDynamicImports(node, specs) {
|
|
1408
|
+
return walk(node, null, {
|
|
1409
|
+
ImportExpression(n) {
|
|
1410
|
+
const spec = stringLiteralValue(n.source);
|
|
1411
|
+
if (!spec || !specs.has(spec))
|
|
1412
|
+
return;
|
|
1413
|
+
return promiseOfRequire(n.source);
|
|
1414
|
+
},
|
|
1415
|
+
});
|
|
1416
|
+
}
|
|
1348
1417
|
/** Rewrites an ESM program body (imports/exports removed) into CJS statements. */
|
|
1349
|
-
export function esmToCjs(body) {
|
|
1418
|
+
export function esmToCjs(body, rewriteImports) {
|
|
1419
|
+
const statements = rewriteImports
|
|
1420
|
+
? body.map((stmt) => rewriteDynamicImports(stmt, rewriteImports))
|
|
1421
|
+
: body;
|
|
1350
1422
|
const lines = [];
|
|
1351
|
-
for (const stmt of
|
|
1423
|
+
for (const stmt of statements) {
|
|
1352
1424
|
switch (stmt.type) {
|
|
1353
1425
|
case 'ImportDeclaration': {
|
|
1354
1426
|
const source = printNode(stmt.source);
|
|
@@ -1457,6 +1529,35 @@ export function esmToCjs(body) {
|
|
|
1457
1529
|
}
|
|
1458
1530
|
return lines.join('\n');
|
|
1459
1531
|
}
|
|
1532
|
+
/**
|
|
1533
|
+
* Synthetic key for a module. Derived from the absolute path rather than the
|
|
1534
|
+
* registry's insertion order so the SAME module always gets the same key in
|
|
1535
|
+
* every build. Positional keys (`__veskMod${size}`) made cross-build plan
|
|
1536
|
+
* caching unsafe: a second in-process build (the dev server after the prod
|
|
1537
|
+
* build) started with an empty registry, served cached plans whose keys
|
|
1538
|
+
* referred to modules it never registered, and emitted `export const
|
|
1539
|
+
* __veskModules = {}`. Paired with the plan cache replaying each plan's
|
|
1540
|
+
* modules into the fresh registry, a path-derived key makes that replay
|
|
1541
|
+
* idempotent and collision-free.
|
|
1542
|
+
*/
|
|
1543
|
+
function moduleKeyFor(absPath) {
|
|
1544
|
+
// Four independent FNV-1a 32-bit lanes → 128 bits of key space, which makes
|
|
1545
|
+
// an accidental collision between two paths (which would silently swap one
|
|
1546
|
+
// module for another) effectively impossible. Hand-rolled rather than
|
|
1547
|
+
// `node:crypto` because this file is bundled into the edge/server runtime,
|
|
1548
|
+
// where a `node:` import fails to resolve.
|
|
1549
|
+
const seeds = [0x811c9dc5, 0x9e3779b1, 0x85ebca6b, 0xc2b2ae35];
|
|
1550
|
+
let hex = '';
|
|
1551
|
+
for (const seed of seeds) {
|
|
1552
|
+
let h = seed >>> 0;
|
|
1553
|
+
for (let i = 0; i < absPath.length; i++) {
|
|
1554
|
+
h ^= absPath.charCodeAt(i);
|
|
1555
|
+
h = Math.imul(h, 0x01000193) >>> 0;
|
|
1556
|
+
}
|
|
1557
|
+
hex += h.toString(16).padStart(8, '0');
|
|
1558
|
+
}
|
|
1559
|
+
return `__veskMod${hex}`;
|
|
1560
|
+
}
|
|
1460
1561
|
/**
|
|
1461
1562
|
* Global registry of bundled module source code, shared across every SSR
|
|
1462
1563
|
* function in a single build. Without it, every page plan re-embedded the
|
|
@@ -1479,14 +1580,14 @@ export class ModuleRegistry {
|
|
|
1479
1580
|
get size() {
|
|
1480
1581
|
return this.data.size;
|
|
1481
1582
|
}
|
|
1482
|
-
/** Register a module's transpiled body, returning its
|
|
1583
|
+
/** Register a module's transpiled body, returning its stable key. */
|
|
1483
1584
|
register(absPath, entry) {
|
|
1484
1585
|
const existing = this.keysByAbs.get(absPath);
|
|
1485
1586
|
if (existing)
|
|
1486
1587
|
return existing;
|
|
1487
|
-
const key =
|
|
1588
|
+
const key = moduleKeyFor(absPath);
|
|
1488
1589
|
this.keysByAbs.set(absPath, key);
|
|
1489
|
-
this.data.set(key, entry);
|
|
1590
|
+
this.data.set(key, { ...entry, absPath });
|
|
1490
1591
|
return key;
|
|
1491
1592
|
}
|
|
1492
1593
|
getModule(key) {
|
|
@@ -1520,41 +1621,51 @@ function stringLiteralValue(node) {
|
|
|
1520
1621
|
*/
|
|
1521
1622
|
function collectModuleSpecifiers(ast) {
|
|
1522
1623
|
const specs = new Set();
|
|
1624
|
+
// Every type-specific visitor MUST call `next()`. zimmerframe only recurses
|
|
1625
|
+
// into a node's children when its visitor does — the default visitor is the
|
|
1626
|
+
// one that calls `next`. Without it, an `import()`/`require()` nested inside
|
|
1627
|
+
// an exported function (e.g. vesk-qr's lazy encoder load) was never seen, so
|
|
1628
|
+
// the module was neither bundled nor recorded in `deps`.
|
|
1523
1629
|
walk(ast, null, {
|
|
1524
|
-
ImportDeclaration(node) {
|
|
1525
|
-
if (node.importKind
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1630
|
+
ImportDeclaration(node, ctx) {
|
|
1631
|
+
if (node.importKind !== 'type') {
|
|
1632
|
+
const v = stringLiteralValue(node.source);
|
|
1633
|
+
if (v)
|
|
1634
|
+
specs.add(v);
|
|
1635
|
+
}
|
|
1636
|
+
ctx.next();
|
|
1530
1637
|
},
|
|
1531
|
-
ExportNamedDeclaration(node) {
|
|
1532
|
-
if (
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1638
|
+
ExportNamedDeclaration(node, ctx) {
|
|
1639
|
+
if (node.exportKind !== 'type' && node.source) {
|
|
1640
|
+
const v = stringLiteralValue(node.source);
|
|
1641
|
+
if (v)
|
|
1642
|
+
specs.add(v);
|
|
1643
|
+
}
|
|
1644
|
+
ctx.next();
|
|
1537
1645
|
},
|
|
1538
|
-
ExportAllDeclaration(node) {
|
|
1539
|
-
if (node.exportKind
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1646
|
+
ExportAllDeclaration(node, ctx) {
|
|
1647
|
+
if (node.exportKind !== 'type') {
|
|
1648
|
+
const v = stringLiteralValue(node.source);
|
|
1649
|
+
if (v)
|
|
1650
|
+
specs.add(v);
|
|
1651
|
+
}
|
|
1652
|
+
ctx.next();
|
|
1544
1653
|
},
|
|
1545
|
-
CallExpression(node) {
|
|
1654
|
+
CallExpression(node, ctx) {
|
|
1546
1655
|
const callee = node.callee;
|
|
1547
|
-
if (
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1656
|
+
if (callee && callee.type === 'Identifier' && callee.name === 'require') {
|
|
1657
|
+
const args = (node.arguments || []);
|
|
1658
|
+
const v = stringLiteralValue(args[0]);
|
|
1659
|
+
if (v)
|
|
1660
|
+
specs.add(v);
|
|
1661
|
+
}
|
|
1662
|
+
ctx.next();
|
|
1553
1663
|
},
|
|
1554
|
-
ImportExpression(node) {
|
|
1664
|
+
ImportExpression(node, ctx) {
|
|
1555
1665
|
const v = stringLiteralValue(node.source);
|
|
1556
1666
|
if (v)
|
|
1557
1667
|
specs.add(v);
|
|
1668
|
+
ctx.next();
|
|
1558
1669
|
},
|
|
1559
1670
|
});
|
|
1560
1671
|
return specs;
|
|
@@ -1594,6 +1705,7 @@ export function collectModuleBundled(absPath, registry) {
|
|
|
1594
1705
|
const cached = mtimeMs >= 0 ? bundledCodeCache.get(absPath) : undefined;
|
|
1595
1706
|
let code;
|
|
1596
1707
|
let specifiers;
|
|
1708
|
+
let deps = null;
|
|
1597
1709
|
if (cached && cached.mtimeMs === mtimeMs) {
|
|
1598
1710
|
code = cached.code;
|
|
1599
1711
|
specifiers = cached.specifiers;
|
|
@@ -1614,17 +1726,30 @@ export function collectModuleBundled(absPath, registry) {
|
|
|
1614
1726
|
stripped = stripTsTypes(src.ast);
|
|
1615
1727
|
stripped.body = (stripped.body || []).filter((n) => (n ? !isTypeOnlyStatement(n) : false));
|
|
1616
1728
|
specifiers = [...collectModuleSpecifiers(src.ast)];
|
|
1617
|
-
|
|
1729
|
+
// Resolve the closure first: the emitter needs the set of specifiers that
|
|
1730
|
+
// became registry modules so it can route `import("<spec>")` through the
|
|
1731
|
+
// same require shim instead of leaving a bare dynamic import for the host
|
|
1732
|
+
// loader (see `rewriteDynamicImports`).
|
|
1733
|
+
deps = resolveBundledDeps(specifiers, dir, registry);
|
|
1734
|
+
code = esmToCjs(stripped.body, new Set(Object.keys(deps)));
|
|
1618
1735
|
bundledCodeCache.set(absPath, { mtimeMs, code, specifiers });
|
|
1619
1736
|
evict(bundledCodeCache);
|
|
1620
1737
|
}
|
|
1738
|
+
if (!deps)
|
|
1739
|
+
deps = resolveBundledDeps(specifiers, dir, registry);
|
|
1740
|
+
return registry.register(absPath, { code, dir, deps });
|
|
1741
|
+
}
|
|
1742
|
+
/**
|
|
1743
|
+
* Resolves every specifier a module reaches for into the registry key of its
|
|
1744
|
+
* bundled closure. Compiler-owned (`@vesk/*`) targets are injected by the SSR
|
|
1745
|
+
* require shim at runtime (`precompile-runtime.ts`), never bundled: their built
|
|
1746
|
+
* JS may contain identifiers the `.vsk` grammar reserves (`component` in
|
|
1747
|
+
* ripple-runtime.js) and would fail to parse here. `.vsk`/`.css`/`.md` carry no
|
|
1748
|
+
* SSR value. Node builtins load natively through the shim.
|
|
1749
|
+
*/
|
|
1750
|
+
function resolveBundledDeps(specifiers, dir, registry) {
|
|
1621
1751
|
const deps = {};
|
|
1622
1752
|
for (const spec of specifiers) {
|
|
1623
|
-
// Compiler-owned (`@vesk/*`) targets are injected by the SSR require shim
|
|
1624
|
-
// at runtime (`precompile-runtime.ts`), never bundled: their built JS may
|
|
1625
|
-
// contain identifiers the `.vsk` grammar reserves (`component` in
|
|
1626
|
-
// ripple-runtime.js) and would fail to parse here. `.vsk`/`.css`/`.md`
|
|
1627
|
-
// carry no SSR value. Node builtins load natively through the shim.
|
|
1628
1753
|
if (isCompilerOwnedTarget(spec) || isValueLessTarget(spec))
|
|
1629
1754
|
continue;
|
|
1630
1755
|
const depPath = resolveSsrModule(spec, dir);
|
|
@@ -1632,7 +1757,7 @@ export function collectModuleBundled(absPath, registry) {
|
|
|
1632
1757
|
continue;
|
|
1633
1758
|
deps[spec] = collectModuleBundled(depPath, registry);
|
|
1634
1759
|
}
|
|
1635
|
-
return
|
|
1760
|
+
return deps;
|
|
1636
1761
|
}
|
|
1637
1762
|
const bundledCodeCache = new Map();
|
|
1638
1763
|
/**
|
package/dist/precompile.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"precompile.d.ts","sourceRoot":"","sources":["../src/precompile.ts"],"names":[],"mappings":"AASA,OAAO,
|
|
1
|
+
{"version":3,"file":"precompile.d.ts","sourceRoot":"","sources":["../src/precompile.ts"],"names":[],"mappings":"AASA,OAAO,EAIL,cAAc,EACf,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EACV,kBAAkB,EAGnB,MAAM,uCAAuC,CAAC;AAG/C;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,QAAQ,CAAC,EAAE,cAAc,GACxB,kBAAkB,CAsBpB;AA8CD,iFAAiF;AACjF,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
|
package/dist/precompile.js
CHANGED
|
@@ -26,16 +26,54 @@ export function precompileFile(source, sourcePath, registry) {
|
|
|
26
26
|
const hit = precompileCache.get(sourcePath);
|
|
27
27
|
// Compare the source, not just the path: the dev server rebuilds in-process
|
|
28
28
|
// and a stale plan would silently ship yesterday's component.
|
|
29
|
-
if (hit !== undefined && hit.source === source)
|
|
29
|
+
if (hit !== undefined && hit.source === source) {
|
|
30
|
+
// A plan is only half of the output: it references module keys that live
|
|
31
|
+
// in the caller's registry. A second build in the same process (prod then
|
|
32
|
+
// dev under `e2e-setup`) starts with a fresh registry, so replaying the
|
|
33
|
+
// memoized plan without its modules left `__veskModules` empty and every
|
|
34
|
+
// bare-package import (`vesk-qr`, …) resolved to `undefined`. Keys are
|
|
35
|
+
// path-derived, so registering the same absPaths here is idempotent.
|
|
36
|
+
for (const { absPath, entry } of hit.modules)
|
|
37
|
+
reg.register(absPath, entry);
|
|
30
38
|
return hit.plan;
|
|
39
|
+
}
|
|
31
40
|
const plan = precompileFileInternal(source, sourcePath, new Set(), reg);
|
|
32
41
|
// Bound it: plans are sizeable on a large app, and a watch session can
|
|
33
42
|
// outlive many builds.
|
|
34
43
|
if (precompileCache.size >= 512)
|
|
35
44
|
precompileCache.clear();
|
|
36
|
-
precompileCache.set(sourcePath, { source, plan });
|
|
45
|
+
precompileCache.set(sourcePath, { source, plan, modules: collectPlanModules(plan, reg) });
|
|
37
46
|
return plan;
|
|
38
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Every module entry a plan (and its nested `.vsk` sub-plans) resolves
|
|
50
|
+
* against, including transitive deps. The shared `__veskModules` registry
|
|
51
|
+
* must contain the whole closure, not just the keys named by `plan.modules`,
|
|
52
|
+
* or `evaluateModule` cannot walk `deps` at hydrate time.
|
|
53
|
+
*/
|
|
54
|
+
function collectPlanModules(plan, registry) {
|
|
55
|
+
const out = [];
|
|
56
|
+
const seen = new Set();
|
|
57
|
+
const visitKey = (key) => {
|
|
58
|
+
if (seen.has(key))
|
|
59
|
+
return;
|
|
60
|
+
seen.add(key);
|
|
61
|
+
const entry = registry.getModule(key);
|
|
62
|
+
if (!entry || !entry.absPath)
|
|
63
|
+
return;
|
|
64
|
+
out.push({ absPath: entry.absPath, entry });
|
|
65
|
+
for (const depKey of Object.values(entry.deps))
|
|
66
|
+
visitKey(depKey);
|
|
67
|
+
};
|
|
68
|
+
const visitPlan = (p) => {
|
|
69
|
+
for (const mod of p.modules)
|
|
70
|
+
visitKey(mod.key);
|
|
71
|
+
for (const sub of p.subFiles)
|
|
72
|
+
visitPlan(sub.plan);
|
|
73
|
+
};
|
|
74
|
+
visitPlan(plan);
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
39
77
|
/**
|
|
40
78
|
* Compiled plans, keyed by absolute path.
|
|
41
79
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vesk/compiler",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.94",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vesk compiler — lexer, parser, semantic analysis, IR, codegen",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@sveltejs/acorn-typescript": "^1.0.0",
|
|
23
|
-
"@vesk/types": "^0.2.
|
|
23
|
+
"@vesk/types": "^0.2.94",
|
|
24
24
|
"acorn": "^8.15.0",
|
|
25
25
|
"esrap": "^2.3.0",
|
|
26
26
|
"is-reference": "^3.0.0",
|