fix(artifacts): never treat a directory named *.map as a source map (#4131)
Artifact inventory decided source-map edges from the `.map` path suffix, so an archive directory such as `main.js.map/` received a maps-source edge whose parent was the sibling `main.js`, although the same occurrence was classified as a directory container. Edge construction now uses the occurrence's own artifact_kind, and the duplicate suffix rule in relationFor is removed; such directories are contained by their parent, and real source-map files keep maps-source. Fixes #3909 Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a90c9eac6a
commit
9d6651e5b5
2 files changed
+47
-9
No files matched your search
@@ -121,6 +121,43 @@ describe("source-map artifact relationships", () => {
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it("keeps a directory named like a source map contained by its parent", () => {
|
||||
const archive = createOccurrence(entry("app", "directory"), "app", null);
|
||||
archive.artifact_id = contentId("1");
|
||||
const script = createOccurrence(
|
||||
entry("app/main.js", "file"),
|
||||
"app/main.js",
|
||||
archive.occurrence_id,
|
||||
);
|
||||
script.artifact_id = contentId("2");
|
||||
const directory = createOccurrence(
|
||||
entry("app/main.js.map", "directory"),
|
||||
"app/main.js.map",
|
||||
archive.occurrence_id,
|
||||
);
|
||||
directory.artifact_id = contentId("3");
|
||||
|
||||
const { edges, limitations } = createArtifactEdges(contentId("4"), [
|
||||
archive,
|
||||
script,
|
||||
directory,
|
||||
]);
|
||||
|
||||
expect(directory).toMatchObject({
|
||||
artifact_kind: "container",
|
||||
artifact_format: "directory",
|
||||
});
|
||||
expect(
|
||||
edges.find(
|
||||
({ occurrence_id }) => occurrence_id === directory.occurrence_id,
|
||||
),
|
||||
).toMatchObject({
|
||||
relation: "contains",
|
||||
parent_artifact_id: contentId("1"),
|
||||
});
|
||||
expect(limitations).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
const fat = (wide = false): Buffer =>
|
||||
|
||||
@@ -295,7 +295,9 @@ export const createArtifactEdges = (
|
||||
const edges: ArtifactEdge[] = [];
|
||||
const limitations: string[] = [];
|
||||
for (const occurrence of occurrences) {
|
||||
const isSourceMap = occurrence.logical_path.toLowerCase().endsWith(".map");
|
||||
// Use the occurrence's own classification: a directory named `x.map` is
|
||||
// a container, not a source map of its sibling.
|
||||
const isSourceMap = occurrence.artifact_kind === "source-map";
|
||||
const sourcePath = isSourceMap
|
||||
? occurrence.logical_path.slice(0, -".map".length)
|
||||
: undefined;
|
||||
@@ -337,8 +339,10 @@ export const createArtifactEdges = (
|
||||
relation:
|
||||
occurrence.entry_kind === "slice"
|
||||
? ("slice-of" as const)
|
||||
: isSourceMap && mappedSource === undefined
|
||||
? ("contains" as const)
|
||||
: isSourceMap
|
||||
? mappedSource === undefined
|
||||
? ("contains" as const)
|
||||
: ("maps-source" as const)
|
||||
: relationFor(occurrence.logical_path),
|
||||
occurrence_id: occurrence.occurrence_id,
|
||||
};
|
||||
@@ -587,11 +591,8 @@ const classifyFatArtifact = (
|
||||
return identity.state === "mach-o" ? "mach-o-universal" : "unknown";
|
||||
};
|
||||
|
||||
const relationFor = (path: string): ArtifactEdge["relation"] => {
|
||||
const lower = path.toLowerCase();
|
||||
if (lower.endsWith(".map")) return "maps-source";
|
||||
if (lower.includes(".framework/")) return "embeds";
|
||||
return "contains";
|
||||
};
|
||||
/** Relation of a non-source-map occurrence to its parent. */
|
||||
const relationFor = (path: string): ArtifactEdge["relation"] =>
|
||||
path.toLowerCase().includes(".framework/") ? "embeds" : "contains";
|
||||
|
||||
const depth = (path: string): number => path.split("/").length;
|
||||
Reference in new issue
Block a user