@vesk/compiler 0.2.83 → 0.2.85

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.
@@ -125,20 +125,62 @@ export interface ModuleBindingData {
125
125
  /** `default` | `*` | named export. */
126
126
  kind: string;
127
127
  }
128
+ /** Lightweight plan-level reference to a bundled module (no source code). */
129
+ export interface ModuleRef {
130
+ /** Synthetic loader key (e.g. `__veskMod0`), referenced by deps/bindings. */
131
+ key: string;
132
+ /** Directory the module lived in at build time (require fallback anchor). */
133
+ dir: string;
134
+ /** Relative specifier (as written) -> sibling module key. */
135
+ deps: Record<string, string>;
136
+ }
137
+ /** What the registry stores per key: the transpiled body plus anchor dir/deps. */
138
+ export interface ModuleEntry {
139
+ /** ESM->CJS rewritten body (or raw CJS / JSON `module.exports` body). */
140
+ code: string;
141
+ /** Directory the module lived in at build time (require fallback anchor). */
142
+ dir: string;
143
+ /** Relative specifier (as written) -> sibling module key. */
144
+ deps: Record<string, string>;
145
+ }
146
+ /**
147
+ * Global registry of bundled module source code, shared across every SSR
148
+ * function in a single build. Without it, every page plan re-embedded the
149
+ * full source of every module it transitively imports — a docs-style app
150
+ * whose 40 pages all import `lucide-vevk` stored its ~1.8 MB `buildSvgString`
151
+ * 40 times, inflating the single serverless handler to hundreds of megabytes
152
+ * and OOM-killing cold starts. Modules are registered once and every plan
153
+ * references them by key; the registry source is emitted into one shared file
154
+ * imported by every SSR function.
155
+ */
156
+ export declare class ModuleRegistry {
157
+ private keysByAbs;
158
+ private data;
159
+ has(absPath: string): boolean;
160
+ getKey(absPath: string): string | undefined;
161
+ get size(): number;
162
+ /** Register a module's transpiled body, returning its globally-unique key. */
163
+ register(absPath: string, entry: ModuleEntry): string;
164
+ getModule(key: string): ModuleEntry | undefined;
165
+ /** All registered modules as a plain object keyed by synthetic key, for
166
+ * passing to `hydratePrecompile` at SSR load time. */
167
+ modules(): Record<string, ModuleEntry>;
168
+ /** Emit a self-contained module registry source file. */
169
+ toModuleSource(): string;
170
+ }
128
171
  export type ModuleCollector = {
129
- keysByAbs: Map<string, string>;
130
- modules: BundledModuleData[];
172
+ modules: ModuleRef[];
131
173
  };
132
174
  /**
133
175
  * Bundles one module file (plus its relative closure) into `collector`.
134
176
  * Returns the synthetic key loaded modules use to reference it.
135
177
  */
136
- export declare function collectModuleBundled(absPath: string, collector: ModuleCollector): string;
178
+ export declare function collectModuleBundled(absPath: string, registry: ModuleRegistry): string;
137
179
  /**
138
180
  * Builds the module bundle + local-binding list for a set of import lines
139
181
  * (a `.vsk` file's `imports`). Framework-owned, `.vsk`, `.css` and markdown
140
182
  * targets are skipped exactly as `applyLocalModuleImports` skips them, so the
141
183
  * hydrate-time scope matches today's runtime module loader.
142
184
  */
143
- export declare function collectModuleBundle(importStrs: string[], fromDir: string | undefined, collector: ModuleCollector): ModuleBindingData[];
185
+ export declare function collectModuleBundle(importStrs: string[], fromDir: string | undefined, registry: ModuleRegistry, collector: ModuleCollector): ModuleBindingData[];
144
186
  //# sourceMappingURL=module-imports.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"module-imports.d.ts","sourceRoot":"","sources":["../src/module-imports.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"module-imports.d.ts","sourceRoot":"","sources":["../src/module-imports.ts"],"names":[],"mappings":"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"}
@@ -1437,6 +1437,55 @@ export function esmToCjs(body) {
1437
1437
  }
1438
1438
  return lines.join('\n');
1439
1439
  }
