@volter/tabnode 0.5.26 → 0.5.28

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/src/runtime.ts CHANGED
@@ -117,6 +117,29 @@ function __substrateGuestConstructor(Constructor: unknown, process: Process): un
117
117
  return __substrateFunctionScope(__substrateGuestGlobal(process), String(compiled));
118
118
  } });
119
119
  }
120
+ /**
121
+ * `vm.runInThisContext` runs its script in the calling process's global scope,
122
+ * as Node's does. The shim evaluated it in the host's, so a script saw the
123
+ * worker's own timers: jiti evaluates every module it loads this way, and
124
+ * pi-mcp-adapter's `setInterval(...).unref()` threw "unref is not a function"
125
+ * because the browser's `setInterval` returns a number. The script runs inside
126
+ * the process's guest global, as a guest `Function` does
127
+ * (`__substrateGuestConstructor`).
128
+ */
129
+ const __substrateScriptScope = Function("__substrateScriptGlobals", "__substrateScriptSource", "with (__substrateScriptGlobals) { return eval(__substrateScriptSource); }");
130
+ const __substrateGuestVms = new WeakMap<Process, unknown>();
131
+ function __substrateGuestVm(process: Process): unknown {
132
+ let vm = __substrateGuestVms.get(process);
133
+ if (vm) return vm;
134
+ const run = (code: string): unknown => __substrateScriptScope(__substrateGuestGlobal(process), String(code));
135
+ class Script extends vmShim.Script {
136
+ override runInThisContext(_options?: object): unknown { return run((this as unknown as { code: string }).code); }
137
+ }
138
+ vm = { ...vmShim, Script, runInThisContext: (code: string, _options?: object) => run(code), default: undefined };
139
+ (vm as { default: unknown }).default = vm;
140
+ __substrateGuestVms.set(process, vm);
141
+ return vm;
142
+ }
120
143
  /**
121
144
  * A `.ts`, `.mts` or `.cts` file runs with its types stripped, as Node runs
122
145
  * one since 22.18, before the module's imports are read -- the entry a `node`
@@ -456,8 +479,12 @@ function __substratePrepareBody(rawCode: string, resolvedPath: string, format: s
456
479
  // A `.cjs` module skips the ESM transform, and with it the rewrite of
457
480
  // `import(...)` to the engine's dynamic import, so its
458
481
  // `import("fs/promises")` reached the browser's own import and failed on
459
- // the bare specifier. The dynamic-import rewrite applies to `.cjs` too.
460
- code = transformDynamicImportsRegex(code);
482
+ // the bare specifier. The dynamic-import rewrite applies to `.cjs` too,
483
+ // from the syntax tree as for every other CommonJS module: the text
484
+ // rewrite also renamed a method called `import`, and jiti's
485
+ // `async import(e,t){...}` became `__dynamicImport`, so `jiti.import` was
486
+ // undefined and every Pi extension failed to load.
487
+ code = __substrateRewriteDynamicImportsInScript(code);
461
488
  }
462
489
 
463
490
  return code;
@@ -726,6 +753,27 @@ async function __substrateImportChain(
726
753
  return doors.__loadFromURL(resolved.url, loaded.format ?? resolved.format, loaded.source ?? void 0);
727
754
  }
728
755
 
756
+ /**
757
+ * A module's `import.meta`: `url`, `dirname`, `filename` and Node's synchronous
758
+ * `resolve` (Node 20.6+). Pi's extension loader resolves its own packages with
759
+ * `import.meta.resolve(specifier)`, and without it every Pi extension failed to
760
+ * load with "import_meta.resolve is not a function". A relative or URL specifier
761
+ * resolves against the module's URL, a builtin to `node:<name>`, and a bare one
762
+ * through the module's own resolver, the one `import()` uses here. Unlike Node,
763
+ * a relative specifier naming a missing file resolves instead of throwing.
764
+ */
765
+ function createImportMeta(moduleRequire: RequireFunction, url: string, dirname: string, filename: string): Record<string, unknown> {
766
+ const resolve = (specifier: unknown, parent?: unknown): string => {
767
+ const id = typeof specifier === 'string' ? specifier : String(specifier);
768
+ const base = parent === undefined ? url : String(parent);
769
+ if (id.startsWith('./') || id.startsWith('../') || id.startsWith('/')) return new URL(id, base).href;
770
+ if (/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(id)) return id.startsWith('node:') ? id : new URL(id).href;
771
+ if (Object.prototype.hasOwnProperty.call(builtinModules, id)) return `node:${id}`;
772
+ return 'file://' + moduleRequire.resolve(id);
773
+ };
774
+ return { url, dirname, filename, resolve };
775
+ }
776
+
729
777
  function createDynamicImport(moduleRequire: RequireFunction, process: Process, parentURL?: string): (specifier: unknown) => Promise<unknown> {
730
778
  return async (specifier: unknown): Promise<unknown> => {
731
779
  try {
@@ -1962,7 +2010,7 @@ function createRequire(
1962
2010
  dirname,
1963
2011
  process,
1964
2012
  consoleWrapper,
1965
- { url: importMetaUrl, dirname, filename: resolvedPath },
2013
+ createImportMeta(moduleRequire, importMetaUrl, dirname, resolvedPath),
1966
2014
  dynamicImport,
1967
2015
  __substrateGuestGlobal,
1968
2016
  __substrateGuestConstructor
@@ -2130,6 +2178,11 @@ function createRequire(
2130
2178
  if (id === 'module') {
2131
2179
  return __substrateModule();
2132
2180
  }
2181
+ // Ahead of the per-process builtin table: node-lib's own modules require
2182
+ // `vm` first and that table keeps the first answer for the process.
2183
+ if (id === 'vm') {
2184
+ return __substrateGuestVm(process);
2185
+ }
2133
2186
  if (id === 'wasi') {
2134
2187
  return __substrateGuestWasi(fsShim, process);
2135
2188
  }
@@ -2445,8 +2498,12 @@ export class Runtime {
2445
2498
  // A `.cjs` module skips the ESM transform, and with it the rewrite of
2446
2499
  // `import(...)` to the engine's dynamic import, so its
2447
2500
  // `import("fs/promises")` reached the browser's own import and failed on
2448
- // the bare specifier. The dynamic-import rewrite applies to `.cjs` too.
2449
- code = transformDynamicImportsRegex(code);
2501
+ // the bare specifier. The dynamic-import rewrite applies to `.cjs` too,
2502
+ // from the syntax tree as for every other CommonJS module: the text
2503
+ // rewrite also renamed a method called `import`, and jiti's
2504
+ // `async import(e,t){...}` became `__dynamicImport`, so `jiti.import` was
2505
+ // undefined and every Pi extension failed to load.
2506
+ code = __substrateRewriteDynamicImportsInScript(code);
2450
2507
  }
2451
2508
 
2452
2509
  // Execute code
@@ -2492,7 +2549,7 @@ export class Runtime {
2492
2549
  dirname,
2493
2550
  this.process,
2494
2551
  consoleWrapper,
2495
- { url: importMetaUrl, dirname, filename },
2552
+ createImportMeta(require, importMetaUrl, dirname, filename),
2496
2553
  dynamicImport,
2497
2554
  __substrateGuestGlobal,
2498
2555
  __substrateGuestConstructor