@nubjs/nub-linux-x64 0.2.1 → 0.2.3
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/bin/nub +0 -0
- package/bin/nubx +0 -0
- package/package.json +1 -1
- package/runtime/addons/nub-native.node +0 -0
- package/runtime/navigator-locks.mjs +188 -81
- package/runtime/navigator-shim.mjs +144 -0
- package/runtime/polyfills.cjs +624 -18
- package/runtime/preload-async-hooks.mjs +16 -3
- package/runtime/preload-common.cjs +49 -0
- package/runtime/preload.cjs +15 -0
- package/runtime/preload.mjs +8 -0
- package/runtime/transform-core.mjs +86 -14
- package/runtime/version.mjs +1 -1
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
// loader worker, not a user realm, so it installs no browser globals.)
|
|
29
29
|
import "./floor-builtin.mjs";
|
|
30
30
|
import {
|
|
31
|
-
TRANSPILE_EXTS, DATA_EXTS,
|
|
32
|
-
extname, resolveSpec, loadTranspile, loadData,
|
|
31
|
+
TRANSPILE_EXTS, PLAIN_JS_EXTS, DATA_EXTS,
|
|
32
|
+
extname, resolveSpec, loadTranspile, maybeTranspilePlainJs, loadData, isNodeModules,
|
|
33
33
|
} from "./transform-core.mjs";
|
|
34
34
|
import { createRequire, isBuiltin } from "node:module";
|
|
35
35
|
import { existsSync } from "node:fs";
|
|
@@ -85,13 +85,26 @@ export async function resolve(specifier, context, nextResolve) {
|
|
|
85
85
|
// ── Load hook ───────────────────────────────────────────────────────
|
|
86
86
|
export async function load(url, context, nextLoad) {
|
|
87
87
|
const ext = extname(url);
|
|
88
|
-
|
|
88
|
+
// node_modules deps are NEVER transpiled (the byte-parity boundary). This guard is
|
|
89
|
+
// make-or-break now that TRANSPILE_EXTS includes `.js`/`.mjs`/`.cjs`: without it,
|
|
90
|
+
// the compat tier would route every dependency `.js` through oxc. (loadTranspile's
|
|
91
|
+
// own skip-gate handles the project-source no-op case; this keeps deps off the
|
|
92
|
+
// pipeline entirely.) Mirrors the fast-tier sync hook's `!isNodeModules` gate.
|
|
93
|
+
if (TRANSPILE_EXTS.has(ext) && !isNodeModules(url)) {
|
|
89
94
|
// Module-format + decorator detection inside loadTranspile is a synchronous
|
|
90
95
|
// native call (nub's addon), available on every supported Node — no parser
|
|
91
96
|
// warm-up needed (the old `await ensureParser()` for the ESM-only oxc-parser
|
|
92
97
|
// is gone with the package).
|
|
93
98
|
return loadTranspile(url, ext);
|
|
94
99
|
}
|
|
100
|
+
// Project-source plain JS: transpile ONLY when it carries transformable syntax. A
|
|
101
|
+
// no-op plain-JS file returns null and falls through to `nextLoad` — Node's own
|
|
102
|
+
// loader handles it byte-identically, preserving every native CJS/ESM behavior.
|
|
103
|
+
// node_modules excluded (the byte-parity boundary).
|
|
104
|
+
if (PLAIN_JS_EXTS.has(ext) && !isNodeModules(url)) {
|
|
105
|
+
const r = maybeTranspilePlainJs(url, ext);
|
|
106
|
+
if (r) return r;
|
|
107
|
+
}
|
|
95
108
|
if (ext in DATA_EXTS) return loadData(url, ext);
|
|
96
109
|
return nextLoad(url, context);
|
|
97
110
|
}
|
|
@@ -373,6 +373,13 @@ function makeHooks(core, watchReporting) {
|
|
|
373
373
|
if (core.TRANSPILE_EXTS.has(ext) && !core.isNodeModules(url)) {
|
|
374
374
|
return core.loadTranspile(url, ext);
|
|
375
375
|
}
|
|
376
|
+
// Plain JS: transpile only when transformable; else fall through to the raw-
|
|
377
|
+
// source path below (which hands CJS back as `source:null` → Node's native
|
|
378
|
+
// CJS loader), byte-identical to a non-intercepted file.
|
|
379
|
+
if (core.PLAIN_JS_EXTS.has(ext) && !core.isNodeModules(url)) {
|
|
380
|
+
const r = core.maybeTranspilePlainJs(url, ext);
|
|
381
|
+
if (r) return r;
|
|
382
|
+
}
|
|
376
383
|
if (ext in core.DATA_EXTS) return core.loadData(url, ext);
|
|
377
384
|
const { readFileSync } = require("node:fs");
|
|
378
385
|
const source = readFileSync(path);
|
|
@@ -432,6 +439,15 @@ function makeHooks(core, watchReporting) {
|
|
|
432
439
|
if (core.TRANSPILE_EXTS.has(ext) && !core.isNodeModules(url)) {
|
|
433
440
|
return core.loadTranspile(url, ext);
|
|
434
441
|
}
|
|
442
|
+
// Project-source plain JS (`.js`/`.mjs`/`.cjs`): transpile ONLY when it carries
|
|
443
|
+
// transformable syntax. A no-op plain-JS file returns null here and falls through
|
|
444
|
+
// to Node's native loader (the `nextLoad`/relabel path below) BYTE-FOR-BYTE — it
|
|
445
|
+
// is never intercepted, so native CJS/ESM behavior (the relabel, require.cache,
|
|
446
|
+
// the require-of-ESM-syntax-`.cjs` error) is preserved. node_modules excluded.
|
|
447
|
+
if (core.PLAIN_JS_EXTS.has(ext) && !core.isNodeModules(url)) {
|
|
448
|
+
const r = core.maybeTranspilePlainJs(url, ext);
|
|
449
|
+
if (r) return r;
|
|
450
|
+
}
|
|
435
451
|
if (ext in core.DATA_EXTS) return core.loadData(url, ext);
|
|
436
452
|
|
|
437
453
|
// Fidelity: a `data:` URL whose MIME maps to no module format (e.g.
|
|
@@ -673,6 +689,39 @@ function installCjsRequireHooks(core, withClassicTranspile) {
|
|
|
673
689
|
for (const ext of [".ts", ".cts", ".mts", ".tsx", ".jsx"]) {
|
|
674
690
|
module_._extensions[ext] = transpileExtension;
|
|
675
691
|
}
|
|
692
|
+
|
|
693
|
+
// Project-source plain JS (`.js`/`.cjs`) routes through the SAME pipeline so
|
|
694
|
+
// `using`/`v`-flag-RegExp/decorators lower uniformly on the classic require tier —
|
|
695
|
+
// but ONLY when the file carries transformable syntax. THREE cases, each preserving
|
|
696
|
+
// Node's native behavior where it must:
|
|
697
|
+
// (1) node_modules dep → native handler (deps are NEVER transpiled). Node has no
|
|
698
|
+
// own `_extensions['.cjs']` (only `.js`/`.json`/`.node`), and compiles `.cjs`
|
|
699
|
+
// through the same CJS path as `.js`, so the `.cjs` bail falls back to the
|
|
700
|
+
// `.js` handler (`|| nativeJs`) — without it a node_modules `.cjs` require
|
|
701
|
+
// would call `undefined` and crash.
|
|
702
|
+
// (2) project file with transformable syntax → transpile (lower it).
|
|
703
|
+
// (3) project file with NOTHING to lower → the ORIGINAL native handler, raw bytes
|
|
704
|
+
// compiled exactly as Node would. We never serve our own source for a no-op
|
|
705
|
+
// file, so require.cache / the require-of-ESM-syntax-`.cjs` SyntaxError / every
|
|
706
|
+
// native CJS behavior is byte-identical.
|
|
707
|
+
// `.mjs` is ESM-only; Node registers no require.extensions handler for it, so a
|
|
708
|
+
// `require()` of `.mjs` throws ERR_REQUIRE_ESM as before — we don't override it.
|
|
709
|
+
const nativeJs = module_._extensions[".js"];
|
|
710
|
+
for (const ext of [".js", ".cjs"]) {
|
|
711
|
+
const origExtension = module_._extensions[ext] || nativeJs;
|
|
712
|
+
module_._extensions[ext] = (mod, filename) => {
|
|
713
|
+
if (core.isNodeModules(pathToFileURL(filename).href)) {
|
|
714
|
+
return origExtension.call(module_._extensions, mod, filename); // (1)
|
|
715
|
+
}
|
|
716
|
+
const r = core.maybeTranspilePlainJs(pathToFileURL(filename).href, pathExtname(filename));
|
|
717
|
+
if (r) {
|
|
718
|
+
if (r.format === "module") throw requireEsmError(filename); // (2)
|
|
719
|
+
mod._compile(r.source, filename);
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
return origExtension.call(module_._extensions, mod, filename); // (3)
|
|
723
|
+
};
|
|
724
|
+
}
|
|
676
725
|
}
|
|
677
726
|
|
|
678
727
|
// ── Clobbered-polyfill preloading + Temporal lazy global ────────────
|
package/runtime/preload.cjs
CHANGED
|
@@ -209,6 +209,21 @@ function installLazyEsmPolyfills() {
|
|
|
209
209
|
}
|
|
210
210
|
};
|
|
211
211
|
|
|
212
|
+
// navigator backfill, ordered BEFORE the navigator.locks installs below so locks
|
|
213
|
+
// always has a host. The fast tier floor is 22.15 (navigator is always native, >= 21),
|
|
214
|
+
// so installNavigatorShim() version-checks and returns WITHOUT reading globalThis
|
|
215
|
+
// .navigator — never triggering the 24.5+ lazy-navigator realization. It does real
|
|
216
|
+
// work only if this preload is ever reached on Node < 21; on the fast floor it is a
|
|
217
|
+
// cheap no-op, wired for symmetry with the compat tier. See navigator-shim.mjs.
|
|
218
|
+
try {
|
|
219
|
+
__require("./navigator-shim.mjs").installNavigatorShim();
|
|
220
|
+
} catch (err) {
|
|
221
|
+
// require(esm) disabled (--no-experimental-require-module): navigator is native at
|
|
222
|
+
// the fast floor, so skipping the no-op shim is harmless. Any OTHER error is a real
|
|
223
|
+
// fault in the module — surface it rather than swallow it.
|
|
224
|
+
if (!err || err.code !== "ERR_REQUIRE_ESM") throw err;
|
|
225
|
+
}
|
|
226
|
+
|
|
212
227
|
if (inWorkerThread) {
|
|
213
228
|
// Worker-side scope bootstrap must be present synchronously where possible.
|
|
214
229
|
loadEsmSideEffect("./worker-polyfill.mjs");
|
package/runtime/preload.mjs
CHANGED
|
@@ -112,6 +112,14 @@ if (__isFastTier) {
|
|
|
112
112
|
// modules is unreliable, so they load via dynamic `import()` here.
|
|
113
113
|
const __preloadedPolyfills = common.preloadPolyfillPackages(__require);
|
|
114
114
|
installSyncPolyfills(__preloadedPolyfills);
|
|
115
|
+
// navigator backfill (Node < 21: the `navigator` global is wholly absent). MUST run
|
|
116
|
+
// BEFORE navigator-locks so Web Locks has a host on the 18.19–20.x floor. On Node >= 21
|
|
117
|
+
// it is a no-op (navigator is native). Thread the floor's createRequire so the shim can
|
|
118
|
+
// fetch node:os where process.getBuiltinModule is absent (the narrow floor). See
|
|
119
|
+
// navigator-shim.mjs.
|
|
120
|
+
const __navShim = await import("./navigator-shim.mjs");
|
|
121
|
+
__navShim.setBootstrapCreateRequire(floorCreateRequire);
|
|
122
|
+
__navShim.installNavigatorShim();
|
|
115
123
|
if (typeof globalThis.navigator?.locks === "undefined") {
|
|
116
124
|
await import("./navigator-locks.mjs");
|
|
117
125
|
}
|
|
@@ -156,7 +156,21 @@ if (typeof process.getBuiltinModule === "function") __ensureBuiltins();
|
|
|
156
156
|
// natively now, and this file no longer needs to read version.mjs.
|
|
157
157
|
|
|
158
158
|
// ── Constants ───────────────────────────────────────────────────────
|
|
159
|
+
// TS/JSX exts ALWAYS transform (type-stripping is required), so they live in
|
|
160
|
+
// TRANSPILE_EXTS — the set every dispatch site checks to route a file to
|
|
161
|
+
// loadTranspile. Plain JS (.js/.mjs/.cjs) is DELIBERATELY NOT here: a plain-JS file
|
|
162
|
+
// is transpiled ONLY when it carries transformable syntax (`using`/`await using`,
|
|
163
|
+
// `v`-flag RegExp, decorators), and a no-op plain-JS file must take Node's OWN load
|
|
164
|
+
// path BYTE-FOR-BYTE — putting it in TRANSPILE_EXTS would route every `.js`/`.cjs`
|
|
165
|
+
// through nub's hook and change native CJS/ESM behavior (the `commonjs-sync` relabel,
|
|
166
|
+
// require.cache, the require-of-ESM-syntax-.cjs error). So plain JS is handled by a
|
|
167
|
+
// SEPARATE narrow path (`maybeTranspilePlainJs`) that fires only for transformable
|
|
168
|
+
// files and is a no-op (returns null) otherwise — see PLAIN_JS_EXTS below.
|
|
159
169
|
export const TRANSPILE_EXTS = new Set([".ts", ".tsx", ".mts", ".cts", ".jsx"]);
|
|
170
|
+
// Project-source plain JS. Routed to the transpiler ONLY when transformable (the
|
|
171
|
+
// `maybeTranspilePlainJs` gate); a no-op plain-JS file falls through to Node's
|
|
172
|
+
// native loader untouched, byte-identical. node_modules is excluded at the gate.
|
|
173
|
+
export const PLAIN_JS_EXTS = new Set([".js", ".mjs", ".cjs"]);
|
|
160
174
|
export const DATA_EXTS = { ".jsonc": "jsonc", ".json5": "json5", ".toml": "toml", ".yaml": "yaml", ".yml": "yaml", ".txt": "txt" };
|
|
161
175
|
export const TS_PARENT_EXTS = new Set([".ts", ".tsx", ".mts", ".cts"]);
|
|
162
176
|
|
|
@@ -328,7 +342,7 @@ export function resolveSpec(specifier, parentURL) {
|
|
|
328
342
|
// from a nub-dependency ESM entry) delegated to a strict user loader is exactly
|
|
329
343
|
// the R11 leak. See isNubInternalParent.
|
|
330
344
|
if (isNubInternalParent(parentURL)) {
|
|
331
|
-
if (specifier.startsWith("node:") || module.
|
|
345
|
+
if (specifier.startsWith("node:") || module.isBuiltin(specifier)) {
|
|
332
346
|
const url = specifier.startsWith("node:") ? specifier : `node:${specifier}`;
|
|
333
347
|
return { url, shortCircuit: true };
|
|
334
348
|
}
|
|
@@ -349,7 +363,7 @@ export function resolveSpec(specifier, parentURL) {
|
|
|
349
363
|
|
|
350
364
|
// node: and data: protocols, and bare Node built-ins, are never ours.
|
|
351
365
|
if (specifier.startsWith("node:") || specifier.startsWith("data:")) return null;
|
|
352
|
-
if (module.
|
|
366
|
+
if (module.isBuiltin(specifier)) return null;
|
|
353
367
|
|
|
354
368
|
// 1. Built-in modules provided by Nub.
|
|
355
369
|
if (BUILTIN_MODULES.has(specifier)) {
|
|
@@ -392,7 +406,7 @@ export function resolveSpec(specifier, parentURL) {
|
|
|
392
406
|
// file's absolute path (from the CJS parent Module), or null for the entry.
|
|
393
407
|
export function resolveCjsPath(request, parentPath) {
|
|
394
408
|
if (request.startsWith("node:") || request.startsWith("data:") ||
|
|
395
|
-
module.
|
|
409
|
+
module.isBuiltin(request)) {
|
|
396
410
|
return null;
|
|
397
411
|
}
|
|
398
412
|
// The SAME native additive resolver as resolveSpec, returning an absolute path
|
|
@@ -435,13 +449,15 @@ function detectModuleInfo(filePath, source, lang) {
|
|
|
435
449
|
// Addon missing (should never happen in a real install): default to ESM for
|
|
436
450
|
// format (the common case) and "no decorators" for the guard — the same fallback
|
|
437
451
|
// the old oxc-parser-unavailable branches used.
|
|
438
|
-
if (!nubNative) return { hasValueEsmSyntax: true, hasDecorators: false };
|
|
452
|
+
if (!nubNative) return { hasValueEsmSyntax: true, hasDecorators: false, transformableSyntax: false };
|
|
439
453
|
try {
|
|
440
454
|
return nubNative.detectModuleInfo(filePath, source, lang);
|
|
441
455
|
} catch {
|
|
442
456
|
// Unparseable → CJS for format + no decorators (the transpile/V8 surfaces the
|
|
443
|
-
// real error), matching the old per-call catch blocks.
|
|
444
|
-
|
|
457
|
+
// real error), matching the old per-call catch blocks. `transformableSyntax:
|
|
458
|
+
// false` is the SAFE plain-JS default — the verbatim path hands the raw bytes
|
|
459
|
+
// back, so V8 surfaces the real syntax error exactly where Node would.
|
|
460
|
+
return { hasValueEsmSyntax: false, hasDecorators: false, transformableSyntax: false };
|
|
445
461
|
}
|
|
446
462
|
}
|
|
447
463
|
|
|
@@ -450,13 +466,28 @@ function detectModuleInfo(filePath, source, lang) {
|
|
|
450
466
|
// `type` is authoritative; otherwise (ambiguous) we detect from source syntax —
|
|
451
467
|
// full Node parity (`--experimental-detect-module`), so a CJS-syntax `.ts` with
|
|
452
468
|
// no `type` runs as CJS on nub exactly as on Node. See wiki/runtime/module-format.md.
|
|
469
|
+
// `.mjs`→module / `.cjs`→commonjs are explicit (mirroring `.mts`/`.cts`), so the
|
|
470
|
+
// plain-JS gate gets the right format without a needless detect.
|
|
453
471
|
export function moduleFormatFor(ext, pkgType, filePath, source) {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
472
|
+
return moduleFormatWithInfo(ext, pkgType, filePath, source).format;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Same format decision as moduleFormatFor, but ALSO returns the `ModuleInfo`
|
|
476
|
+
// (`detectModuleInfo`) result when a parse was needed — `{ format, info }`, with
|
|
477
|
+
// `info` null on the no-parse short-circuits (`.mts`/`.mjs`/`.cts`/`.cjs`, explicit
|
|
478
|
+
// `type`). loadTranspile uses this so its ONE parse serves BOTH readers — the
|
|
479
|
+
// format decision (`hasValueEsmSyntax`) and the Stage-3 decorator guard
|
|
480
|
+
// (`hasDecorators`) — instead of `moduleFormatFor` + `hasDecoratorSyntax` each
|
|
481
|
+
// parsing the same source. On a short-circuit (`info` null) no parse happened, so
|
|
482
|
+
// the decorator guard runs its own single parse: still ≤1 detect per file.
|
|
483
|
+
function moduleFormatWithInfo(ext, pkgType, filePath, source) {
|
|
484
|
+
if (ext === ".mts" || ext === ".mjs") return { format: "module", info: null };
|
|
485
|
+
if (ext === ".cts" || ext === ".cjs") return { format: "commonjs", info: null };
|
|
486
|
+
if (pkgType === "module") return { format: "module", info: null };
|
|
487
|
+
if (pkgType === "commonjs") return { format: "commonjs", info: null };
|
|
458
488
|
const lang = ext === ".tsx" ? "tsx" : ext === ".jsx" ? "jsx" : "ts";
|
|
459
|
-
|
|
489
|
+
const info = detectModuleInfo(filePath, source, lang);
|
|
490
|
+
return { format: info.hasValueEsmSyntax ? "module" : "commonjs", info };
|
|
460
491
|
}
|
|
461
492
|
|
|
462
493
|
// The Stage-3-decorator rejection diagnostic. oxc does not lower TC39 Stage 3
|
|
@@ -568,9 +599,13 @@ export function loadTranspile(url, ext) {
|
|
|
568
599
|
// (.ts/.tsx/.jsx); .mts/.cts are explicit so its lookup is skipped. The chosen
|
|
569
600
|
// format is folded into the cache key (and the entry's leading byte) by native.
|
|
570
601
|
const pkgType = ext === ".mts" || ext === ".cts" ? undefined : getPackageType(dir);
|
|
571
|
-
|
|
602
|
+
// ONE detectModuleInfo parse for both the format decision and the decorator
|
|
603
|
+
// guard below: `moduleInfo` is the parsed ModuleInfo when the format needed a
|
|
604
|
+
// parse (ambiguous ext, no explicit `type`), else null (a no-parse short-circuit).
|
|
605
|
+
const { format, info: moduleInfo } = moduleFormatWithInfo(ext, pkgType, filePath, source);
|
|
572
606
|
|
|
573
607
|
const lang = ext === ".tsx" ? "tsx" : ext === ".jsx" ? "jsx" : "ts";
|
|
608
|
+
|
|
574
609
|
const opts = {
|
|
575
610
|
lang,
|
|
576
611
|
sourceType: format === "commonjs" ? "commonjs" : "module",
|
|
@@ -604,9 +639,12 @@ export function loadTranspile(url, ext) {
|
|
|
604
639
|
// SyntaxError. When legacy mode is off and decorator syntax is present, reject
|
|
605
640
|
// with the documented Option-A diagnostic instead. (Cheap `source.includes("@")`
|
|
606
641
|
// pre-filter keeps decorator-free files off the native parser; runs BEFORE the
|
|
607
|
-
// cache so the diagnostic surfaces even on what would be a warm hit.)
|
|
642
|
+
// cache so the diagnostic surfaces even on what would be a warm hit.) Reuse the
|
|
643
|
+
// `hasDecorators` flag from the format parse above when it ran (`moduleInfo`
|
|
644
|
+
// non-null), so the ambiguous-ext + `@` path detects ONCE; on a no-parse
|
|
645
|
+
// short-circuit (`.mts`/`.cts`/explicit `type`) it does its own single parse.
|
|
608
646
|
if (co?.experimentalDecorators !== true && source.includes("@") &&
|
|
609
|
-
hasDecoratorSyntax(filePath, source, lang)) {
|
|
647
|
+
(moduleInfo ? moduleInfo.hasDecorators : hasDecoratorSyntax(filePath, source, lang))) {
|
|
610
648
|
throw stage3DecoratorError(filePath);
|
|
611
649
|
}
|
|
612
650
|
|
|
@@ -626,6 +664,40 @@ export function loadTranspile(url, ext) {
|
|
|
626
664
|
return { format: result.format, source: result.code, shortCircuit: true };
|
|
627
665
|
}
|
|
628
666
|
|
|
667
|
+
// Project-source plain JS (`.js`/`.mjs`/`.cjs`) gate. Returns a transpiled load
|
|
668
|
+
// result ONLY when the file carries syntax oxc lowers at nub's es2022 target
|
|
669
|
+
// (`using`/`await using`, a `v`-flag RegExp, or decorators); otherwise returns
|
|
670
|
+
// `null`, meaning "this file needs no transform — handle it with Node's OWN loader,
|
|
671
|
+
// exactly as a non-listed extension." This is why `.js`/`.mjs`/`.cjs` are NOT in
|
|
672
|
+
// TRANSPILE_EXTS: a no-op plain-JS file must take Node's native load path
|
|
673
|
+
// byte-for-byte (preserving the `commonjs-sync` relabel, require.cache, the
|
|
674
|
+
// require-of-ESM-syntax-`.cjs` error — all of which intercepting the file would
|
|
675
|
+
// break), and oxc would reformat it (quotes/semicolons/whitespace + a sourcemap
|
|
676
|
+
// footer) if we ran it through anyway. The verdict rides ONE parse (the same one
|
|
677
|
+
// `detectModuleInfo` does for format detection). node_modules is gated at the call
|
|
678
|
+
// sites (the byte-parity boundary). JSX-in-`.js` is out of scope (lang is "ts",
|
|
679
|
+
// which does not parse JSX); use `.jsx`.
|
|
680
|
+
export function maybeTranspilePlainJs(url, ext) {
|
|
681
|
+
__ensureBuiltins();
|
|
682
|
+
const filePath = fileURLToPath(url);
|
|
683
|
+
let source;
|
|
684
|
+
try {
|
|
685
|
+
source = readFileSync(filePath, "utf8");
|
|
686
|
+
} catch {
|
|
687
|
+
// Unreadable here → let Node's loader surface its own error.
|
|
688
|
+
return null;
|
|
689
|
+
}
|
|
690
|
+
// lang "ts" parses all JS (a TS superset) but NOT JSX — JSX-in-.js is out of scope.
|
|
691
|
+
const info = detectModuleInfo(filePath, source, "ts");
|
|
692
|
+
if (!info.transformableSyntax && !info.hasDecorators) {
|
|
693
|
+
return null; // no-op: Node's native loader handles it, byte-identical.
|
|
694
|
+
}
|
|
695
|
+
// Transformable: run the SAME pipeline as TS/JSX (target es2022 lowering, tsconfig,
|
|
696
|
+
// source maps, the Stage-3 decorator guard, format detection, cache). loadTranspile
|
|
697
|
+
// re-reads + re-parses, but only for the rare file that actually needs lowering.
|
|
698
|
+
return loadTranspile(url, ext);
|
|
699
|
+
}
|
|
700
|
+
|
|
629
701
|
// ── Data-format imports ─────────────────────────────────────────────
|
|
630
702
|
function lazyRequire(pkg) {
|
|
631
703
|
try { return __require(pkg); } catch {
|
package/runtime/version.mjs
CHANGED
|
@@ -9,4 +9,4 @@
|
|
|
9
9
|
// previously lived as a literal inside preload.mjs, which `make version` patched,
|
|
10
10
|
// while the worker carried a hand-maintained "…-compat" copy that `make version`
|
|
11
11
|
// never touched — a latent staleness bug this module closes.)
|
|
12
|
-
export const NUB_VERSION = "0.2.
|
|
12
|
+
export const NUB_VERSION = "0.2.3";
|