mirror of
https://github.com/morluto/rea
synced 2026-10-26 14:25:49 -04:00
refactor(javascript): reuse validated source-map decoding
Pass typed map objects into the codec and reuse validated TraceMap instances for regular and indexed lookups. Remove whole-map serialization, duplicate leaf decoding, an array-copy wrapper, and the unused offset-validation mode in artifact declaration collection. Validation: source-map and browser consumer suites (126 tests), declaration tests, and artifact reconstruction boundaries pass. Section overlap checks and raw source declarations remain intact.
This commit is contained in:
@@ -51,12 +51,13 @@ export const decodeValidatedSourceMapLeaves = (
|
||||
check?: () => void,
|
||||
): readonly {
|
||||
readonly leaf: SourceMapLeaf;
|
||||
readonly map: TraceMap;
|
||||
readonly rows: ReturnType<typeof decodedMappings>;
|
||||
readonly resolvedSources: readonly string[];
|
||||
}[] =>
|
||||
leaves.map((leaf) => {
|
||||
check?.();
|
||||
const map = new TraceMap(JSON.stringify(leaf.map), mapUrl);
|
||||
const map = new TraceMap(leaf.codecMap, mapUrl);
|
||||
const rows = decodedMappings(map);
|
||||
for (const [line, row] of rows.entries()) {
|
||||
if ((line & 255) === 0) check?.();
|
||||
@@ -78,5 +79,5 @@ export const decodeValidatedSourceMapLeaves = (
|
||||
);
|
||||
}
|
||||
}
|
||||
return { leaf, rows, resolvedSources: map.resolvedSources };
|
||||
return { leaf, map, rows, resolvedSources: map.resolvedSources };
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import { z } from "zod";
|
||||
import { WEB_SOURCE_MAP_LIMITS } from "../../domain/webSourceLocation.js";
|
||||
import { hasValidSourceMapContents } from "../../domain/sourceMapContents.js";
|
||||
import { sourceMapJsonText } from "../../domain/sourceMapEnvelope.js";
|
||||
import type { EncodedSourceMapXInput } from "@jridgewell/trace-mapping";
|
||||
|
||||
const leafSchema = z.object({
|
||||
version: z.literal(3),
|
||||
@@ -74,10 +75,27 @@ export interface SourceMapSourceDeclaration {
|
||||
/** Validated leaf with absolute first-line offsets and its enclosing section boundary. */
|
||||
export interface SourceMapLeaf {
|
||||
readonly map: z.output<typeof leafSchema>;
|
||||
readonly codecMap: EncodedSourceMapXInput;
|
||||
readonly offset: Offset;
|
||||
readonly stop: Offset | null;
|
||||
}
|
||||
|
||||
const codecLeaf = (
|
||||
map: z.output<typeof leafSchema>,
|
||||
): EncodedSourceMapXInput => ({
|
||||
version: 3,
|
||||
...(map.file === undefined ? {} : { file: map.file }),
|
||||
...(typeof map.sourceRoot === "string" ? { sourceRoot: map.sourceRoot } : {}),
|
||||
sources: map.sources,
|
||||
...(map.sourcesContent == null ? {} : { sourcesContent: map.sourcesContent }),
|
||||
names: map.names,
|
||||
mappings: map.mappings,
|
||||
...(map.ignoreList === undefined ? {} : { ignoreList: map.ignoreList }),
|
||||
...(map.x_google_ignoreList === undefined
|
||||
? {}
|
||||
: { x_google_ignoreList: map.x_google_ignoreList }),
|
||||
});
|
||||
|
||||
const compare = (a: Offset, b: Offset): number =>
|
||||
a.line - b.line || a.column - b.column;
|
||||
const addOffset = (base: Offset, offset: Offset): Offset => {
|
||||
@@ -283,30 +301,10 @@ const inspectLeaf = (
|
||||
/** Validate structure before allocation, retaining raw declarations and section boundaries. */
|
||||
export const inspectSourceMap = (
|
||||
text: string,
|
||||
): {
|
||||
readonly jsonText: string;
|
||||
readonly format: "regular" | "indexed";
|
||||
readonly reportedFile: string | null;
|
||||
readonly declarations: readonly SourceMapSourceDeclaration[];
|
||||
readonly leaves: readonly SourceMapLeaf[];
|
||||
} => {
|
||||
): ReturnType<typeof inspectSourceMapValue> => {
|
||||
const jsonText = sourceMapJsonText(text);
|
||||
const value: unknown = JSON.parse(jsonText);
|
||||
const inspected = inspectSourceMapValue(value);
|
||||
const normalized =
|
||||
inspected.format === "regular"
|
||||
? inspected.leaves[0]?.map
|
||||
: {
|
||||
version: 3,
|
||||
sections: inspected.leaves.map((leaf) => ({
|
||||
offset: leaf.offset,
|
||||
map: leaf.map,
|
||||
})),
|
||||
};
|
||||
return {
|
||||
jsonText: JSON.stringify(normalized),
|
||||
...inspected,
|
||||
};
|
||||
return inspectSourceMapValue(value);
|
||||
};
|
||||
|
||||
/** Return validated leaves when a consumer needs decoded rows after preflight. */
|
||||
@@ -341,7 +339,12 @@ export const inspectSourceMapValue = (
|
||||
continue;
|
||||
}
|
||||
const leaf = inspectLeaf(node, budget, options);
|
||||
leaves.push({ map: leaf, offset: node.offset, stop: node.stop });
|
||||
leaves.push({
|
||||
map: leaf,
|
||||
codecMap: codecLeaf(leaf),
|
||||
offset: node.offset,
|
||||
stop: node.stop,
|
||||
});
|
||||
if (options.profile !== "browser-collection") {
|
||||
const ignoredSources = new Set(
|
||||
leaf.ignoreList ?? leaf.x_google_ignoreList ?? [],
|
||||
|
||||
@@ -34,7 +34,6 @@ export const traceSourceMap = (
|
||||
position: WebSourcePosition,
|
||||
): WebSourceMapReport => {
|
||||
const inspected = inspectSourceMap(text);
|
||||
const map = new AnyMap(inspected.jsonText, url);
|
||||
const decodedLeaves = decodeValidatedSourceMapLeaves(inspected.leaves, url);
|
||||
for (const { leaf, rows } of decodedLeaves)
|
||||
for (const [line, row] of rows.entries())
|
||||
@@ -44,6 +43,27 @@ export const traceSourceMap = (
|
||||
"format",
|
||||
"Embedded source-map mappings overlap the following section boundary.",
|
||||
);
|
||||
let map: TraceMap;
|
||||
if (inspected.format === "regular") {
|
||||
const decoded = decodedLeaves[0];
|
||||
if (decoded === undefined)
|
||||
throw new SourceMapFormatFailure(
|
||||
"format",
|
||||
"Regular source map has no validated leaf.",
|
||||
);
|
||||
map = decoded.map;
|
||||
} else {
|
||||
map = new AnyMap(
|
||||
{
|
||||
version: 3,
|
||||
sections: decodedLeaves.map(({ leaf, map: sectionMap }) => ({
|
||||
offset: leaf.offset,
|
||||
map: sectionMap,
|
||||
})),
|
||||
},
|
||||
url,
|
||||
);
|
||||
}
|
||||
const rows =
|
||||
inspected.format === "regular"
|
||||
? (decodedLeaves[0]?.rows ?? [])
|
||||
|
||||
Reference in New Issue
Block a user