Skip to content

runtime: defer text imports to Node native on 26.5+ - #396

Closed
colinhacks wants to merge 1 commit into
mainfrom
import-text-unflag
Closed

runtime: defer text imports to Node native on 26.5+#396
colinhacks wants to merge 1 commit into
mainfrom
import-text-unflag

Conversation

@colinhacks

Copy link
Copy Markdown
Contributor

Node 26.5.0 added --experimental-import-text (nodejs/node#62300). On Node >= 26.5.0 nub injects it and its preload defers with { type: "text" } to Node's native translator; below 26.5 nub's own loadTextImport short-circuit stays the mechanism. Output is byte-identical across the boundary (both TextDecoder, 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-text and version downgrades fall back to nub's impl. Verified on Node 26.5.0 / 26.2.0 / 24.4.0; tiers pinned in version_tiers.rs.

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).
Copilot AI review requested due to automatic review settings July 9, 2026 16:42
@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nub Ready Ready Preview, Comment Jul 9, 2026 4:47pm

Request Review

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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-text feature-matrix row — an Unflag("--experimental-import-text") mitigation on the open-ended band [26.5.0, ∞) in feature_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_TEXT signalNATIVE_IMPORT_TEXT_ENV in spawn.rs, set iff --experimental-import-text is in the FINAL inject vec; the direct-spawn block sets-or-env_removes it authoritatively, and compute_augmentation_env carries it as the new AugmentationEnv::native_import_text field applied via apply_native_import_text_env.
  • Wire all augmentation consumers — the two cli.rs script/exec paths and the pm_engine lifecycle overlay each gained the mirror apply_native_import_text_env call alongside their existing apply_localstorage_env call.
  • Gate the fast-tier preloadpreload-common.cjs reads the signal once at hook construction AND applies a hard >= 26.5.0 version floor before deferring via nextLoad; both gates fail safe to nub's own impl. The compat-tier preload-async-hooks.mjs path 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.

Pullfrog  | View workflow run | Using Claude Opus𝕏

@colinhacks

Copy link
Copy Markdown
Contributor Author

Superseded by #395, which shipped the same behavior via native feature detection.

@colinhacks colinhacks closed this Jul 9, 2026
colinhacks added a commit that referenced this pull request Jul 9, 2026
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
colinhacks added a commit that referenced this pull request Jul 9, 2026
… 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants