Resolve shared island modules by real path (#2671)

This commit is contained in:
Chris Tate
2026-10-30 13:56:31 -05:00
committed by GitHub
3 changed files with 35 additions and 7 deletions
+12 -1
View File
@@ -30,8 +30,19 @@ function scriptcSharedModules(nativeHost) {
const table = JSON.parse(nativeHost.sharedTable());
const none = { entry: (path, load) => load(null), push() {} };
if (table.length === 0) return none;
const { realpathSync } = require("node:fs");
// Node resolves an import to the module's real path, so a module of a
// tree reached through a symbolic link (a cache directory under macOS's
// /var, which is /private/var) is keyed by its real path as well.
const byUrl = new Map();
table.forEach((m, id) => byUrl.set(pathToFileURL(m.path).href, id));
table.forEach((m, id) => {
byUrl.set(pathToFileURL(m.path).href, id);
try {
byUrl.set(pathToFileURL(realpathSync(m.path)).href, id);
} catch {
// A module that is not on disk keeps only its own path.
}
});
const TDZ = Symbol("scriptc.tdz");
const setters = new Map(); // `${mod}:${slot}` -> [(value) => void]
const entries = new Map(); // entry URL -> { target, late: [[mod, slot]] }
+12 -1
View File
@@ -769,8 +769,19 @@ static const char scr_node_island_host_js[] =
" const table = JSON.parse(nativeHost.sharedTable());\012"
" const none = { entry: (path, load) => load(null), push() {} };\012"
" if (table.length === 0) return none;\012"
" const { realpathSync } = require(\"node:fs\");\012"
" // Node resolves an import to the module's real path, so a module of a\012"
" // tree reached through a symbolic link (a cache directory under macOS's\012"
" // /var, which is /private/var) is keyed by its real path as well.\012"
" const byUrl = new Map();\012"
" table.forEach((m, id) => byUrl.set(pathToFileURL(m.path).href, id));\012"
" table.forEach((m, id) => {\012"
" byUrl.set(pathToFileURL(m.path).href, id);\012"
" try {\012"
" byUrl.set(pathToFileURL(realpathSync(m.path)).href, id);\012"
" } catch {\012"
" // A module that is not on disk keeps only its own path.\012"
" }\012"
" });\012"
" const TDZ = Symbol(\"scriptc.tdz\");\012"
" const setters = new Map(); // `${mod}:${slot}` -> [(value) => void]\012"
" const entries = new Map(); // entry URL -> { target, late: [[mod, slot]] }\012"
+11 -5
View File
@@ -18,6 +18,7 @@ import {
realpathSync,
rmSync,
statSync,
symlinkSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
@@ -544,13 +545,18 @@ export function patchAndBump(): number {
// Node strips types only outside node_modules, and the shared island
// cache of these tests lives below the repository's node_modules.
const islandCache = mkdtempSync(join(tmpdir(), "scriptc-island-cache-"));
// A cache reached through a symbolic link (macOS's temporary directory
// is under /var, which is /private/var): Node resolves the island's
// import to the shared module's real path.
const linkedCache = `${islandCache}-link`;
symlinkSync(islandCache, linkedCache);
try {
const out = await run(join(dir, "main"), [], {
...process.env,
XDG_CACHE_HOME: islandCache,
});
expect(out).toEqual({ stdout: "2 2\n", stderr: "", code: 0 });
for (const cache of [islandCache, linkedCache]) {
const out = await run(join(dir, "main"), [], { ...process.env, XDG_CACHE_HOME: cache });
expect(out).toEqual({ stdout: "2 2\n", stderr: "", code: 0 });
}
} finally {
rmSync(linkedCache, { force: true });
rmSync(islandCache, { recursive: true, force: true });
}
}, 300_000);