refactor(domain): extract artifact path syntax helpers (#830)

Move hasScheme/stripQueryAndFragment/admitsCanonicalPathSyntax
plus looksExternal into domain/artifactPathSyntax with the
deliberate policy-divergence table (artifact root vs allowedOrigins
vs exact-origin fetch). Adopt in JavaScriptArtifactPathResolution
and the Electron native specifier check with characterization
tests. Policy unification tracked in #829.
This commit is contained in:
morluto authored and GitHub committed 2026-10-07 11:28:28 +08:00
1 parent 64ebdf4501
commit ef535b81fe
4 files changed
+89 -21

No files matched your search

@@ -2,6 +2,12 @@ import { builtinModules } from "node:module";
import { posix } from "node:path";
import type { JavaScriptArtifactFile } from "./JavaScriptArtifactFiles.js";
import {
admitsCanonicalPathSyntax,
hasScheme,
looksExternal,
stripQueryAndFragment,
} from "../domain/artifactPathSyntax.js";
type ArtifactPathResolutionContext =
| "package-entrypoint"
@@ -115,12 +121,6 @@ const rejectDeclaration = (
return null;
};
/** Path syntax admitted for a canonical artifact path. */
const admitsCanonicalPathSyntax = (value: string): boolean =>
!value.includes("\0") &&
!value.includes("\\") &&
!/%(?:2e|2f|5c)/iu.test(value);
const contextualCandidate = (
input: ResolveArtifactPathInput,
): string | ArtifactPathResolution => {
@@ -212,7 +212,7 @@ const htmlCandidate = (
input: ResolveArtifactPathInput,
): string | ArtifactPathResolution => {
const declared = stripQueryAndFragment(input.declaredPath);
if (hasScheme(declared) || declared.startsWith("//"))
if (looksExternal(declared))
return unresolvedOutcome(input, "external", [
"External HTML references are not mapped to local artifact assets.",
]);
@@ -221,11 +221,7 @@ const htmlCandidate = (
rawBase === undefined || rawBase === null
? rawBase
: stripQueryAndFragment(rawBase);
if (
base !== undefined &&
base !== null &&
(hasScheme(base) || base.startsWith("//"))
)
if (base !== undefined && base !== null && looksExternal(base))
return unresolvedOutcome(input, "external", [
"The document base href is external, so its script reference is not a local artifact path.",
]);
@@ -538,9 +534,6 @@ const notFoundCandidate = (): CandidateResolution => ({
],
});
const hasScheme = (value: string): boolean =>
/^[A-Za-z][A-Za-z+.-]*:/u.test(value);
const fileUrlPath = (value: string): string | undefined => {
if (!value.startsWith("file://")) return undefined;
try {
@@ -554,9 +547,6 @@ const fileUrlPath = (value: string): string | undefined => {
}
};
const stripQueryAndFragment = (value: string): string =>
value.split("#", 1)[0]?.split("?", 1)[0] ?? "";
const outcome = (
input: ResolveArtifactPathInput,
resolution: CandidateResolution,