@nubjs/nub 0.0.22 → 0.0.23

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/launch.js CHANGED
@@ -9,18 +9,20 @@
9
9
  //
10
10
  // On its FIRST POSIX invocation this launcher SELF-HEALS: it rewrites the on-PATH
11
11
  // entry that dispatched it — the package manager's bin shim (pnpm cmd-shim) or
12
- // symlink (npm/bun) — into a MINIMAL `#!/bin/sh` trampoline that exec's the native
13
- // binary directly. Every later call then resolves PATH -> that tiny sh trampoline
12
+ // symlink (npm/bun/yarn) — into a tiny `#!/bin/sh` sh/node POLYGLOT trampoline that
13
+ // exec's the native binary. Every later call then resolves PATH -> that trampoline
14
14
  // -> native, skipping Node entirely (~native cold-start; the sh hop is ~1-2ms on
15
15
  // Linux dash/busybox, ~4ms on macOS bash — vs ~50ms for this Node launcher).
16
16
  //
17
- // CRITICAL: the heal target is a minimal sh SCRIPT, never a native binary. A
18
- // script->binary swap has an irreducible TOCTOU race (the kernel reads `#!/bin/sh`
19
- // then `/bin/sh` reopens the path and finds a Mach-O -> "cannot execute binary
20
- // file"; ~24% under a concurrent burst). A script->script swap (both `#!/bin/sh`,
21
- // always valid scripts) is race-free by construction a concurrent `/bin/sh`
22
- // reopening the entry mid-swap always reads a valid trampoline (measured 0/600 vs
23
- // 146/600). So the heal needs no lock: it is best-effort, atomic (write temp +
17
+ // CRITICAL: the heal target is a SCRIPT, never a native binary (a script->binary swap
18
+ // has an irreducible exec-format TOCTOU race), AND it is an sh/node polyglot so the
19
+ // swap is safe under concurrency on every PM. Two race classes are closed: (1) pnpm's
20
+ // entry is an sh cmd-shim, so sh->sh is race-free by construction; (2) npm/bun/yarn's
21
+ // entry is a symlink to this #!node launcher, so a concurrent Node that already passed
22
+ // the shebang and re-reads the swapped file would parse sh-as-JS and die — UNLESS the
23
+ // new file is also valid JS, which the polyglot is (it runs a JS fallback that spawns
24
+ // native). Measured: pure-sh heal ~6%/200 concurrent first-call failures on npm/bun;
25
+ // polyglot 0/600. So the heal needs no lock: it is best-effort, atomic (write temp +
24
26
  // rename), verify-before-clobber, and a no-op on Windows.
25
27
  //
26
28
  // The native binary selects its verb from argv[0]'s basename (nub vs nubx); the
