#3095

Resolve a bare subpath to its island file when Node names no runtime entry

Opencramforcewants to merge intofrom

The site

pi reports packages/ai/src/utils/provider-env.ts:26:17 - error SC1090: library functions as values (call 'readFileSync' directly) in every round of its build (round 1 has 193 diagnostics, round 2 76, round 3 67; only the last round's list is printed). It is not a round-3 artifact.

Root cause

islandModuleFile's bare-specifier branch resolved with the runtime-JS pass only. For a workspace package whose exports map points a subpath at TypeScript source ("./utils/*": { "types": "./src/utils/*.ts", "import": "./src/utils/*.ts" }), that pass answers nothing — pi's packages/ai has no runnable JS entry. An import of an island module over such a bare subpath (cache-warmer.ts:10) therefore never bound to the island, and the island module's body was compiled natively, where readFileSync's cast-typed callee hits the library-function-as-value fence.

Relative specifiers take relativeIslandFile and work, which is why the earlier isolated probes and corpus program did not reproduce it.

Fix

lower-node-island.ts, islandModuleFile, bare branch: when the runtime-JS pass answers nothing, fall back to resolveBareModule(..., "runtime-source", ...) and accept the answer only if islandOwnerOfFile names an island, so an unrelated resolution can never become an island import. An early return when the island set owns no packages keeps programs without islands on exactly the old path. The fallback answers import edges only (7adc37cc4, from review): it resolves with Node's import conditions, and a package may map "require" to another file, so a require() keeps the answer it had before, which binds nothing.

Evidence

  • New differential corpus program tests/corpus/8998-node-island-workspace-reader/: a workspace package @probe/ai mapping ./utils/* to TS source, an island reader module that reads through a patched fs.readFileSync, and a native module importing it by bare subpath. It fails to compile before the change and matches Node after (differential.test.ts -t 8998-node-island-workspace-reader → 1 passed).
  • node-islands unit tests: 161 passed. Node island harness: 34 passed, 1 failed (Node ignores NODE_OPTIONS from the program's environment), which fails identically on the unmodified compiler.
  • pnpm test:ts7 --baselines-only complete; order-parity.test.ts 121/121 passed.
  • New unit test packages/compiler/src/frontend/lowering/lower-node-island.test.ts: a workspace package whose exports map names one source file for "import" and another for "require". The import edge answers the island file; the require edge answers nothing. Without the import-only guard the require case returns the import's file (1 failed, 2 passed); with it 3 passed. node-islands unit tests with it: 164 passed.
  • On 7adc37cc4 in a sandbox: differential.test.ts -t 8998-node-island-workspace-reader passes plain and under SCRIPTC_SAN=1; differential.test.ts -t node-island is 78 passed, 1 failed. The failure is 6863-node-island-native-arrays (V8 Check failed: isolate_->IsOnCentralStack() inside the sandbox's libnode pack); it fails the same way with the guard removed, and CI passes it. pnpm lint and pnpm format:check are clean.
  • Zero-cost gate (bin/validate --skip=lanes,bench,t262,san-bootstrap --gate-corpus=all) on 7adc37cc4: PASS in 14.1 min — 5175 identical, 95 both-fail over 8 shards, no differing program, no runtime-only row; bench geomean −0.04 %, fixtures geomean +0.38 %, self +1.75 % (reported inconclusive; the compiler's own build has no island set, so it never reaches the changed branch). The same gate passed on 8567c8677 (18.1 min) and d7c9d1fcf (20.4 min).
  • The native bootstraps were not run for this PR. An earlier version of this description said the second gate run included them; it did not (--skip=lanes leaves them out). The change is reached only with a non-empty island set, which the compiler's own build does not have.
  • pi: 67 → 66 diagnostics, and diff of the two lists is exactly the provider-env.ts:26:17 line. No other diagnostic changed.

🤖 Generated with Claude Code

Activity

7
vercel[bot]6d ago

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

ProjectDeploymentActionsUpdated
scriptc ReadyPreview, v0Nov 7, 2026 12:08am UTC
vercel[bot]reviewed6d ago
cramforcereviewed6d ago
vercel[bot]reviewed6d ago