Embedder support for wrapping the Node runtime (not just selecting one) #1083
Replies: 3 comments 4 replies
|
this is going to be a big change but I think it's necessary, I'm working on it |
|
Thanks for the detailed write-up — the direction is welcome, and the decomposition (three distinct paths + an env contribution + every spawn path) held up. This is now implemented in #1086. What landed, relative to the proposal:
We also read through nub's tree (the
From the mapping, this should let nub drop its runtime-seam patches ( The other fork seams (the disk-materialize/extract hooks, the UA token, config-posture flags) are out of scope here, but happy to discuss those separately if you want to shrink the fork further. Feedback on the API shape welcome before it merges. This comment was generated by Claude. |
|
Confirming the semantic difference you flagged: equivalent for nub. The NUB profile sets One gap does block dropping entries.push(project_bin); // node_modules/.bin
// The switched Node runtime sits between project bins and the
// inherited PATH: ... while anything installed into `.bin` still wins.
if let Some(dir) = &settings.node_bin_dir { entries.push(dir.clone()); }
Two shapes would close it: a Related and minor: AI-assisted — Tool: Claude Code; model: anthropic/claude-opus-5; version: unavailable. |
Uh oh!
There was an error while loading. Please reload this page.
PR #1079 lets an embedder point aube at a Node for lifecycle scripts — a version manager selecting a toolchain. It can't express an embedder that wraps Node rather than selecting one: an instrumenting runtime, a transpiling loader, a sandbox. That case needs three things the current hook doesn't carry.
node_bin_dirbecomes the PATH entry,NODE, andnpm_node_execpathat once (node_bin = bin_dir.join("node")). A wrapper needs them distinct: its shim dir on PATH,NODEat the shim so$NODE child.jsin a script stays wrapped, andnpm_node_execpathat the real node, which node-gyp and native-addon tooling read to find Node's install prefix.NODE_OPTIONSpreload is how you interpose without patching Node. There's no hook for it today.seed_embedder_nodehook only applies insideruntime::scope, sodlx/exec/run/nodenever see it. A selector that misses a path falls back to the ambient node; a wrapper silently runs dependencies unwrapped, which is worse than not wrapping.The proposal is to let an embedder describe a Node invocation rather than a bin dir:
Embedder side. The host resolves its own runtime, then describes how Node should be invoked — per call, or registered once so every spawn path sees it:
Script side. A dependency's
postinstallthen runs with:Each of these then does the right thing:
Every field is optional and unset reproduces today's behavior, so standalone aube is unchanged. The existing
node_bin_dirbecomes the degenerate case ({ bin_dir }). Registration is set-once and first-write-wins, the same shape asset_embedder/set_embedder_defaults, with a per-call value taking precedence, so the ambient path costs no mutable runtime global.Nub does this today in a fork — it augments Node through a preload — and runs it in production. Happy to open a PR if the direction's welcome.
All reactions