@@ -88,7 +90,18 @@ function healPathEntry(verb, nativePath) {
88
90
  const ourBin = path.join(__dirname, verb); // .../@nubjs/nub/bin/<verb>
89
91
  let ourReal; try { ourReal = fs.realpathSync(ourBin); } catch { ourReal = ourBin; }
90
92
  let nativeReal; try { nativeReal = fs.realpathSync(nativePath); } catch { nativeReal = nativePath; }
91
- const content = `#!/bin/sh\nexec ${shq(nativeReal)} "$@"\n`;
93
+ // The healed entry is an sh/node POLYGLOT. A fresh exec reads `#!/bin/sh` and sh
94
+ // runs line 2 (`exec native`, the fast path). But a concurrent Node that already
95
+ // spawned through the pre-heal node shim — passing the `#!node` shebang BEFORE the
96
+ // heal renamed this file in — then re-opens this path as its "script" and reads
97
+ // line 2 as a `":"` string statement + a `//` comment (no-op), running line 3's JS
98
+ // fallback (spawn native) instead of choking on sh-as-JS. So the heal is race-free
99
+ // on symlink-to-node-shim PMs (npm/bun/yarn) too, the guarantee pnpm gets for free.
100
+ // Measured: pure-sh heal ~6%/200 concurrent first-call failures; polyglot 0/600.
101
+ const content =
102
+ `#!/bin/sh\n` +
103
+ `":" //# nub launcher; exec ${shq(nativeReal)} "$@"\n` +
104
+ `var r=require("child_process").spawnSync(${JSON.stringify(nativeReal)},process.argv.slice(2),{stdio:"inherit"});process.exit(r.status==null?1:r.status)\n`;
92
105
 
93
106
  for (const dir of (process.env.PATH || "").split(path.delimiter)) {
94
107
  if (!dir) continue;
package/bin/nub CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- // Entry point for the `nub` command. On POSIX this file is replaced by a symlink
4
- // to the native binary at install time (see postinstall.js); it only executes via
5
- // Node on Windows or as a fallback. No argv0 override the child sees the binary's
6
- // own basename ("nub") and runs the default verb.
3
+ // Entry point for the `nub` command. The package manager links its on-PATH `nub` to
4
+ // this Node launcher (a symlink on npm/bun/yarn, an sh cmd-shim on pnpm). On its first
5
+ // POSIX call, launch.js self-heals that on-PATH entry into a tiny sh trampoline the
6
+ // native binary, so later calls skip Node entirely (see launch.js). On Windows there
7
+ // is no such fast path and this Node launcher runs on every call.
7
8
  require("./launch.js")();
package/bin/nubx CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- // Entry point for the `nubx` command (npx-equivalent bin runner). On POSIX this
4
- // file is replaced by a symlink to the native binary at install time; it only
5
- // executes via Node on Windows or as a fallback. argv0 "nubx" makes the Rust CLI
6
- // enter exec mode directly (Argv0::Nubx), identical to the POSIX symlink whose
7
- // basename is "nubx".
3
+ // Entry point for the `nubx` command (npx-equivalent bin runner). The package manager
4
+ // links its on-PATH `nubx` to this Node launcher; on its first POSIX call launch.js
5
+ // self-heals that entry into a tiny sh trampoline that exec's the platform package's
6
+ // bin/nubx whose argv[0] basename "nubx" makes the Rust CLI enter exec mode
7
+ // (Argv0::Nubx). On Windows this Node launcher runs every call (no fast path).
8
8
  require("./launch.js")("nubx");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nubjs/nub",
3
- "version": "0.0.22",
3
+ "version": "0.0.23",
4
4
  "description": "TypeScript-first developer supertool — a fast script runner and TS runtime powered by Node.js",
5
5
  "license": "MIT",
6
6
  "repository": "https://github.com/nubjs/nub",
@@ -14,13 +14,13 @@
14
14
  "platform.js"
15
15
  ],
16
16
  "optionalDependencies": {
17
- "@nubjs/nub-darwin-arm64": "0.0.22",
18
- "@nubjs/nub-darwin-x64": "0.0.22",
19
- "@nubjs/nub-linux-x64": "0.0.22",
20
- "@nubjs/nub-linux-x64-musl": "0.0.22",
21
- "@nubjs/nub-linux-arm64": "0.0.22",
22
- "@nubjs/nub-linux-arm64-musl": "0.0.22",
23
- "@nubjs/nub-win32-x64": "0.0.22",
24
- "@nubjs/nub-win32-arm64": "0.0.22"
17
+ "@nubjs/nub-darwin-arm64": "0.0.23",
18
+ "@nubjs/nub-darwin-x64": "0.0.23",
19
+ "@nubjs/nub-linux-x64": "0.0.23",
20
+ "@nubjs/nub-linux-x64-musl": "0.0.23",
21
+ "@nubjs/nub-linux-arm64": "0.0.23",
22
+ "@nubjs/nub-linux-arm64-musl": "0.0.23",
23
+ "@nubjs/nub-win32-x64": "0.0.23",
24
+ "@nubjs/nub-win32-arm64": "0.0.23"
25
25
  }
26
26
  }