rea/src/application/javascript/JavaScriptArtifactPathResol...

2763 lines
78 KiB
TypeScript

import { describe, expect, it } from "vitest";
import {
resolveArtifactPathByContext,
type ResolveArtifactPathInput,
} from "./JavaScriptArtifactPathResolution.js";
import type { JavaScriptArtifactFile } from "../../domain/javascript/javascriptArtifactFiles.js";
import { artifactLocalIdentity } from "./JavaScriptArtifactGraphContext.js";
import { applicationNodeIdentitySchema } from "../../domain/javascript/javascriptApplicationEvidenceSchemas.js";
import { analyzeJavaScriptStaticSource } from "../../domain/javascript/javascriptStaticAnalysis.js";
describe("artifact URI scheme classification", () => {
it.each(["html-reference", "module-specifier", "url-reference"] as const)(
"keeps digit-bearing schemes external in %s even when a local file matches",
(context) => {
const files = fileMap([
file("index.html", "root"),
file("web3:app.js", "root"),
]);
expect(
resolve({
declaredPath: "web3:app.js",
sourcePath: "index.html",
context,
files,
}),
).toMatchObject({ resolution_status: "external", resolved_path: null });
},
);
it("keeps references under a digit-bearing external base href external", () => {
const files = fileMap([
file("index.html", "root"),
file("web3:assets/app.js", "root"),
]);
expect(
resolve({
declaredPath: "app.js",
sourcePath: "index.html",
context: "html-reference",
htmlBaseHref: "web3:assets/",
files,
}),
).toMatchObject({ resolution_status: "external", resolved_path: null });
});
});
describe("artifact-local graph identity", () => {
it("preserves complete long namespace and key values", () => {
const digest = "a".repeat(64);
const namespacePrefix = "n".repeat(512);
const keyPrefix = "k".repeat(4_096);
const first = artifactLocalIdentity(
digest,
`${namespacePrefix}a`,
`${keyPrefix}a`,
);
const second = artifactLocalIdentity(
digest,
`${namespacePrefix}b`,
`${keyPrefix}b`,
);
expect(applicationNodeIdentitySchema.parse(first)).toEqual(first);
expect(applicationNodeIdentitySchema.parse(second)).toEqual(second);
expect(first).not.toEqual(second);
});
});
describe("loader-owned path lookup", () => {
it("keeps relative ESM imports exact", () => {
const files = fileMap([
file("app/entry.mjs", "root"),
file("app/feature.js", "root"),
file("app/directory/index.js", "root"),
file("app/feature.js.js", "root"),
]);
for (const declaredPath of ["./feature", "./directory"]) {
expect(
resolve({
declaredPath,
sourcePath: "app/entry.mjs",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
}
expect(
resolve({
declaredPath: "./feature.js",
sourcePath: "app/entry.mjs",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({ resolved_path: "app/feature.js" });
});
it("does not use .cjs as an extensionless CommonJS probe", () => {
const files = fileMap([
file("app/entry.cjs", "root"),
file("app/feature.cjs", "root"),
]);
expect(
resolve({
declaredPath: "./feature",
sourcePath: "app/entry.cjs",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
expect(
resolve({
declaredPath: "./feature.cjs",
sourcePath: "app/entry.cjs",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({ resolved_path: "app/feature.cjs" });
});
it("keeps present opaque inventory files distinct from missing module targets", () => {
const opaque = new Map([
[
"app/core.jsc",
{
path: "app/core.jsc",
container_sha256: file("app/entry.cjs", "root").container_sha256,
sha256: "a".repeat(64),
bytes: 7,
inventory_artifact_id: "opaque-core",
},
],
]);
const files = fileMap([file("app/entry.cjs", "root")]);
const unanalyzedFiles = {
get: (path: string) => opaque.get(path),
hasDirectory: () => false,
};
expect(
resolve({
declaredPath: "./core.jsc",
sourcePath: "app/entry.cjs",
context: "module-specifier",
moduleKind: "require",
files,
unanalyzedFiles,
}),
).toMatchObject({
resolution_status: "unavailable",
resolved_path: null,
candidate_path: "app/core.jsc",
limitations: [
expect.stringContaining(`sha256 ${"a".repeat(64)}, 7 bytes`),
],
});
expect(
resolve({
declaredPath: "./missing.jsc",
sourcePath: "app/entry.cjs",
context: "module-specifier",
moduleKind: "require",
files,
unanalyzedFiles,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
expect(
resolve({
declaredPath: "./core.jsc",
sourcePath: "app/entry.cjs",
context: "module-specifier",
moduleKind: "require",
files,
unanalyzedFiles: {
...unanalyzedFiles,
get: () => ({
...opaque.get("app/core.jsc")!,
container_sha256: "b".repeat(64),
}),
},
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
});
});
describe("bare package root file lookup", () => {
it("uses loader-specific bare package roots when only a sibling .js file exists", () => {
const absentDirectory = fileMap([
file("app/entry.mjs", "root"),
file("app/node_modules/fixture.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/entry.mjs",
context: "module-specifier",
moduleKind: "import",
files: absentDirectory,
}),
).toMatchObject({ resolution_status: "external", resolved_path: null });
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/entry.mjs",
context: "module-specifier",
moduleKind: "require",
files: absentDirectory,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture.js",
});
const packageDirectory = fileMap([
file("app/entry.mjs", "root"),
file("app/node_modules/fixture.js", "root"),
file("app/node_modules/fixture/package.json", "root", "{}"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/entry.mjs",
context: "module-specifier",
moduleKind: "import",
files: packageDirectory,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/entry.mjs",
context: "module-specifier",
moduleKind: "require",
files: packageDirectory,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture.js",
});
});
});
describe("legacy package main lookup", () => {
it("treats an empty package main as absent and resolves the root index", () => {
const files = fileMap([
file("app/src/entry.cjs", "root"),
file("app/node_modules/fixture/package.json", "root", '{"main":""}'),
file("app/node_modules/fixture/index.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/src/entry.cjs",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture/index.js",
});
});
it.each(["import", "require"] as const)(
"limits %s package-main probes to Node's file extensions",
(moduleKind) => {
const files = fileMap([
file("app/src/entry.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
'{"main":"main"}',
),
file("app/node_modules/fixture/main.cjs", "root"),
file("app/node_modules/fixture/index.mjs", "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/src/entry.js",
context: "module-specifier",
moduleKind,
files,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
},
);
it("retains inventoried directories during legacy ESM main finalization", () => {
const files = fileMap([
file("app/src/entry.mjs", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
'{"main":"./lib/"}',
),
file("app/node_modules/fixture/lib.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/src/entry.mjs",
context: "module-specifier",
moduleKind: "import",
files,
directoryPaths: new Set(["app/node_modules/fixture/lib/.js"]),
}),
).toMatchObject({
resolution_status: "rejected",
resolved_path: null,
candidate_path: "app/node_modules/fixture/lib/.js",
});
});
it.each(["import", "require"] as const)(
"does not recursively resolve a nested package from a %s package main",
(moduleKind) => {
const files = fileMap([
file("app/src/entry.js", "root"),
file("app/node_modules/fixture/package.json", "root", '{"main":"sub"}'),
file(
"app/node_modules/fixture/sub/package.json",
"root",
'{"main":"other"}',
),
file("app/node_modules/fixture/sub/other.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/src/entry.js",
context: "module-specifier",
moduleKind,
files,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
},
);
});
describe("legacy package main metadata validation and fallback", () => {
it("still rejects non-string package main metadata", () => {
expect(
resolve({
declaredPath: "./package",
sourcePath: "app/entry.js",
context: "filesystem-expression",
files: fileMap([
file("app/entry.js", "root"),
file("app/package/package.json", "root", '{"main":false}'),
file("app/package/index.js", "root"),
]),
}),
).toMatchObject({ resolution_status: "unavailable", resolved_path: null });
});
it.each(["import", "require"] as const)(
"uses Node's index fallback for a non-string %s package main",
(moduleKind) => {
const files = fileMap([
file("app/src/entry.js", "root"),
file("app/node_modules/fixture/package.json", "root", '{"main":42}'),
file("app/node_modules/fixture/index.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/src/entry.js",
context: "module-specifier",
moduleKind,
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture/index.js",
});
},
);
it.each(["import", "require"] as const)(
"does not treat a root-pointing %s package main as a dotfile module",
(moduleKind) => {
const files = fileMap([
file("src/entry.js", "root"),
file("node_modules/fixture/package.json", "root", '{"main":"../.."}'),
file("index.js", "root"),
file(".js", "root"),
file(".json", "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "src/entry.js",
context: "module-specifier",
moduleKind,
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "index.js",
});
},
);
});
describe("CommonJS bare package ancestor lookup", () => {
it.each([
["absent metadata", undefined, true],
["empty metadata", "{}", true],
["empty main", '{"main":""}', true],
["truthy missing main", '{"main":"missing"}', false],
] as const)(
"handles %s before an ancestor package for both loaders",
(_name, packageJson, commonJsUsesAncestor) => {
const files = fileMap([
file("app/src/entry.js", "root"),
file("app/src/node_modules/fixture/placeholder.js", "root"),
...(packageJson === undefined
? []
: [
file(
"app/src/node_modules/fixture/package.json",
"root",
packageJson,
),
]),
file("app/node_modules/fixture/index.js", "root"),
]);
for (const moduleKind of ["import", "require"] as const) {
const resolution = resolve({
declaredPath: "fixture",
sourcePath: "app/src/entry.js",
context: "module-specifier",
moduleKind,
files,
});
if (moduleKind === "require" && commonJsUsesAncestor) {
expect(resolution).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture/index.js",
});
} else {
expect(resolution).toMatchObject({
resolution_status: "not-found",
resolved_path: null,
});
}
}
},
);
});
describe("CommonJS bare package subpath ancestor lookup", () => {
it.each([
["absent subpath", undefined, true],
["empty subpath metadata", "{}", true],
["truthy missing subpath main", '{"main":"missing"}', false],
] as const)(
"handles %s before an ancestor package for both loaders",
(_name, packageJson, commonJsUsesAncestor) => {
const files = fileMap([
file("app/src/entry.js", "root"),
file("app/src/node_modules/fixture/placeholder.js", "root"),
...(packageJson === undefined
? []
: [
file(
"app/src/node_modules/fixture/parser/package.json",
"root",
packageJson,
),
file(
"app/src/node_modules/fixture/parser/placeholder.js",
"root",
),
]),
file("app/node_modules/fixture/parser.js", "root"),
]);
const commonJsResolution = resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/entry.js",
context: "module-specifier",
moduleKind: "require",
files,
});
expect(commonJsResolution).toMatchObject({
resolved_path: commonJsUsesAncestor
? "app/node_modules/fixture/parser.js"
: null,
});
const esmResolution = resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/entry.js",
context: "module-specifier",
moduleKind: "import",
files,
});
expect(esmResolution.resolved_path).toBeNull();
},
);
});
describe("CommonJS bare package exhausted lookup", () => {
it.each([
["empty main", "fixture", '{"main":""}', "app/src/node_modules/fixture"],
[
"missing subpath",
"fixture/parser",
"{}",
"app/src/node_modules/fixture/parser",
],
] as const)(
"preserves not-found for an exhausted %s lookup",
(_name, declaredPath, packageJson, packageDirectory) => {
const files = fileMap([
file("app/src/entry.js", "root"),
file("app/src/node_modules/fixture/package.json", "root", packageJson),
file(`${packageDirectory}/placeholder.js`, "root"),
]);
expect(
resolve({
declaredPath,
sourcePath: "app/src/entry.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
},
);
});
describe("logical path identity", () => {
it("resolves an NFD relative import to the NFC inventory path and rejects a root escape", () => {
const nfc = "caf\u00e9".normalize("NFC");
const nfd = nfc.normalize("NFD");
const files = fileMap([
file("dir/index.js", "root"),
file(`dir/${nfc}.js`, "root"),
]);
expect(
resolve({
declaredPath: `./${nfd}.js`,
sourcePath: "dir/index.js",
context: "module-specifier",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: `dir/${nfc}.js`,
});
expect(
resolve({
declaredPath: "../escape.js",
sourcePath: "index.js",
context: "module-specifier",
files,
}),
).toMatchObject({ resolution_status: "rejected", resolved_path: null });
});
});
describe("contextual JavaScript artifact path resolution", () => {
it.each([
["main.js", "app/main.js"],
["./main.js", "app/main.js"],
["src/main", "app/src/main.cjs"],
["entry", "app/entry/start.mjs"],
["fallback", "app/fallback/index.ts"],
])("resolves package entrypoint %s", (declaredPath, expected) => {
const files = fileMap([
file("app/package.json", "root"),
file("app/main.js", "root"),
file("app/src/main.cjs", "root"),
file("app/entry/package.json", "root", '{"main":"start"}'),
file("app/entry/start.mjs", "root"),
file("app/fallback/index.ts", "root"),
]);
expect(
resolve({
declaredPath,
sourcePath: "app/package.json",
context: "package-entrypoint",
files,
}),
).toMatchObject({
resolution_context: "package-entrypoint",
resolution_status: "resolved",
resolved_path: expected,
limitations: [],
});
});
it("resolves dirname-derived bare paths but keeps bare module specifiers external", () => {
const files = fileMap([
file("app/main.js", "root"),
file("app/preload.js", "root"),
]);
const base = {
declaredPath: "preload.js",
sourcePath: "app/main.js",
files,
} as const;
expect(
resolve({ ...base, context: "filesystem-expression" }),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/preload.js",
});
expect(resolve({ ...base, context: "module-specifier" })).toMatchObject({
resolution_status: "external",
resolved_path: null,
});
});
it("applies document and base-href semantics to HTML references", () => {
const files = fileMap([
file("renderer/index.html", "root"),
file("assets/app.js", "root"),
file("renderer/local.js", "root"),
]);
expect(
resolve({
declaredPath: "app.js?v=1",
sourcePath: "renderer/index.html",
context: "html-reference",
htmlBaseHref: "/assets/",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "assets/app.js",
});
expect(
resolve({
declaredPath: "./local.js",
sourcePath: "renderer/index.html",
context: "html-reference",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "renderer/local.js",
});
});
it.each(["node:fs", "electron", "../../escape.js", "%2e%2e/escape.js"])(
"fails closed for unsafe or external module declaration %s",
(declaredPath) => {
const result = resolve({
declaredPath,
sourcePath: "app/main.js",
context: "module-specifier",
files: fileMap([file("app/main.js", "root")]),
});
expect(result.resolved_path).toBeNull();
expect(["external", "rejected"]).toContain(result.resolution_status);
expect(result.limitations.length).toBeGreaterThan(0);
},
);
it("does not cross nested ASAR container identities", () => {
const files = fileMap([
file("app.asar/main.js", "asar-a"),
file("app.asar/preload.js", "asar-b"),
]);
expect(
resolve({
declaredPath: "preload.js",
sourcePath: "app.asar/main.js",
context: "filesystem-expression",
files,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
});
it("resolves inventoried paths longer than the former character ceiling", () => {
const declaredPath = `./${"a".repeat(5_000)}.js`;
const expectedPath = `app/${declaredPath.slice(2)}`;
const files = fileMap([
file("app/consumer.js", "root"),
file(expectedPath, "root"),
]);
expect(
resolve({
declaredPath,
sourcePath: "app/consumer.js",
context: "module-specifier",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: expectedPath,
limitations: [],
});
});
});
describe("ESM module URL path decoding", () => {
it.each([
["./a%2eb.mjs", "app/esm/a.b.mjs"],
["./sub/%2e%2e/x.mjs", "app/esm/x.mjs"],
])(
"decodes confined URL path %s before artifact lookup",
(declaredPath, target) => {
expect(
resolve({
declaredPath,
sourcePath: "app/esm/entry.mjs",
context: "module-specifier",
moduleKind: "import",
files: fileMap([
file("app/esm/entry.mjs", "root"),
file("app/esm/a.b.mjs", "root"),
file("app/esm/x.mjs", "root"),
]),
}),
).toMatchObject({
resolved_path: target,
resolution_status: "resolved",
});
},
);
it("rejects encoded separators and paths escaping the artifact root", () => {
const files = fileMap([
file("app/esm/entry.mjs", "root"),
file("app/esm/x.mjs", "root"),
]);
for (const declaredPath of ["./sub%2fx.mjs", "../../../escape.mjs"]) {
expect(
resolve({
declaredPath,
sourcePath: "app/esm/entry.mjs",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({
resolved_path: null,
resolution_status: "rejected",
});
}
});
});
describe("JavaScript file URL resolution", () => {
it("resolves file URL paths without interpreting query bytes as path syntax", () => {
const files = fileMap([file("assets/app.js", "root")]);
for (const declaredPath of [
"file:///assets/app.js#entry",
"FILE:///assets/app.js?token=%2F#entry",
]) {
expect(
resolve({
declaredPath,
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({
declared_path: declaredPath,
resolution_status: "resolved",
resolved_path: "assets/app.js",
});
}
for (const declaredPath of [
"file:///assets%2Fapp.js",
"file:///assets%2\nFapp.js",
]) {
expect(
resolve({
declaredPath,
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({ resolution_status: "rejected", resolved_path: null });
}
expect(
resolve({
declaredPath: "file:/assets/app.js",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({ resolution_status: "external", resolved_path: null });
});
});
describe("contextual JavaScript package path resolution", () => {
it("follows package entrypoints beyond the former recursion ceiling", () => {
const files = fileMap([
file("app/consumer.js", "root"),
file(
"app/node_modules/pkg-1/package.json",
"root",
'{"main":"../pkg-2"}',
),
file(
"app/node_modules/pkg-2/package.json",
"root",
'{"main":"../pkg-3"}',
),
file(
"app/node_modules/pkg-3/package.json",
"root",
'{"main":"../pkg-4"}',
),
file(
"app/node_modules/pkg-4/package.json",
"root",
'{"main":"../pkg-5"}',
),
file(
"app/node_modules/pkg-5/package.json",
"root",
'{"main":"../pkg-6"}',
),
file(
"app/node_modules/pkg-6/package.json",
"root",
'{"main":"entry.js"}',
),
file("app/node_modules/pkg-6/entry.js", "root"),
]);
expect(
resolve({
declaredPath: "pkg-1",
sourcePath: "app/consumer.js",
context: "module-specifier",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/pkg-6/entry.js",
limitations: [],
});
});
it("keeps an inventoried but unreadable directory package unavailable", () => {
const files = fileMap([
file("app/package.json", "root"),
file("app/entry/package.json", "root", null),
]);
expect(
resolve({
declaredPath: "entry",
sourcePath: "app/package.json",
context: "package-entrypoint",
files,
}),
).toMatchObject({
resolution_status: "unavailable",
resolved_path: null,
limitations: [expect.stringContaining("text is unavailable")],
});
});
it("resolves nearest inventoried bare packages with import/require conditions", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
JSON.stringify({
exports: {
".": {
import: "./esm.mjs",
require: "./cjs.cjs",
default: "./fallback.js",
},
},
}),
),
file("app/node_modules/fixture/esm.mjs", "root"),
file("app/node_modules/fixture/cjs.cjs", "root"),
file("app/node_modules/fixture/fallback.js", "root"),
file("app/node_modules/fixture/hidden.js", "root"),
file("app/node_modules/fs/index.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture/esm.mjs",
});
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture/cjs.cjs",
});
expect(
resolve({
declaredPath: "fs",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({ resolution_status: "external", resolved_path: null });
expect(
resolve({
declaredPath: "fixture/hidden.js",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({
resolution_status: "external",
resolved_path: null,
limitations: [
expect.stringContaining("declares no exports target for subpath"),
],
});
});
});
describe("package exports subpath resolution", () => {
it("resolves exact subpath keys through import and require conditions", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
JSON.stringify({
exports: {
".": "./index.cjs",
"./parser": {
import: "./parser.mjs",
require: "./parser.cjs",
default: "./fallback.js",
},
},
}),
),
file("app/node_modules/fixture/index.cjs", "root"),
file("app/node_modules/fixture/parser.mjs", "root"),
file("app/node_modules/fixture/parser.cjs", "root"),
file("app/node_modules/fixture/fallback.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture/parser.mjs",
});
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture/parser.cjs",
});
});
it("resolves array subpath targets at their first string entry", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
JSON.stringify({
exports: {
"./parser": [{ import: "./parser.mjs" }, "./parser.cjs"],
},
}),
),
file("app/node_modules/fixture/parser.cjs", "root"),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture/parser.cjs",
});
});
it("resolves subpaths of scoped packages", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file(
"app/node_modules/@scope/fixture/package.json",
"root",
JSON.stringify({
exports: { "./parser": "./parser.cjs" },
}),
),
file("app/node_modules/@scope/fixture/parser.cjs", "root"),
]);
expect(
resolve({
declaredPath: "@scope/fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/@scope/fixture/parser.cjs",
});
});
});
describe("package exports subpath encapsulation", () => {
it("keeps subpaths encapsulated when only a root target is exported", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
JSON.stringify({ exports: "./index.cjs" }),
),
file("app/node_modules/fixture/index.cjs", "root"),
file("app/node_modules/fixture/parser.cjs", "root"),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "external",
resolved_path: null,
limitations: [expect.stringContaining("a root target only")],
});
});
it("blocks subpaths with an explicit null target", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
JSON.stringify({
exports: { ".": "./index.cjs", "./parser": null },
}),
),
file("app/node_modules/fixture/index.cjs", "root"),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "external",
resolved_path: null,
limitations: [expect.stringContaining("explicit null exports target")],
});
});
it("reports a missing selected subpath target without index fallback", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
JSON.stringify({
exports: { "./parser": "./parser.cjs" },
}),
),
file("app/node_modules/fixture/parser/index.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "not-found",
resolved_path: null,
limitations: [expect.stringContaining("exports targets are exact files")],
});
});
});
describe("package subpath directory ownership", () => {
it.each(["root", "other"])(
"selects metadata-less package directories only in the %s container",
(container) => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file("app/src/node_modules/fixture/parser.js", container),
file("app/node_modules/fixture/package.json", "root", "{}"),
file("app/node_modules/fixture/parser.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
declared_path: "fixture/parser",
resolution_context: "module-specifier",
resolution_status: "resolved",
resolved_path:
container === "root"
? "app/src/node_modules/fixture/parser.js"
: "app/node_modules/fixture/parser.js",
});
},
);
it("does not mistake a package-name file or sibling prefix for a nearer directory", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file("app/src/node_modules/fixture.js", "root"),
file("app/src/node_modules/fixture-extra/parser.js", "root"),
file("app/node_modules/fixture/parser.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolved_path: "app/node_modules/fixture/parser.js",
resolution_status: "resolved",
});
});
it.each([
["malformed", "{", "not valid package JSON"],
["unavailable", null, "text is unavailable"],
])("preserves %s nested directory failures", (_name, text, reason) => {
const files = fileMap([
file("app/consumer.js", "root"),
file("app/node_modules/fixture/package.json", "root", "{}"),
file("app/node_modules/fixture/parser/package.json", "root", text),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
declared_path: "fixture/parser",
resolution_context: "module-specifier",
resolved_path: null,
resolution_status: "unavailable",
limitations: [expect.stringContaining(reason)],
});
});
it("does not recurse through a cyclic nested main during CommonJS lookup", () => {
const files = fileMap([
file("app/consumer.js", "root"),
file("app/node_modules/fixture/package.json", "root", "{}"),
file(
"app/node_modules/fixture/parser/package.json",
"root",
'{"main":"."}',
),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "not-found",
resolved_path: null,
});
});
});
describe("package subpath legacy lookup and metadata failures", () => {
it("resolves CommonJS legacy subpath files and indexes without exports", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
'{"main":"./index.cjs"}',
),
file("app/node_modules/fixture/direct.js", "root"),
file("app/node_modules/fixture/explicit.cjs", "root"),
file("app/node_modules/fixture/folder/index.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture/direct",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture/direct.js",
});
expect(
resolve({
declaredPath: "fixture/explicit.cjs",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture/explicit.cjs",
});
expect(
resolve({
declaredPath: "fixture/folder",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/node_modules/fixture/folder/index.js",
});
});
it("rejects subpath metadata that mixes subpath and condition keys", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
JSON.stringify({
exports: { "./parser": "./parser.cjs", node: "./index.cjs" },
}),
),
file("app/node_modules/fixture/parser.cjs", "root"),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "rejected",
resolved_path: null,
limitations: [expect.stringContaining("mixes subpath keys")],
});
});
it("reports malformed subpath package metadata as unavailable", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file("app/node_modules/fixture/package.json", "root", "{"),
file("app/node_modules/fixture/parser.cjs", "root"),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "unavailable",
resolved_path: null,
limitations: [expect.stringContaining("not valid package JSON")],
});
});
it("reports unavailable metadata text for subpath resolution", () => {
const files = fileMap([
file("app/src/consumer.js", "root"),
file("app/node_modules/fixture/package.json", "root", null),
file("app/node_modules/fixture/parser.cjs", "root"),
]);
expect(
resolve({
declaredPath: "fixture/parser",
sourcePath: "app/src/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "unavailable",
resolved_path: null,
limitations: [expect.stringContaining("text is unavailable")],
});
});
});
describe("generic package entry heuristics", () => {
it.each([
['{"main":"actual.cjs","module":"bundler.mjs"}', "actual.cjs"],
['{"module":"bundler.mjs"}', "bundler.mjs"],
])(
"preserves generic entry heuristics without a module kind for %s",
(metadata, entry) => {
const files = fileMap([
file("app/consumer.js", "root"),
file("app/node_modules/fixture/package.json", "root", metadata),
file("app/node_modules/fixture/actual.cjs", "root"),
file("app/node_modules/fixture/bundler.mjs", "root"),
file("app/node_modules/fixture/index.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/consumer.js",
context: "module-specifier",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: `app/node_modules/fixture/${entry}`,
});
},
);
});
describe("package exports exact targets", () => {
it.each([
["./file", "app/node_modules/fixture/file.js"],
["./folder", "app/node_modules/fixture/folder/index.js"],
])(
"resolves exports target %s only to that exact file",
(target, nearMiss) => {
const files = fileMap([
file("app/consumer.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
JSON.stringify({ exports: target }),
),
file(nearMiss, "root"),
]);
for (const moduleKind of ["import", "require"] as const) {
const resolution = resolve({
declaredPath: "fixture",
sourcePath: "app/consumer.js",
context: "module-specifier",
moduleKind,
files,
});
expect(resolution).toMatchObject({
resolution_status: "not-found",
resolved_path: null,
});
expect(resolution.limitations.join(" ")).toContain(
"exports targets are exact files",
);
}
},
);
it("keeps extension and index fallbacks for a legacy main entry", () => {
for (const [main, target] of [
["./file", "app/node_modules/fixture/file.js"],
["./folder", "app/node_modules/fixture/folder/index.js"],
] as const) {
const files = fileMap([
file("app/consumer.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
JSON.stringify({ main }),
),
file(target, "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({ resolution_status: "resolved", resolved_path: target });
}
});
});
describe("package import alias resolution", () => {
it.each(["import", "require"] as const)(
"resolves an exact #%s alias from the enclosing package imports map",
(moduleKind) => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#config": "./config.cjs" },
}),
"main.js": "",
"config.cjs": "",
});
expect(
resolve({
declaredPath: "#config",
sourcePath: "main.js",
context: "module-specifier",
moduleKind,
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "config.cjs",
declared_path: "#config",
});
},
);
it("resolves an alias from a nested file through the enclosing package root", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#config": "./config.cjs" },
}),
"src/main.js": "",
"config.cjs": "",
});
expect(
resolve({
declaredPath: "#config",
sourcePath: "src/main.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "config.cjs",
});
});
it("keeps package import aliases available for runtime entrypoints", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#worker": "./worker.js" },
}),
"main.cjs": "",
"worker.js": "",
});
expect(
resolve({
declaredPath: "#worker",
sourcePath: "main.cjs",
context: "module-specifier",
files,
runtimePathKind: "exact-file",
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "worker.js",
declared_path: "#worker",
});
});
it("uses a nested package imports map rather than the application root", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#config": "./root.cjs" },
}),
"root.cjs": "",
"node_modules/fixture/package.json": JSON.stringify({
imports: { "#config": "./local.cjs" },
}),
"node_modules/fixture/index.js": "",
"node_modules/fixture/local.cjs": "",
});
expect(
resolve({
declaredPath: "#config",
sourcePath: "node_modules/fixture/index.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "node_modules/fixture/local.cjs",
});
});
it("does not inherit an ancestor imports map across a nested package.json", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#config": "./root.cjs" },
}),
"root.cjs": "",
"node_modules/fixture/package.json": "{}",
"node_modules/fixture/index.js": "",
});
const outcome = resolve({
declaredPath: "#config",
sourcePath: "node_modules/fixture/index.js",
context: "module-specifier",
moduleKind: "require",
files,
});
expect(outcome).toMatchObject({
resolution_status: "external",
resolved_path: null,
});
expect(outcome.limitations.join(" ")).toContain(
"node_modules/fixture/package.json",
);
expect(outcome.limitations.join(" ")).not.toContain("root.cjs");
});
it("does not apply a nested package map to the application root importer", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#config": "./root.cjs" },
}),
"main.js": "",
"root.cjs": "",
"node_modules/fixture/package.json": JSON.stringify({
imports: { "#config": "./local.cjs" },
}),
"node_modules/fixture/local.cjs": "",
});
expect(
resolve({
declaredPath: "#config",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "root.cjs",
});
});
});
describe("package import alias target selection", () => {
it("selects import and require conditions from an imports target", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: {
"#config": {
import: "./config.mjs",
require: "./config.cjs",
default: "./fallback.js",
},
},
}),
"main.js": "",
"config.mjs": "",
"config.cjs": "",
"fallback.js": "",
});
expect(
resolve({
declaredPath: "#config",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "import",
files,
}).resolved_path,
).toBe("config.mjs");
expect(
resolve({
declaredPath: "#config",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "require",
files,
}).resolved_path,
).toBe("config.cjs");
});
it("resolves array import targets at their first string entry", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#config": [{ import: "./missing.mjs" }, "./config.cjs"] },
}),
"main.js": "",
"config.cjs": "",
});
expect(
resolve({
declaredPath: "#config",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "config.cjs",
});
});
it("does not add an extension or index to a selected import target", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#config": "./config" },
}),
"main.js": "",
"config.cjs": "",
"config/index.js": "",
});
const outcome = resolve({
declaredPath: "#config",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "require",
files,
});
expect(outcome).toMatchObject({
resolution_status: "not-found",
resolved_path: null,
});
expect(outcome.limitations.join(" ")).toContain(
"import targets are exact files",
);
});
});
describe("package import alias refusals", () => {
it("reports a missing exact alias without looking in another package", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#config": "./config.cjs" },
}),
"main.js": "",
"config.cjs": "",
});
const outcome = resolve({
declaredPath: "#other",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "require",
files,
});
expect(outcome).toMatchObject({
resolution_status: "external",
resolved_path: null,
});
expect(outcome.limitations.join(" ")).toContain("#other");
expect(outcome.limitations.join(" ")).toContain("#config");
});
it("reports an explicit null import target as blocked", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#config": null },
}),
"main.js": "",
"config.cjs": "",
});
const outcome = resolve({
declaredPath: "#config",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "require",
files,
});
expect(outcome).toMatchObject({
resolution_status: "external",
resolved_path: null,
});
expect(outcome.limitations.join(" ")).toContain("explicit null");
});
it("leaves wildcard import aliases unresolved", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#internal/*": "./src/*.js" },
}),
"main.js": "",
"src/util.js": "",
});
const outcome = resolve({
declaredPath: "#internal/util",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "import",
files,
});
expect(outcome).toMatchObject({
resolution_status: "external",
resolved_path: null,
});
expect(outcome.limitations.join(" ")).toMatch(/wildcard/i);
});
it("leaves recursive and external-package import targets unresolved", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#loop": "#config", "#dep": "fixture" },
}),
"main.js": "",
"node_modules/fixture/index.js": "",
});
const recursive = resolve({
declaredPath: "#loop",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "require",
files,
});
const external = resolve({
declaredPath: "#dep",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "require",
files,
});
expect(recursive).toMatchObject({
resolution_status: "external",
resolved_path: null,
});
expect(recursive.limitations.join(" ")).toMatch(/recursive/i);
expect(external).toMatchObject({
resolution_status: "external",
resolved_path: null,
});
expect(external.limitations.join(" ")).toMatch(/external-package/i);
});
it("rejects reserved hash specifiers", () => {
const files = aliasFiles({
"package.json": JSON.stringify({
imports: { "#config": "./config.cjs" },
}),
"main.js": "",
"config.cjs": "",
});
expect(
resolve({
declaredPath: "#",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({ resolution_status: "rejected", resolved_path: null });
});
it("does not use a foreign-container enclosing package.json", () => {
const files = fileMap([
file(
"package.json",
"other",
JSON.stringify({ imports: { "#config": "./config.cjs" } }),
),
file("main.js", "root"),
file("config.cjs", "root"),
]);
const outcome = resolve({
declaredPath: "#config",
sourcePath: "main.js",
context: "module-specifier",
moduleKind: "require",
files,
});
expect(outcome).toMatchObject({
resolution_status: "external",
resolved_path: null,
});
expect(outcome.limitations.join(" ")).toContain("package scopes");
});
});
describe("directory package entrypoint precedence", () => {
it.each([
["require", '{"main":"actual.cjs"}', "actual.cjs"],
["require", '{"exports":{"require":"./actual.cjs"}}', "actual.cjs"],
["import", '{"exports":{"import":"./actual.mjs"}}', "actual.mjs"],
] as const)(
"prefers declared %s entrypoints over index files",
(moduleKind, metadata, entry) => {
const files = fileMap([
file("app/consumer.js", "root"),
file("app/node_modules/fixture/package.json", "root", metadata),
file(`app/node_modules/fixture/${entry}`, "root"),
file("app/node_modules/fixture/index.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/consumer.js",
context: "module-specifier",
moduleKind,
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: `app/node_modules/fixture/${entry}`,
});
},
);
it.each(["{}", '{"main":"."}'])(
"preserves index fallback for package metadata %s",
(metadata) => {
const files = fileMap([
file("app/consumer.js", "root"),
file("app/entry/package.json", "root", metadata),
file("app/entry/index.js", "root"),
]);
expect(
resolve({
declaredPath: "./entry",
sourcePath: "app/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/entry/index.js",
});
},
);
it.each([null, "{"])(
"keeps unreadable or invalid metadata explicit even when an index exists",
(metadata) => {
const files = fileMap([
file("app/consumer.js", "root"),
file("app/entry/package.json", "root", metadata),
file("app/entry/index.js", "root"),
]);
expect(
resolve({
declaredPath: "./entry",
sourcePath: "app/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "unavailable",
resolved_path: null,
});
},
);
it("does not replace a missing exports target with an index", () => {
const files = fileMap([
file("app/consumer.js", "root"),
file(
"app/node_modules/fixture/package.json",
"root",
'{"exports":"./missing.js"}',
),
file("app/node_modules/fixture/index.js", "root"),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "app/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "not-found",
resolved_path: null,
});
});
it("keeps direct files ahead of a relative directory package", () => {
const files = fileMap([
file("app/consumer.js", "root"),
file("app/entry.js", "root"),
file("app/entry/package.json", "root", '{"main":"actual.js"}'),
file("app/entry/actual.js", "root"),
file("app/entry/index.js", "root"),
]);
expect(
resolve({
declaredPath: "./entry",
sourcePath: "app/consumer.js",
context: "module-specifier",
moduleKind: "require",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/entry.js",
});
});
it("retains cycle diagnostics for generic package-entrypoint inference", () => {
const files = fileMap([
file("app/package.json", "root"),
file("app/a/package.json", "root", '{"main":"../b"}'),
file("app/b/package.json", "root", '{"main":"../a"}'),
]);
expect(
resolve({
declaredPath: "./a",
sourcePath: "app/package.json",
context: "package-entrypoint",
files,
}),
).toMatchObject({
resolution_status: "unavailable",
resolved_path: null,
limitations: [expect.stringContaining("cycle")],
});
});
});
describe("contextual JavaScript module identity", () => {
it("retains CommonJS and ESM file-base identity during inert extraction", () => {
const analysis = analyzeJavaScriptStaticSource(
`
import { BrowserWindow } from "electron";
new BrowserWindow({ webPreferences: {
preload: path.resolve("ignored", __dirname, "preload.cjs")
}});
new BrowserWindow({ webPreferences: {
preload: fileURLToPath(new URL("./preload.mjs", import.meta.url))
}});
new BrowserWindow({ webPreferences: {
preload: path.join(path.dirname(__filename), "legacy-preload.js")
}});
new BrowserWindow({ webPreferences: {
preload: path.posix.resolve("/ignored", dirname(fileURLToPath(import.meta.url)), "esm-preload.js")
}});
new BrowserWindow({ webPreferences: {
preload: path.posix.resolve(__dirname, "/shared", "absolute-preload.js/")
}});
new BrowserWindow({ webPreferences: {
preload: path.posix.resolve(\`/templates\`, "template-preload.js")
}});
new BrowserWindow({ webPreferences: {
preload: new URL("./remote-base.js", location.href)
}});
window.loadURL("file:///renderer/index.html");
`,
);
expect(analysis.role_paths).toEqual(
expect.arrayContaining([
expect.objectContaining({
path: "preload.cjs",
resolution_context: "filesystem-expression",
}),
expect.objectContaining({
path: "./preload.mjs",
resolution_context: "filesystem-expression",
}),
expect.objectContaining({
path: "legacy-preload.js",
resolution_context: "filesystem-expression",
}),
expect.objectContaining({
path: "esm-preload.js",
resolution_context: "filesystem-expression",
}),
expect.objectContaining({
path: "/shared/absolute-preload.js",
resolution_context: "filesystem-expression",
}),
expect.objectContaining({
path: "/templates/template-preload.js",
resolution_context: "filesystem-expression",
}),
expect.objectContaining({
path: "file:///renderer/index.html",
resolution_context: "module-specifier",
}),
]),
);
expect(analysis.electron.browser_windows).toEqual(
expect.arrayContaining([
expect.objectContaining({
preload_path: "preload.cjs",
preload_resolution_context: "filesystem-expression",
}),
expect.objectContaining({
preload_path: "./preload.mjs",
preload_resolution_context: "filesystem-expression",
}),
expect.objectContaining({
preload_path: "esm-preload.js",
preload_resolution_context: "filesystem-expression",
}),
expect.objectContaining({
preload_path: "/shared/absolute-preload.js",
preload_resolution_context: "filesystem-expression",
}),
expect.objectContaining({
preload_path: "/templates/template-preload.js",
preload_resolution_context: "filesystem-expression",
}),
]),
);
expect(analysis.role_paths).not.toEqual(
expect.arrayContaining([
expect.objectContaining({ path: "./remote-base.js" }),
]),
);
});
});
describe("TypeScript NodeNext emitted-extension resolution", () => {
const container = "container";
it.each([
["./dep.js", "src/dep.ts"],
["./ui/Button.js", "src/ui/Button.tsx"],
["./cfg.mjs", "src/cfg.mts"],
["./legacy.cjs", "src/legacy.cts"],
] as const)(
"resolves %s to its TypeScript source counterpart",
(specifier, target) => {
const files = fileMap([
file("src/main.ts", container),
file(target, container, "export const value = 1;"),
]);
expect(
resolve({
declaredPath: specifier,
sourcePath: "src/main.ts",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({ resolution_status: "resolved", resolved_path: target });
},
);
});
describe("TypeScript declaration fallback ownership", () => {
const container = "container";
it.each([
["./dep.js", "src/dep.d.ts"],
["./cfg.mjs", "src/cfg.d.mts"],
["./legacy.cjs", "src/legacy.d.cts"],
] as const)(
"retains %s as compile-time evidence without inventing a runtime target",
(specifier, target) => {
const files = fileMap([
file("src/main.ts", container),
file(target, container, "export const value = 1;"),
]);
for (const moduleKind of ["import", "require"] as const) {
expect(
resolve({
declaredPath: specifier,
sourcePath: "src/main.ts",
context: "module-specifier",
moduleKind,
files,
}),
).toMatchObject({
resolution_status: "unavailable",
resolved_path: null,
candidate_path: target,
});
}
expect(
resolve({
declaredPath: "./" + target.slice(4),
sourcePath: "src/main.ts",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({ resolution_status: "resolved", resolved_path: target });
},
);
it("prefers a present runtime file and keeps the fallback off for JS callers", () => {
const files = fileMap([
file("src/main.ts", container),
file("src/dep.js", container),
file("src/dep.ts", container),
file("src/js-main.js", container),
]);
expect(
resolve({
declaredPath: "./dep.js",
sourcePath: "src/main.ts",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "src/dep.js",
});
expect(
resolve({
declaredPath: "./dep.js",
sourcePath: "src/js-main.js",
context: "module-specifier",
moduleKind: "import",
files: fileMap([
file("src/js-main.js", container),
file("src/dep.ts", container),
]),
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
});
it("does not apply the mapping to URL resources or package export targets", () => {
const urlFiles = fileMap([
file("src/main.ts", container),
file("src/asset.ts", container),
]);
expect(
resolve({
declaredPath: "asset.js",
sourcePath: "src/main.ts",
context: "url-reference",
files: urlFiles,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
const packageFiles = fileMap([
file("src/main.ts", container),
file(
"src/node_modules/fixture/package.json",
container,
'{"exports":"./dep.js"}',
),
file("src/node_modules/fixture/dep.ts", container),
]);
expect(
resolve({
declaredPath: "fixture",
sourcePath: "src/main.ts",
context: "module-specifier",
moduleKind: "import",
files: packageFiles,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
});
it("does not substitute source counterparts for directory or index resolution", () => {
const files = fileMap([
file("src/main.ts", container),
file("src/lib/index.ts", container),
]);
expect(
resolve({
declaredPath: "./lib.js",
sourcePath: "src/main.ts",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
});
it("resolves an emitted dotfile name within its own directory", () => {
const files = fileMap([
file("src/main.ts", container),
file("src/.ts", container),
]);
expect(
resolve({
declaredPath: "./.js",
sourcePath: "src/main.ts",
context: "module-specifier",
moduleKind: "import",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "src/.ts",
});
});
});
describe("url-reference directory and empty-segment semantics", () => {
it.each([
"./worker.js/.",
"./worker.js/child/..",
"./worker.js/",
"/dist/worker.js/.",
"./worker.js/.?cache=1#entry",
])("keeps directory-form URLs distinct from files: %s", (declaredPath) => {
expect(
resolve({
declaredPath,
sourcePath: "dist/app.mjs",
context: "url-reference",
files: fileMap([file("dist/worker.js", "root")]),
}),
).toMatchObject({
declared_path: declaredPath,
resolution_status: "not-found",
resolved_path: null,
});
});
it.each(["./nested//worker.js", "./nested//../worker.js"])(
"does not collapse empty URL path segments: %s",
(declaredPath) => {
expect(
resolve({
declaredPath,
sourcePath: "dist/app.mjs",
context: "url-reference",
files: fileMap([
file("dist/worker.js", "root"),
file("dist/nested/worker.js", "root"),
]),
}),
).toMatchObject({ resolved_path: null });
},
);
it.each([
["./nested/.././worker.js?cache=1#entry", "dist/worker.js"],
["./.worker.js", "dist/.worker.js"],
])("resolves exact file URLs with dots: %s", (declaredPath, resolvedPath) => {
expect(
resolve({
declaredPath,
sourcePath: "dist/app.mjs",
context: "url-reference",
files: fileMap([file(resolvedPath, "root")]),
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: resolvedPath,
});
});
});
describe("suffix-only non-runtime URL references", () => {
it.each(["", "?cache=1", "#worker"])(
"rejects URL reference %s without a path or known base document",
(declaredPath) => {
expect(
resolve({
declaredPath,
sourcePath: "dist/app.mjs",
context: "url-reference",
files: fileMap([file("dist/app.mjs", "root")]),
}),
).toMatchObject({
declared_path: declaredPath,
resolution_status: "rejected",
resolved_path: null,
});
},
);
});
describe("url-reference JavaScript artifact path resolution", () => {
it.each([
["C|?cache=1#entry", "dist/C|"],
["/c:/worker.js", "c:/worker.js"],
["/./c|/worker.js", "c|/worker.js"],
["../c|/worker.js", "c|/worker.js"],
["/nested/../c|/worker.js", "c|/worker.js"],
["c|/../worker.js", "dist/worker.js"],
])("leaves drive-letter URL paths unresolved: %s", (declaredPath, decoy) => {
const resolution = resolve({
declaredPath,
sourcePath: "dist/app.mjs",
context: "url-reference",
files: fileMap([file(decoy, "root")]),
});
expect(resolution).toMatchObject({
declared_path: declaredPath,
resolution_status: "unavailable",
resolved_path: null,
});
expect(resolution.limitations.length).toBeGreaterThan(0);
});
it.each([
["./c|/worker.js", "dist/c|/worker.js"],
["c|name/worker.js", "dist/c|name/worker.js"],
["/%63|/worker.js", "c|/worker.js"],
["/c%3A/worker.js", "c:/worker.js"],
])(
"retains non-drive URL path identities: %s",
(declaredPath, resolvedPath) => {
expect(
resolve({
declaredPath,
sourcePath: "dist/app.mjs",
context: "url-reference",
files: fileMap([file(resolvedPath, "root")]),
}),
).toMatchObject({
declared_path: declaredPath,
resolution_status: "resolved",
resolved_path: resolvedPath,
});
},
);
it.each(["?value=", "#value="])(
"admits the pathname independently of its %s suffix",
(suffix) => {
for (const value of ["%2F", "%2E", "%5C", "%00", "%FF", "\\", "\0"]) {
const declaredPath = `./worker.js${suffix}${value}`;
expect(
resolve({
declaredPath,
sourcePath: "dist/app.js",
context: "url-reference",
files: fileMap([file("dist/worker.js", "root")]),
}),
declaredPath,
).toMatchObject({
declared_path: declaredPath,
resolution_status: "resolved",
resolved_path: "dist/worker.js",
});
}
},
);
it.each([
"app\0.js.map?valid=1",
"nested\\worker.js#valid",
"app%00.js.map",
"app%FF.js.map",
"app%C0%AF.js.map",
"app%2ejs.map",
"nested%2fworker.js",
"nested%5cworker.js",
"h\nttp://[",
"../../outside.js.map",
"../../outside/.",
])("rejects an inadmissible URL path: %s", (declaredPath) => {
const resolution = resolve({
declaredPath,
sourcePath: "dist/app.js",
context: "url-reference",
files: fileMap([
file("dist/app.js.map", "root"),
file("dist/nested/worker.js", "root"),
]),
});
expect(resolution).toMatchObject({
declared_path: declaredPath,
resolution_context: "url-reference",
resolution_status: "rejected",
resolved_path: null,
});
expect(resolution.limitations.length).toBeGreaterThan(0);
});
it("resolves sibling paths and rejects external URL forms", () => {
const files = fileMap([
file("dist/app.js", "root"),
file("dist/app.js.map", "root"),
file("dist/worker.js", "root"),
]);
expect(
resolve({
declaredPath: "app.js.map",
sourcePath: "dist/app.js",
context: "url-reference",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "dist/app.js.map",
});
expect(
resolve({
declaredPath: "app.js.map?v=1#section",
sourcePath: "dist/app.js",
context: "url-reference",
files,
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "dist/app.js.map",
});
expect(
resolve({
declaredPath: "//cdn.example.com/app.js.map",
sourcePath: "dist/app.js",
context: "url-reference",
files,
}),
).toMatchObject({
resolution_status: "external",
resolved_path: null,
});
expect(
resolve({
declaredPath: "https://cdn.example.com/app.js.map",
sourcePath: "dist/app.js",
context: "url-reference",
files,
}),
).toMatchObject({
resolution_status: "external",
resolved_path: null,
});
});
});
const resolve = (input: ResolveArtifactPathInput) =>
resolveArtifactPathByContext(input);
const fileMap = (files: readonly JavaScriptArtifactFile[]) =>
new Map(files.map((value) => [value.path, value]));
const file = (
path: string,
container: string,
text: string | null = "",
): JavaScriptArtifactFile => ({
path,
container_sha256: container.padEnd(64, "0").slice(0, 64),
sha256: path.padEnd(64, "0").slice(0, 64),
bytes: text?.length ?? 0,
inventory_artifact_id: `artifact-${path}`,
kind: path.endsWith("package.json") ? "package-json" : "javascript",
unpacked: false,
text:
text === null
? { included: false, reason: "invalid-utf8" }
: { included: true, value: text },
});
const aliasFiles = (
entries: Readonly<Record<string, string | null>>,
): ReturnType<typeof fileMap> =>
fileMap(
Object.entries(entries).map(([path, text]) =>
file(path, "root", text ?? ""),
),
);
describe("exact HTML resource resolution", () => {
it.each([
["extension", ["app.js"]],
["directory index", ["app/index.js"]],
["directory package", ["app/package.json", "app/entry.js"]],
] as const)("does not infer a file from %s fallback", (_name, paths) => {
const files = fileMap([
file("index.html", "root"),
...paths.map((path) =>
file(
path,
"root",
path.endsWith("package.json") ? '{"main":"entry.js"}' : "",
),
),
]);
expect(
resolve({
declaredPath: "./app",
sourcePath: "index.html",
context: "html-reference",
files,
}),
).toMatchObject({ resolution_status: "not-found", resolved_path: null });
});
it("prefers an exact extensionless resource and retains URL suffix handling", () => {
const files = fileMap([
file("renderer/index.html", "root"),
file("assets/app", "root"),
file("assets/app.js", "root"),
file("assets/app/index.js", "root"),
]);
expect(
resolve({
declaredPath: "./app?cache=1#v2",
sourcePath: "renderer/index.html",
context: "html-reference",
htmlBaseHref: "/assets/",
files,
}),
).toMatchObject({
declared_path: "./app?cache=1#v2",
resolution_status: "resolved",
resolved_path: "assets/app",
});
});
});
it.each(["require", "import"] as const)(
"rejects a literal trailing backslash package main before %s probing",
(moduleKind) => {
const files = fileMap([
file("entry.js", "root"),
file(
"node_modules/p/package.json",
"root",
JSON.stringify({ main: "lib\\" }),
),
file("node_modules/p/lib", "root"),
]);
expect(
resolve({
declaredPath: "p",
sourcePath: "entry.js",
context: "module-specifier",
moduleKind,
files,
}),
).toMatchObject({ resolution_status: "rejected", resolved_path: null });
},
);
describe("exact Electron runtime entrypoint resolution", () => {
it("requires a protocol for Electron URL resources", () => {
const files = fileMap([
file("app/main.cjs", "root"),
file("app/renderer", "root"),
file("app/renderer.js", "root"),
]);
expect(
resolve({
declaredPath: "./renderer",
sourcePath: "app/main.cjs",
context: "module-specifier",
files,
runtimePathKind: "url-resource",
}),
).toMatchObject({
resolution_status: "unavailable",
resolved_path: null,
limitations: [expect.stringContaining("requires a URL protocol")],
});
expect(
resolve({
declaredPath: "file:///app/renderer",
sourcePath: "app/main.cjs",
context: "module-specifier",
files,
runtimePathKind: "url-resource",
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/renderer",
});
});
it("checks local paths exactly while preserving bare package lookup", () => {
const files = fileMap([
file("app/main.cjs", "root"),
file("app/worker.js", "root"),
file("app/worker", "root"),
file("app/worker#v1.js", "root"),
file(
"node_modules/exported/package.json",
"root",
'{"exports":{"./parser":"./parser.cjs"}}',
),
file("node_modules/exported/parser.cjs", "root"),
file("app/fallback/index.js", "root"),
]);
expect(
resolve({
declaredPath: "./worker.js",
sourcePath: "app/main.cjs",
context: "module-specifier",
files,
runtimePathKind: "exact-file",
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/worker.js",
});
expect(
resolve({
declaredPath: "exported/parser",
sourcePath: "app/main.cjs",
context: "module-specifier",
files,
runtimePathKind: "exact-file",
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "node_modules/exported/parser.cjs",
});
expect(
resolve({
declaredPath: "./worker#v1.js",
sourcePath: "app/main.cjs",
context: "module-specifier",
files,
runtimePathKind: "exact-file",
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/worker#v1.js",
});
expect(
resolve({
declaredPath: "./fallback",
sourcePath: "app/main.cjs",
context: "module-specifier",
files,
runtimePathKind: "exact-file",
}),
).toMatchObject({
resolution_status: "not-found",
resolved_path: null,
});
});
it("accepts an exact extensionless file but not a directory index", () => {
const files = fileMap([
file("app/main.cjs", "root"),
file("app/preload", "root"),
file("app/preload.js", "root"),
file("app/fallback/index.js", "root"),
]);
expect(
resolve({
declaredPath: "./preload",
sourcePath: "app/main.cjs",
context: "module-specifier",
files,
runtimePathKind: "exact-file",
}),
).toMatchObject({
resolution_status: "resolved",
resolved_path: "app/preload",
});
expect(
resolve({
declaredPath: "./fallback",
sourcePath: "app/main.cjs",
context: "module-specifier",
files,
runtimePathKind: "exact-file",
}),
).toMatchObject({
resolution_status: "not-found",
resolved_path: null,
});
});
});
it.each(["#home", "?theme=dark", ""])(
"does not invent a document base for runtime URL %s",
(declaredPath) => {
expect(
resolve({
declaredPath,
sourcePath: "main.cjs",
context: "url-reference",
runtimePathKind: "url-resource",
files: fileMap([file("main.cjs", "root")]),
}),
).toMatchObject({
declared_path: declaredPath,
resolution_status: "unavailable",
resolved_path: null,
});
},
);
it("resolves Node runtime entrypoints without substituting emitted TypeScript sources", () => {
const files = fileMap([
file("main.ts", "root"),
file("worker.ts", "root"),
file("worker.js", "other-container"),
file("runtime.js", "root"),
file("directory/index.js", "root"),
]);
for (const [declaredPath, status, path, candidatePath] of [
["./worker.js", "not-found", null, "worker.js"],
["./runtime", "resolved", "runtime.js", undefined],
["./directory", "resolved", "directory/index.js", undefined],
] as const)
expect(
resolve({
declaredPath,
sourcePath: "main.ts",
context: "module-specifier",
files,
runtimePathKind: "node-entrypoint",
}),
).toMatchObject({
resolution_status: status,
resolved_path: path,
...(candidatePath === undefined ? {} : { candidate_path: candidatePath }),
});
});