1440
+ /**
1441
+ * Global registry of bundled module source code, shared across every SSR
1442
+ * function in a single build. Without it, every page plan re-embedded the
1443
+ * full source of every module it transitively imports — a docs-style app
1444
+ * whose 40 pages all import `lucide-vevk` stored its ~1.8 MB `buildSvgString`
1445
+ * 40 times, inflating the single serverless handler to hundreds of megabytes
1446
+ * and OOM-killing cold starts. Modules are registered once and every plan
1447
+ * references them by key; the registry source is emitted into one shared file
1448
+ * imported by every SSR function.
1449
+ */
1450
+ export class ModuleRegistry {
1451
+ keysByAbs = new Map();
1452
+ data = new Map();
1453
+ has(absPath) {
1454
+ return this.keysByAbs.has(absPath);
1455
+ }
1456
+ getKey(absPath) {
1457
+ return this.keysByAbs.get(absPath);
1458
+ }
1459
+ get size() {
1460
+ return this.data.size;
1461
+ }
1462
+ /** Register a module's transpiled body, returning its globally-unique key. */
1463
+ register(absPath, entry) {
1464
+ const existing = this.keysByAbs.get(absPath);
1465
+ if (existing)
1466
+ return existing;
1467
+ const key = `__veskMod${this.data.size}`;
1468
+ this.keysByAbs.set(absPath, key);
1469
+ this.data.set(key, entry);
1470
+ return key;
1471
+ }
1472
+ getModule(key) {
1473
+ return this.data.get(key);
1474
+ }
1475
+ /** All registered modules as a plain object keyed by synthetic key, for
1476
+ * passing to `hydratePrecompile` at SSR load time. */
1477
+ modules() {
1478
+ return Object.fromEntries(this.data.entries());
1479
+ }
1480
+ /** Emit a self-contained module registry source file. */
1481
+ toModuleSource() {
1482
+ const parts = [];
1483
+ for (const [key, entry] of this.data) {
1484
+ parts.push(`${JSON.stringify(key)}: ${JSON.stringify({ code: entry.code, dir: entry.dir, deps: entry.deps })}`);
1485
+ }
1486
+ return `export const __veskModules = {${parts.join(',')}};\n`;
1487
+ }
1488
+ }
1440
1489
  function isRelativeSpec(spec) {
1441
1490
  return spec.startsWith('./') || spec.startsWith('../');
1442
1491
  }
