@vesk/compiler 0.2.46 → 0.2.47

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.
@@ -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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"}
@@ -301,15 +301,70 @@ function depsFresh(cachedVal) {
301
301
  }
302
302
  return true;
303
303
  }
304
- export function readSsrSource(absPath) {
304
+ /**
305
+ * Raw file contents, keyed by path and validated by mtime.
306
+ *
307
+ * `readSsrSource` is on the hot path of every `.vsk` compile: a page's module
308
+ * bundle pulls in its `.ts`/`.js` imports, and a docs-style app where 26 pages
309
+ * all import one content module read and re-parsed that module 26 times. The
310
+ * parsed AST is deliberately NOT shared (callers mutate it — `stripTsTypes`,
311
+ * `stripped.body = ...`) and is still produced per call; only the immutable
312
+ * text is reused, and only while the file's mtime is unchanged, so an edit in
313
+ * a watch session is picked up immediately.
314
+ */
315
+ const rawSourceCache = new Map();
316
+ /**
317
+ * Bounded, insertion-ordered eviction.
318
+ *
319
+ * The cap has to clear the OLDEST entries, not the whole map: an app that
320
+ * imports an icon barrel walks 1,600+ modules, and a 512-entry cap with
321
+ * `clear()` on overflow thrashed itself into a 0% hit rate (11,235 reads of
322
+ * 1,620 distinct files on vesk-doc). Draining the front keeps the hot modules
323
+ * resident and bounds memory.
324
+ */
325
+ const BUILD_CACHE_MAX = 8192;
326
+ const BUILD_CACHE_EVICT = 2048;
327
+ function evict(cache) {
328
+ if (cache.size <= BUILD_CACHE_MAX)
329
+ return;
330
+ let dropped = 0;
331
+ for (const key of cache.keys()) {
332
+ cache.delete(key);
333
+ if (++dropped >= BUILD_CACHE_EVICT)
334
+ break;
335
+ }
336
+ }
337
+ function readSourceCached(absPath) {
338
+ let mtimeMs;
339
+ try {
340
+ mtimeMs = statSync(absPath).mtimeMs;
341
+ }
342
+ catch {
343
+ return null;
344
+ }
345
+ const hit = rawSourceCache.get(absPath);
346
+ if (hit && hit.mtimeMs === mtimeMs)
347
+ return hit.raw;
305
348
  let raw;
306
349
  try {
307
350
  raw = readFileSync(absPath, 'utf-8');
308
351
  }
309
- catch (err) {
310
- console.warn(`[vesk] SSR: failed to read ${absPath}: ${err?.message ?? String(err)}`);
352
+ catch {
353
+ return null;
354
+ }
355
+ rawSourceCache.set(absPath, { mtimeMs, raw });
356
+ evict(rawSourceCache);
357
+ return raw;
358
+ }
359
+ export function readSsrSource(absPath) {
360
+ const cachedRaw = readSourceCached(absPath);
361
+ if (cachedRaw === null) {
362
+ // Keep the original warning: a missing module is a build-time signal, not
363
+ // a cache miss to swallow.
364
+ console.warn(`[vesk] SSR: failed to read ${absPath}`);
311
365
  return null;
312
366
  }
367
+ const raw = cachedRaw;
313
368
  let ast = null;
314
369
  try {
315
370
  ast = parse(raw, { filename: absPath });
@@ -1208,18 +1263,44 @@ export function collectModuleBundled(absPath, collector) {
1208
1263
  collector.modules.push({ key, code: `module.exports = ${raw};`, dir, deps: {} });
1209
1264
  return key;
1210
1265
  }
1211
- const src = readSsrSource(absPath);
1212
- if (!src || !src.ast) {
1213
- const raw = src ? src.raw : '// unreadable during build\nmodule.exports = {};';
1214
- collector.modules.push({ key, code: raw, dir, deps: {} });
1215
- return key;
1266
+ // The transpiled code and the relative specifiers of a module do not depend
1267
+ // on which collector is asking, only on the file — and every `.vsk` compile
1268
+ // builds its own collector, so a docs-style app whose 26 pages all import one
1269
+ // content module read, parsed, stripped and re-transpiled that module 26
1270
+ // times (51s of a 95s build). Cache the result against the file's mtime and
1271
+ // skip the read AND the parse on a hit: callers mutate the AST they get
1272
+ // (`stripTsTypes`, `stripped.body = ...`), so the AST itself stays private to
1273
+ // the call that created it.
1274
+ let mtimeMs = -1;
1275
+ try {
1276
+ mtimeMs = statSync(absPath).mtimeMs;
1277
+ }
1278
+ catch { /* unreadable: fall through to the uncached path */ }
1279
+ const cached = mtimeMs >= 0 ? bundledCodeCache.get(absPath) : undefined;
1280
+ let code;
1281
+ let specifiers;
1282
+ if (cached && cached.mtimeMs === mtimeMs) {
1283
+ code = cached.code;
1284
+ specifiers = cached.specifiers;
1285
+ }
1286
+ else {
1287
+ const src = readSsrSource(absPath);
1288
+ if (!src || !src.ast) {
1289
+ const raw = src ? src.raw : '// unreadable during build\nmodule.exports = {};';
1290
+ collector.modules.push({ key, code: raw, dir, deps: {} });
1291
+ return key;
1292
+ }
1293
+ let stripped = src.ast;
1294
+ if (hasTsSyntax(src.ast))
1295
+ stripped = stripTsTypes(src.ast);
1296
+ stripped.body = (stripped.body || []).filter((n) => (n ? !isTypeOnlyStatement(n) : false));
1297
+ specifiers = [...collectModuleSpecifiers(src.ast)];
1298
+ code = esmToCjs(stripped.body);
1299
+ bundledCodeCache.set(absPath, { mtimeMs, code, specifiers });
1300
+ evict(bundledCodeCache);
1216
1301
  }
1217
- let stripped = src.ast;
1218
- if (hasTsSyntax(src.ast))
1219
- stripped = stripTsTypes(src.ast);
1220
- stripped.body = (stripped.body || []).filter((n) => (n ? !isTypeOnlyStatement(n) : false));
1221
1302
  const deps = {};
1222
- for (const spec of collectModuleSpecifiers(src.ast)) {
1303
+ for (const spec of specifiers) {
1223
1304
  if (!isRelativeSpec(spec))
1224
1305
  continue;
1225
1306
  const depPath = resolveSsrModule(spec, dir);
@@ -1227,9 +1308,10 @@ export function collectModuleBundled(absPath, collector) {
1227
1308
  continue;
1228
1309
  deps[spec] = collectModuleBundled(depPath, collector);
1229
1310
  }
1230
- collector.modules.push({ key, code: esmToCjs(stripped.body), dir, deps });
1311
+ collector.modules.push({ key, code, dir, deps });
1231
1312
  return key;
1232
1313
  }
1314
+ const bundledCodeCache = new Map();
1233
1315
  /**
1234
1316
  * Builds the module bundle + local-binding list for a set of import lines
1235
1317
  * (a `.vsk` file's `imports`). Framework-owned, `.vsk`, `.css` and markdown
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vesk/compiler",
3
- "version": "0.2.46",
3
+ "version": "0.2.47",
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.46",
23
+ "@vesk/types": "^0.2.47",
24
24
  "acorn": "^8.15.0",
25
25
  "esrap": "^2.3.0",
26
26
  "is-reference": "^3.0.0",