runtime: defer text imports to Node native on 26.5+ - #396
Conversation
Node 26.5.0 introduced --experimental-import-text (#62300), giving Node's
ESM loader native `with { type: "text" }` support on any extension. On
Node >= 26.5.0 nub now injects that flag and its fast-tier preload defers
text imports to Node's native translator instead of serving them with its
own loadTextImport short-circuit; below 26.5 the flag does not exist, so
nub's runtime augmentation stays the sole mechanism. Output is byte-identical
across the boundary (both TextDecoder default-export, BOM stripped).
- feature_matrix: import-text Unflag band [26.5.0, inf); derives the
NODE_OPTIONS strip-floor for version-downgraded children for free.
- spawn: signal the preload via the internal __NUB_NATIVE_IMPORT_TEXT env
var, set iff --experimental-import-text is in the final inject set (both
the direct-spawn and script-runner paths) and cleared otherwise on the
direct path, so a user --no-experimental-import-text falls back to nub's
own impl and the signal tracks the flag.
- preload-common: defer to native only when the signal is set AND the
running Node is >= 26.5.0 (a version floor that fails safe to nub's impl
if a stale signal is inherited across a version downgrade); else
loadTextImport. async-tier hook unchanged (compat tier is below 26.5).
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
✅ No new issues found.
Reviewed changes — nub now defers import … with { type: "text" } to Node's native --experimental-import-text translator on Node ≥ 26.5.0, keeping its own loadTextImport short-circuit below that boundary.
- Add
import-textfeature-matrix row — anUnflag("--experimental-import-text")mitigation on the open-ended band[26.5.0, ∞)infeature_matrix.rs, which drives injection, NODE_OPTIONS stripping, and user opt-out through the existing generic paths with no parallel tables. - Add
__NUB_NATIVE_IMPORT_TEXTsignal —NATIVE_IMPORT_TEXT_ENVinspawn.rs, set iff--experimental-import-textis in the FINAL inject vec; the direct-spawn block sets-or-env_removes it authoritatively, andcompute_augmentation_envcarries it as the newAugmentationEnv::native_import_textfield applied viaapply_native_import_text_env. - Wire all augmentation consumers — the two
cli.rsscript/exec paths and thepm_enginelifecycle overlay each gained the mirrorapply_native_import_text_envcall alongside their existingapply_localstorage_envcall. - Gate the fast-tier preload —
preload-common.cjsreads the signal once at hook construction AND applies a hard>= 26.5.0version floor before deferring vianextLoad; both gates fail safe to nub's own impl. The compat-tierpreload-async-hooks.mjspath stays unconditional (comment-only change). - Tier + flag coverage — new tests for injection floor/open-end/opt-out, below-floor NODE_OPTIONS stripping, native-defer transparency (same fixture and assertions across the 24.4.0 short-circuit and 26.5.0 native paths, plus ExperimentalWarning suppression), and the overlay signal reaching build-script children.
The design is sound and cleanly matrix-driven: the single import-text row plugs into unflag_flags_for (injection), unflag_floor (exit-9 stripping), and collect_negations/is_negation_of (opt-out) without any parallel tables. The signal-tracks-the-flag coupling, the direct-spawn env_remove, and the preload's >= 26.5.0 floor together make the never-defer-without-the-flag invariant hold across version downgrades and forced-async tiers. Field coverage is complete — every apply_localstorage_env site gained the mirror call, and no other AugmentationEnv constructor exists. Mergeable as-is.
Claude Opus | 𝕏
|
Superseded by #395, which shipped the same behavior via native feature detection. |
The salvaged test comments referenced the env-signal design from the closed #396 branch (__NUB_NATIVE_IMPORT_TEXT); the merged #395 mechanism is the NATIVE_IMPORT_TEXT feature-detect const in preload-common.cjs. Comments only. Claude-Session: https://claude.ai/code/session_01Gp4tAn3Y66MWpAdGZm9VmL
… 26.5 native) (#397) * test: pin cross-tier import-text behavior (22.13 compat / 24.4 fast / 26.5 native) Claude-Session: https://claude.ai/code/session_0144KrmfsBDfzFZnHAMaH6E3 * test: fix doc-comment references to the merged native-defer mechanism The salvaged test comments referenced the env-signal design from the closed #396 branch (__NUB_NATIVE_IMPORT_TEXT); the merged #395 mechanism is the NATIVE_IMPORT_TEXT feature-detect const in preload-common.cjs. Comments only. Claude-Session: https://claude.ai/code/session_01Gp4tAn3Y66MWpAdGZm9VmL

Node 26.5.0 added
--experimental-import-text(nodejs/node#62300). On Node >= 26.5.0 nub injects it and its preload deferswith { type: "text" }to Node's native translator; below 26.5 nub's ownloadTextImportshort-circuit stays the mechanism. Output is byte-identical across the boundary (bothTextDecoder, default export, BOM stripped).The preload defers only when signaled (
__NUB_NATIVE_IMPORT_TEXT, set iff the flag is in the final inject set) AND Node >= 26.5.0, so--no-experimental-import-textand version downgrades fall back to nub's impl. Verified on Node 26.5.0 / 26.2.0 / 24.4.0; tiers pinned inversion_tiers.rs.