@@ -1497,12 +1546,10 @@ function collectModuleSpecifiers(ast) {
1497
1546
  * Bundles one module file (plus its relative closure) into `collector`.
1498
1547
  * Returns the synthetic key loaded modules use to reference it.
1499
1548
  */
1500
- export function collectModuleBundled(absPath, collector) {
1501
- const existing = collector.keysByAbs.get(absPath);
1549
+ export function collectModuleBundled(absPath, registry) {
1550
+ const existing = registry.getKey(absPath);
1502
1551
  if (existing)
1503
1552
  return existing;
1504
- const key = `__veskMod${collector.keysByAbs.size}`;
1505
- collector.keysByAbs.set(absPath, key);
1506
1553
  const dir = dirname(absPath);
1507
1554
  if (absPath.endsWith('.json')) {
1508
1555
  let raw = '';
@@ -1512,8 +1559,7 @@ export function collectModuleBundled(absPath, collector) {
1512
1559
  catch (err) {
1513
1560
  raw = '{}';
1514
1561
  }
1515
- collector.modules.push({ key, code: `module.exports = ${raw};`, dir, deps: {} });
1516
- return key;
1562
+ return registry.register(absPath, { code: `module.exports = ${raw};`, dir, deps: {} });
1517
1563
  }
1518
1564
  // The transpiled code and the relative specifiers of a module do not depend
1519
1565
  // on which collector is asking, only on the file — and every `.vsk` compile
@@ -1544,8 +1590,7 @@ export function collectModuleBundled(absPath, collector) {
1544
1590
  if (src?.parseError)
1545
1591
  throw src.parseError;
1546
1592
  const raw = src ? src.raw : '// unreadable during build\nmodule.exports = {};';
1547
- collector.modules.push({ key, code: raw, dir, deps: {} });
1548
- return key;
1593
+ return registry.register(absPath, { code: raw, dir, deps: {} });
1549
1594
  }
1550
1595
  let stripped = src.ast;
1551
1596
  if (hasTsSyntax(src.ast))
@@ -1563,10 +1608,9 @@ export function collectModuleBundled(absPath, collector) {
1563
1608
  const depPath = resolveSsrModule(spec, dir);
1564
1609
  if (!depPath)
1565
1610
  continue;
1566
- deps[spec] = collectModuleBundled(depPath, collector);
1611
+ deps[spec] = collectModuleBundled(depPath, registry);
1567
1612
  }
1568
- collector.modules.push({ key, code, dir, deps });
1569
- return key;
1613
+ return registry.register(absPath, { code, dir, deps });
1570
1614
  }
1571
1615
  const bundledCodeCache = new Map();
1572
1616
  /**
@@ -1575,10 +1619,11 @@ const bundledCodeCache = new Map();
1575
1619
  * targets are skipped exactly as `applyLocalModuleImports` skips them, so the
1576
1620
  * hydrate-time scope matches today's runtime module loader.
1577
1621
  */
1578
- export function collectModuleBundle(importStrs, fromDir, collector) {
1622
+ export function collectModuleBundle(importStrs, fromDir, registry, collector) {
1579
1623
  const bindings = [];
1580
1624
  if (!fromDir)
1581
1625
  return bindings;
1626
+ const seenKeys = new Set();
1582
1627
  for (const imp of importStrs) {
1583
1628
  const target = importModuleTarget(imp);
1584
1629
  if (!target || isCompilerOwnedTarget(target) || isValueLessTarget(target))
@@ -1588,7 +1633,12 @@ export function collectModuleBundle(importStrs, fromDir, collector) {
1588
1633
  // Keep render behavior identical to the runtime loader (warn + skip).
1589
1634
  continue;
1590
1635
  }
1591
- const key = collectModuleBundled(resolved, collector);
1636
+ const key = collectModuleBundled(resolved, registry);
1637
+ const mod = registry.getModule(key);
1638
+ if (mod && !seenKeys.has(key)) {
1639
+ seenKeys.add(key);
1640
+ collector.modules.push({ key, dir: mod.dir, deps: mod.deps });
1641
+ }
1592
1642
  for (const pair of importBindingPairs(imp)) {
1593
1643
  bindings.push({ local: pair.local, key, kind: pair.imported });
1594
1644
  }
@@ -1,12 +1,12 @@
1
1
  import type { CompileFileResult } from '@vesk/compiler/src/types';
2
- import type { BundledModuleData, ModuleBindingData } from '@vesk/compiler/src/module-imports';
2
+ import type { ModuleBindingData, ModuleEntry, ModuleRef } from '@vesk/compiler/src/module-imports';
3
3
  export interface PrecompiledComponentEntry {
4
4
  name: string;
5
5
  /** Compiled component body source (`buildComponentMap`-style function code). */
6
6
  source: string;
7
7
  isAsync: boolean;
8
8
  }
9
- export type PrecompileBundledModule = BundledModuleData;
9
+ export type PrecompileBundledModule = ModuleRef;
10
10
  export type PrecompileBinding = ModuleBindingData;
11
11
  export interface PrecompileSubFilePlan {
12
12
  importPath: string;
@@ -19,8 +19,8 @@ export interface PrecompileFilePlan {
19
19
  runtimeImports: string[];
20
20
  /** This file's own compiled components. */
21
21
  components: PrecompiledComponentEntry[];
22
- /** The module bundle backing this file's local value imports. */
23
- modules: PrecompileBundledModule[];
22
+ /** The module bundle backing this file's local value imports (keys into the shared __veskModules registry). */
23
+ modules: ModuleRef[];
24
24
  /** local name -> bundled module export. */
25
25
  bindings: PrecompileBinding[];
26
26
  /** Top-level statements, already `defineAction`-transformed for `server`. */
@@ -50,5 +50,5 @@ export declare function irFromJSON(value: unknown): unknown;
50
50
  * `precompile.ts` plan at SSR function load time. No source, no disk, no
51
51
  * syntax analysis — the plan is fully compiled at build time.
52
52
  */
53
- export declare function hydratePrecompile(plan: PrecompileFilePlan): CompileFileResult;
53
+ export declare function hydratePrecompile(plan: PrecompileFilePlan, modules: Record<string, ModuleEntry>): CompileFileResult;
54
54
  //# sourceMappingURL=precompile-runtime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"precompile-runtime.d.ts","sourceRoot":"","sources":["../src/precompile-runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AA0BlE,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAe9F,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,uBAAuB,GAAG,iBAAiB,CAAC;AAExD,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAElD,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,kBAAkB,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,iFAAiF;IACjF,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IACnB,8DAA8D;IAC9D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,2CAA2C;IAC3C,UAAU,EAAE,yBAAyB,EAAE,CAAC;IACxC,iEAAiE;IACjE,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,2CAA2C;IAC3C,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,6EAA6E;IAC7E,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,0DAA0D;IAC1D,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAqCD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAiBhD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA0BlD;AAoID;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,iBAAiB,CAE7E"}
1
+ {"version":3,"file":"precompile-runtime.d.ts","sourceRoot":"","sources":["../src/precompile-runtime.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AA0BlE,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAenG,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,uBAAuB,GAAG,SAAS,CAAC;AAEhD,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,CAAC;AAElD,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,kBAAkB,CAAC;CAC1B;AAED,MAAM,WAAW,kBAAkB;IACjC,iFAAiF;IACjF,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IACnB,8DAA8D;IAC9D,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,2CAA2C;IAC3C,UAAU,EAAE,yBAAyB,EAAE,CAAC;IACxC,+GAA+G;IAC/G,OAAO,EAAE,SAAS,EAAE,CAAC;IACrB,2CAA2C;IAC3C,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,6EAA6E;IAC7E,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,0DAA0D;IAC1D,QAAQ,EAAE,qBAAqB,EAAE,CAAC;IAClC;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAqCD;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAiBhD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA0BlD;AA0ID;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,kBAAkB,EACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GACnC,iBAAiB,CAEnB"}
@@ -97,30 +97,27 @@ export function irFromJSON(value) {
97
97
  // ---------------------------------------------------------------------------
98
98
  // Hydration.
99
99
  // ---------------------------------------------------------------------------
100
- function hydrateModuleScope(scope, plan) {
100
+ function hydrateModuleScope(scope, plan, modules) {
101
101
  if (!plan.modules || plan.modules.length === 0)
102
102
  return;
103
- const byKey = new Map();
104
- for (const m of plan.modules)
105
- byKey.set(m.key, m);
106
103
  const exportsByKey = new Map();
107
104
  const evaluateModule = (key) => {
108
105
  const existing = exportsByKey.get(key);
109
106
  if (existing)
110
107
  return existing;
111
- const mod = byKey.get(key);
112
- if (!mod)
108
+ const entry = modules[key];
109
+ if (!entry)
113
110
  return null;
114
111
  const exportsObj = {};
115
112
  exportsByKey.set(key, exportsObj);
116
113
  const moduleObj = { exports: exportsObj };
117
114
  const requireShim = (spec) => {
118
- const depKey = mod.deps[spec];
115
+ const depKey = entry.deps[spec];
119
116
  if (depKey)
120
117
  return evaluateModule(depKey) || {};
121
118
  // Framework runtime imports resolve to the instance the SSR bundle
122
119
  // already loaded. Leaving them to the real loader broke every
123
- // serverless deployment: `mod.dir` is the BUILD-time absolute path
120
+ // serverless deployment: `entry.dir` is the BUILD-time absolute path
124
121
  // (/vercel/path0/src/_lib), which does not exist at runtime, so
125
122
  // `require('@vesk/runtime')` walked a market that was not there.
126
123
  if (spec === '@vesk/runtime' ||
@@ -135,7 +132,7 @@ function hydrateModuleScope(scope, plan) {
135
132
  // real loader. Anchor at the module's own dir first (dev/local), then at
136
133
  // the process cwd, which is the deployment root on serverless hosts.
137
134
  let lastErr;
138
- for (const anchor of [mod.dir, process.cwd()]) {
135
+ for (const anchor of [entry.dir, process.cwd()]) {
139
136
  try {
140
137
  return createRequire(join(anchor, '__vesk__.js'))(spec);
141
138
  }
@@ -143,16 +140,16 @@ function hydrateModuleScope(scope, plan) {
143
140
  lastErr = err;
144
141
  }
145
142
  }
146
- throw new Error(`Cannot resolve '${spec}' required by ${mod.key} during SSR hydrate: ${lastErr?.message}`);
143
+ throw new Error(`Cannot resolve '${spec}' required by ${key} during SSR hydrate: ${lastErr?.message}`);
147
144
  };
148
145
  try {
149
- const body = mod.code ? `'use strict';\n${mod.code}` : "'use strict';";
146
+ const body = entry.code ? `'use strict';\n${entry.code}` : "'use strict';";
150
147
  const fn = new Function('require', 'module', 'exports', '__dirname', '__filename', body);
151
- fn(requireShim, moduleObj, moduleObj.exports, mod.dir, join(mod.dir, '__vesk__.js'));
148
+ fn(requireShim, moduleObj, moduleObj.exports, entry.dir, join(entry.dir, '__vesk__.js'));
152
149
  }
153
150
  catch (err) {
154
151
  exportsByKey.delete(key);
155
- console.warn(`[vesk] SSR: failed to evaluate bundled module ${mod.key} (${mod.dir}): ` +
152
+ console.warn(`[vesk] SSR: failed to evaluate bundled module ${key} (${entry.dir}): ` +
156
153
  `${err?.message ?? String(err)}`);
157
154
  return null;
158
155
  }
@@ -185,10 +182,10 @@ function hydrateModuleScope(scope, plan) {
185
182
  }
186
183
  }
187
184
  }
188
- function hydrateFile(plan, seen) {
185
+ function hydrateFile(plan, seen, modules) {
189
186
  const ir = plan.ir ? irFromJSON(plan.ir) : new IRRoot([], [], new Set(), null, null, []);
190
187
  const __vesk = loadRuntimeImports(plan.runtimeImports || []);
191
- hydrateModuleScope(__vesk, plan);
188
+ hydrateModuleScope(__vesk, plan, modules);
192
189
  evalTopLevelCode(plan.topLevelCode || [], __vesk);
193
190
  const componentMap = new Map();
194
191
  for (const entry of plan.components || []) {
@@ -206,7 +203,7 @@ function hydrateFile(plan, seen) {
206
203
  if (seen.has(sub.importPath))
207
204
  continue;
208
205
  seen.add(sub.importPath);
209
- const subResult = hydrateFile(sub.plan, seen);
206
+ const subResult = hydrateFile(sub.plan, seen, modules);
210
207
  for (const [name, fn] of subResult.componentMap) {
211
208
  if (!componentMap.has(name))
212
209
  componentMap.set(name, fn);
@@ -227,6 +224,6 @@ function hydrateFile(plan, seen) {
227
224
  * `precompile.ts` plan at SSR function load time. No source, no disk, no
228
225
  * syntax analysis — the plan is fully compiled at build time.
229
226
  */
230
- export function hydratePrecompile(plan) {
231
- return hydrateFile(plan, new Set());
227
+ export function hydratePrecompile(plan, modules) {
228
+ return hydrateFile(plan, new Set(), modules);
232
229
  }
@@ -1,3 +1,4 @@
1
+ import { ModuleRegistry } from '@vesk/compiler/src/module-imports';
1
2
  import type { PrecompileFilePlan } from '@vesk/compiler/src/precompile-runtime';
2
3
  /**
3
4
  * Precompiles one `.vsk` file into a `PrecompileFilePlan` at BUILD time.
@@ -9,7 +10,7 @@ import type { PrecompileFilePlan } from '@vesk/compiler/src/precompile-runtime';
9
10
  * `CompileFileResult` at load time with `hydratePrecompile`, with no disk
10
11
  * access and no `.vsk` source embedded in the deployment.
11
12
  */
12
- export declare function precompileFile(source: string, sourcePath?: string): PrecompileFilePlan;
13
+ export declare function precompileFile(source: string, sourcePath?: string, registry?: ModuleRegistry): PrecompileFilePlan;
13
14
  /** Drop the plan cache (tests, and any caller that compiles outside a build). */
14
15
  export declare function clearPrecompileCache(): void;
15
16
  //# sourceMappingURL=precompile.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"precompile.d.ts","sourceRoot":"","sources":["../src/precompile.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,kBAAkB,EAGnB,MAAM,uCAAuC,CAAC;AAG/C;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAYtF;AAeD,iFAAiF;AACjF,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
1
+ {"version":3,"file":"precompile.d.ts","sourceRoot":"","sources":["../src/precompile.ts"],"names":[],"mappings":"AASA,OAAO,EAGL,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,CAapB;AAeD,iFAAiF;AACjF,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
@@ -7,7 +7,7 @@ import { buildComponentEntries } from '@vesk/compiler/src/server-jsgen';
7
7
  import { transformTopLevelForActions } from '@vesk/compiler/src/actions';
8
8
  import { collectVskImportPaths, collectVskReexportPaths } from '@vesk/compiler/src/vsk-imports';
9
9
  import { inlineMdImportsFrom, guessProjectRoots } from '@vesk/compiler/src/md-inline';
10
- import { collectModuleBundle, } from '@vesk/compiler/src/module-imports';
10
+ import { collectModuleBundle, ModuleRegistry, } from '@vesk/compiler/src/module-imports';
11
11
  import { irToJSON } from '@vesk/compiler/src/precompile-runtime';
12
12
  /**
13
13
  * Precompiles one `.vsk` file into a `PrecompileFilePlan` at BUILD time.
@@ -19,15 +19,16 @@ import { irToJSON } from '@vesk/compiler/src/precompile-runtime';
19
19
  * `CompileFileResult` at load time with `hydratePrecompile`, with no disk
20
20
  * access and no `.vsk` source embedded in the deployment.
21
21
  */
22
- export function precompileFile(source, sourcePath) {
22
+ export function precompileFile(source, sourcePath, registry) {
23
+ const reg = registry ?? new ModuleRegistry();
23
24
  if (sourcePath === undefined)
24
- return precompileFileInternal(source, sourcePath, new Set());
25
+ return precompileFileInternal(source, sourcePath, new Set(), reg);
25
26
  const hit = precompileCache.get(sourcePath);
26
27
  // Compare the source, not just the path: the dev server rebuilds in-process
27
28
  // and a stale plan would silently ship yesterday's component.
28
29
  if (hit !== undefined && hit.source === source)
29
30
  return hit.plan;
30
- const plan = precompileFileInternal(source, sourcePath, new Set());
31
+ const plan = precompileFileInternal(source, sourcePath, new Set(), reg);
31
32
  // Bound it: plans are sizeable on a large app, and a watch session can
32
33
  // outlive many builds.
33
34
  if (precompileCache.size >= 512)
@@ -51,7 +52,7 @@ const precompileCache = new Map();
51
52
  export function clearPrecompileCache() {
52
53
  precompileCache.clear();
53
54
  }
54
- function precompileFileInternal(source, sourcePath, seenImportFiles) {
55
+ function precompileFileInternal(source, sourcePath, seenImportFiles, registry) {
55
56
  if (sourcePath) {
56
57
  const dir = dirname(sourcePath);
57
58
  source = inlineMdImportsFrom(source, sourcePath, guessProjectRoots(dir));
@@ -76,8 +77,8 @@ function precompileFileInternal(source, sourcePath, seenImportFiles) {
76
77
  const topLevelCode = transformTopLevelForActions(ir.topLevelCode, 'server');
77
78
  const metadataSource = ir.metadataSource || null;
78
79
  const runtimeImports = ir.imports.slice();
79
- const collector = { keysByAbs: new Map(), modules: [] };
80
- const bindings = sourcePath !== undefined ? collectModuleBundle(ir.imports, dirname(sourcePath), collector) : [];
80
+ const collector = { modules: [] };
81
+ const bindings = sourcePath !== undefined ? collectModuleBundle(ir.imports, dirname(sourcePath), registry, collector) : [];
81
82
  const subFiles = [];
82
83
  if (sourcePath !== undefined) {
83
84
  const vskPaths = [
@@ -90,7 +91,7 @@ function precompileFileInternal(source, sourcePath, seenImportFiles) {
90
91
  seenImportFiles.add(importPath);
91
92
  try {
92
93
  const importedSrc = readFileSync(importPath, 'utf-8');
93
- const subPlan = precompileFileInternal(importedSrc, importPath, seenImportFiles);
94
+ const subPlan = precompileFileInternal(importedSrc, importPath, seenImportFiles, registry);
94
95
  subFiles.push({ importPath, plan: subPlan });
95
96
  }
96
97
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesk/compiler",
3
- "version": "0.2.83",
3
+ "version": "0.2.85",
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.83",
23
+ "@vesk/types": "^0.2.85",
24
24
  "acorn": "^8.15.0",
25
25
  "esrap": "^2.3.0",
26
26
  "is-reference": "^3.0.0",