@nubjs/nub-linux-x64 0.0.12 → 0.0.14

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.
@@ -0,0 +1,273 @@
1
+ // Nub fast-tier preload — Node 22.15+, injected via `--require` (CommonJS).
2
+ //
3
+ // WHY CJS / `--require` (not the `.mjs` `--import` the compat tier uses): the mere
4
+ // presence of `--import` forces Node to eagerly initialize the ESM loader, which
5
+ // then routes EVEN A CJS ENTRY POINT through the async ESM module-job
6
+ // (`ModuleJob.run`) instead of the synchronous `Module.runMain` CJS path. That one
7
+ // change is the root cause of a whole regression cluster (R1): top-level
8
+ // `executionAsyncId()===0` (Node: 1), extra PROMISE async-hook events, a top-level
9
+ // sync `throw` surfacing as `unhandledRejection` instead of `uncaughtException`,
10
+ // `require.main.id` `'.'`→abspath, `module.parent` `null`→`undefined`, and a
11
+ // missing-entry `ERR_MODULE_NOT_FOUND` instead of `MODULE_NOT_FOUND`. Loading this
12
+ // preload via `--require` (CJS) keeps Node on the synchronous CJS entry path and
13
+ // restores all of them, while STILL supporting `module.registerHooks` + TS
14
+ // transpile (both work from a `--require` CJS module on Node 22.15+).
15
+ //
16
+ // HARD CONSTRAINT: this file and everything it pulls in synchronously must be
17
+ // TLA-free. `require(esm)` (which loads transform-core.mjs / the polyfill ESM
18
+ // modules) rejects any module with top-level await (ERR_REQUIRE_ASYNC_MODULE), so
19
+ // transform-core.mjs, polyfills.cjs, worker-polyfill.mjs and navigator-locks.mjs
20
+ // are all TLA-free by construction. The compat tier (< 22.15), where require(esm)
21
+ // is unreliable, keeps its async `--import` preload.mjs path UNCHANGED.
22
+ //
23
+ // ROBUSTNESS TO `--no-experimental-require-module` (the require-module cluster):
24
+ // a user may set `--no-experimental-require-module` (e.g. to assert the legacy
25
+ // require(esm)→ERR_REQUIRE_ESM contract for THEIR code). That flag globally
26
+ // disables require(esm) — including for THIS `--require` CJS preload's own
27
+ // `require("./transform-core.mjs")`, which would otherwise crash the process at
28
+ // startup (ERR_REQUIRE_ESM) before any user code runs. nub's preload must survive
29
+ // that. The fix: detect when sync require(esm) is unavailable and fall back to the
30
+ // compat tier's async loader-worker hooks (`module.register("./preload-async-
31
+ // hooks.mjs")`), which loads transform-core.mjs as a STATIC ESM import inside the
32
+ // worker — a path the flag does not gate. User code still gets Node's own
33
+ // ERR_REQUIRE_ESM for ITS require(esm), exactly as the flag promises; only nub's
34
+ // preload is made robust. (See the require-module corpus cluster:
35
+ // test-cjs-esm-warn, test-disable-require-module-with-detection,
36
+ // test-esm-type-field-errors-2, parallel/test-require-mjs.)
37
+
38
+ const { createRequire } = require("node:module");
39
+ const module_ = require("node:module");
40
+
41
+ const __require = createRequire(__filename);
42
+
43
+ // Load preload-common FIRST so we can restore NODE_COMPILE_CACHE (R8) BEFORE
44
+ // transform-core.mjs is required: spawn.rs stripped that env var to keep nub's
45
+ // preload chain out of the user's V8 compile cache, and transform-core reads
46
+ // `NODE_COMPILE_CACHE === "0"` as its transpile-cache disable signal — so the
47
+ // value must be back in process.env before transform-core's module body runs.
48
+ // Restoring it in JS does NOT re-enable Node's bootstrap compile cache (already
49
+ // configured from the stripped env), so the chain below stays uncached.
50
+ const common = __require("./preload-common.cjs");
51
+ common.restoreCompileCacheEnv();
52
+
53
+ // `--no-experimental-require-module` disables require(esm) globally, so the
54
+ // transform-core require below (and the worker/locks ESM side-effect modules)
55
+ // would throw ERR_REQUIRE_ESM and abort the process before user code. Detect that
56
+ // and load via the async-register fallback instead. We probe by attempting the
57
+ // require and catching ERR_REQUIRE_ESM — robust regardless of how the flag arrived
58
+ // (CLI, NODE_OPTIONS, or a config file), and a no-op cost on the common path where
59
+ // require(esm) works.
60
+ let core = null;
61
+ let requireEsmDisabled = false;
62
+ try {
63
+ // The transform core is the single source of truth for resolution + transpile,
64
+ // shared verbatim with the compat tier. It's an ES module with no top-level
65
+ // await, so `require(esm)` loads it synchronously here on Node 22.15+.
66
+ core = __require("./transform-core.mjs");
67
+ } catch (err) {
68
+ if (err && err.code === "ERR_REQUIRE_ESM") {
69
+ requireEsmDisabled = true;
70
+ } else {
71
+ throw err;
72
+ }
73
+ }
74
+
75
+ const { installSyncPolyfills } = __require("./polyfills.cjs");
76
+
77
+ if (!requireEsmDisabled) {
78
+ // ── Fast tier (sync require(esm) available) ───────────────────────
79
+
80
+ // ── Watch-mode dependency reporting + hooks ───────────────────────
81
+ const watchReporting = common.installWatchReporting(core);
82
+
83
+ // Best-effort bounded-cache eviction (main thread only; the core guards on it).
84
+ // DEFERRED to setImmediate: maybeSweepCache probes `worker_threads.isMainThread`
85
+ // and dynamic-imports cache-evict.mjs, which would otherwise pull worker_threads
86
+ // (and its streams/worker-io transitive set) into the BOOTSTRAP module-load list
87
+ // on every startup — a cold-start regression (test-bootstrap-modules snapshots
88
+ // process.moduleLoadList at user code's first line). Running it one turn later
89
+ // keeps those out of the bootstrap snapshot while preserving the once-a-day sweep.
90
+ // unref so a purely-synchronous program still exits promptly without waiting on it.
91
+ setImmediate(() => {
92
+ try { core.maybeSweepCache(); } catch {}
93
+ }).unref();
94
+
95
+ // ── Pre-load clobbered polyfill packages BEFORE hooks register ────
96
+ // Packages in the core's CLOBBER_MAP can't be imported after hooks register (the
97
+ // resolve hook returns a synthetic module instead of the real package), so
98
+ // require them now via the not-yet-hooked CJS require and stash them for the
99
+ // polyfill installer. Temporal is deferred entirely to a lazy global (below).
100
+ const __preloadedPolyfills = common.preloadPolyfillPackages(__require);
101
+
102
+ // ── Hook registration (fast tier: sync, in-thread) ────────────────
103
+ // Same realm as user code; covers `import` and (Node 24+) `require`.
104
+ // registerHooks' require RESOLUTION is incomplete on 22.15–24, so also install
105
+ // the main-thread CJS resolve shim. Install the classic require.extensions
106
+ // transpile shim only on 22.15–22.17 (no native `.ts`); on 22.18+/24+ skip it so
107
+ // Node's native require() of `.ts` — incl. ES modules — isn't shadowed (see
108
+ // installCjsRequireHooks).
109
+ const __hasNativeTs = !!process.features?.typescript;
110
+ const { resolve, load } = common.makeHooks(core, watchReporting);
111
+ module_.registerHooks({ resolve, load });
112
+ common.installCjsRequireHooks(core, !__hasNativeTs);
113
+
114
+ // ── Sync polyfills + lazy ESM-side-effect polyfills ───────────────
115
+ installSyncPolyfills(__preloadedPolyfills);
116
+ installLazyEsmPolyfills();
117
+
118
+ // ── Temporal: lazy global (A37) ───────────────────────────────────
119
+ common.installTemporalLazyGlobal(__require);
120
+
121
+ // ── Compile-cache: re-enable for the USER's modules (R8) ──────────
122
+ common.reenableUserCompileCache();
123
+ } else {
124
+ // ── Fallback tier (`--no-experimental-require-module`): async hooks ─
125
+ // The user disabled require(esm), so the in-thread sync `module.registerHooks`
126
+ // core can't be loaded here. Register the SAME hooks the compat tier uses, run
127
+ // in a dedicated loader worker via `module.register`; that worker imports
128
+ // transform-core.mjs as a static ESM import (not gated by the flag). The
129
+ // main-thread CJS require() transpile shim, which would need the core
130
+ // synchronously in-thread, is unavailable in this mode — an honest, additive
131
+ // degradation: the user opted out of require(esm), and nub's `.ts`-via-require()
132
+ // transpile rides on exactly that mechanism. `import`-side TS still transpiles
133
+ // through the registered loader-worker hooks. User require(esm) of THEIR own ES
134
+ // modules still gets Node's native ERR_REQUIRE_ESM, exactly as the flag promises.
135
+ const { pathToFileURL } = require("node:url");
136
+ module_.register("./preload-async-hooks.mjs", pathToFileURL(__filename).href);
137
+
138
+ // Sync, non-require(esm) polyfills still install (none of them require(esm)).
139
+ // Clobbered-polyfill packages are CJS requires, unaffected by the flag.
140
+ const __preloadedPolyfills = common.preloadPolyfillPackages(__require);
141
+ installSyncPolyfills(__preloadedPolyfills);
142
+ installLazyEsmPolyfills();
143
+
144
+ // Temporal lazy global needs only `__require` (it loads a CJS package), and the
145
+ // user's compile-cache re-enable is independent of require(esm).
146
+ common.installTemporalLazyGlobal(__require);
147
+ common.reenableUserCompileCache();
148
+ }
149
+
150
+ // ── Lazy ESM-side-effect polyfills (R7) ─────────────────────────────
151
+ // The two ESM side-effect polyfills — the browser-shape Worker global
152
+ // (worker-polyfill.mjs) and Web Locks (navigator-locks.mjs) — were previously
153
+ // installed EAGERLY at preload (polyfills.cjs:installEsmPolyfillsSync). That drags
154
+ // ~50 builtins into bootstrap on EVERY startup: worker-polyfill.mjs imports
155
+ // node:worker_threads, which pulls internal/streams/* (readable/writable/duplex/
156
+ // transform/pipeline/…), internal/worker, internal/worker/io,
157
+ // internal/worker/messaging, vm, net, child_process, os, etc.; navigator-locks.mjs
158
+ // pulls internal/locks + internal/navigator. None of that is needed by the common
159
+ // "run a plain file, never touch Worker or navigator.locks" case, and the eager
160
+ // load is a cold-start regression that contradicts the fast-runner premise
161
+ // (test-bootstrap-modules: moduleLoadList must match Node's bootstrap set).
162
+ //
163
+ // Replace the eager install with lazy globals:
164
+ // • `globalThis.Worker` — a non-enumerable getter that, on first access (the
165
+ // first `new Worker(...)`), deletes itself, requires worker-polyfill.mjs (which
166
+ // then defines the real `globalThis.Worker`), and returns it.
167
+ // • `navigator.locks` — a non-enumerable getter that loads navigator-locks.mjs on
168
+ // first access (only when not native — Node 24.5+ ships it).
169
+ // In a WORKER thread, the worker-side bootstrap inside worker-polyfill.mjs (self/
170
+ // postMessage/message wiring) MUST run at startup, so we load it eagerly there.
171
+ // That costs nothing for bootstrap accounting: a worker already loaded
172
+ // worker_threads to exist, and test-bootstrap-modules measures the main thread.
173
+ function installLazyEsmPolyfills() {
174
+ // Cheap main-thread detection that does NOT pull node:worker_threads into the
175
+ // main-thread bootstrap (requiring it eagerly is exactly the regression we're
176
+ // fixing): in a worker, worker_threads is already in the module-load list by the
177
+ // time this preload runs; on the main thread it is not.
178
+ const inWorkerThread = process.moduleLoadList.some(
179
+ (m) => m === "NativeModule worker_threads",
180
+ );
181
+
182
+ const loadEsmSideEffect = (specifier) => {
183
+ try {
184
+ __require(specifier);
185
+ } catch (err) {
186
+ if (err && err.code === "ERR_REQUIRE_ESM") {
187
+ // require(esm) disabled — load via dynamic import (not flag-gated). Async,
188
+ // but side-effect-only; the Worker/locks polyfills are needed lazily, and
189
+ // for a worker thread the worker-side wiring lands a tick later, which is
190
+ // still before any user message round-trip can complete.
191
+ import(specifier).catch(() => {});
192
+ } else {
193
+ throw err;
194
+ }
195
+ }
196
+ };
197
+
198
+ if (inWorkerThread) {
199
+ // Worker-side scope bootstrap must be present synchronously where possible.
200
+ loadEsmSideEffect("./worker-polyfill.mjs");
201
+ if (typeof globalThis.navigator?.locks === "undefined") {
202
+ loadEsmSideEffect("./navigator-locks.mjs");
203
+ }
204
+ return;
205
+ }
206
+
207
+ // Main thread: lazy Worker global. Defined NON-ENUMERABLE so it stays invisible
208
+ // to `Object.keys(globalThis)` / for-in — the additive contract — matching how
209
+ // worker-polyfill.mjs defines the real one.
210
+ if (typeof globalThis.Worker === "undefined") {
211
+ let installing = false;
212
+ Object.defineProperty(globalThis, "Worker", {
213
+ configurable: true,
214
+ enumerable: false,
215
+ get() {
216
+ if (installing) return undefined;
217
+ installing = true;
218
+ // Drop this lazy accessor so worker-polyfill.mjs's own
219
+ // `if (typeof globalThis.Worker === "undefined")` guard fires and defines
220
+ // the real Worker.
221
+ delete globalThis.Worker;
222
+ loadEsmSideEffect("./worker-polyfill.mjs");
223
+ return globalThis.Worker;
224
+ },
225
+ set(value) {
226
+ // A user assigning their own Worker wins — replace the lazy accessor.
227
+ Object.defineProperty(globalThis, "Worker", {
228
+ value,
229
+ configurable: true,
230
+ enumerable: false,
231
+ writable: true,
232
+ });
233
+ },
234
+ });
235
+ }
236
+
237
+ // Main thread: lazy navigator.locks (native on Node 24.5+, absent on the 22.x
238
+ // floor). VERSION-GATE so we never even READ `globalThis.navigator` where locks
239
+ // is native: on Node 24.5+ the native `navigator` global is a lazy getter that,
240
+ // on first access, eagerly realizes internal/navigator + internal/locks AND the
241
+ // whole stream/worker-io transitive set (~30 builtins) — touching it at preload
242
+ // would be exactly the cold-start regression test-bootstrap-modules guards
243
+ // against, for zero benefit (locks is already there). Below 24.5 navigator is
244
+ // present but lacks `locks`, and accessing it is cheap (one internal module), so
245
+ // installing the lazy polyfill there is fine.
246
+ const [navMaj, navMin] = process.versions.node.split(".").map((n) => parseInt(n, 10));
247
+ const locksNative = navMaj > 24 || (navMaj === 24 && navMin >= 5);
248
+ if (locksNative) return;
249
+
250
+ const nav = globalThis.navigator;
251
+ if (nav && typeof nav.locks === "undefined") {
252
+ let installing = false;
253
+ Object.defineProperty(nav, "locks", {
254
+ configurable: true,
255
+ enumerable: true,
256
+ get() {
257
+ if (installing) return undefined;
258
+ installing = true;
259
+ delete nav.locks;
260
+ loadEsmSideEffect("./navigator-locks.mjs");
261
+ return nav.locks;
262
+ },
263
+ set(value) {
264
+ Object.defineProperty(nav, "locks", {
265
+ value,
266
+ configurable: true,
267
+ enumerable: true,
268
+ writable: true,
269
+ });
270
+ },
271
+ });
272
+ }
273
+ }