2026-10-07 16:03:37 +08:00
|
|
|
import { compareCodePoints } from "../../domain/canonicalOrdering.js";
|
2026-07-17 23:57:23 +08:00
|
|
|
import type { JavaScriptJsonModuleObservation } from "./JavaScriptArtifactAnalysisTypes.js";
|
2026-10-07 17:57:33 +08:00
|
|
|
import type { JavaScriptArtifactFile } from "../../domain/javascript/javascriptArtifactFiles.js";
|
2026-07-17 23:57:23 +08:00
|
|
|
|
|
|
|
|
/** Parse one approved JSON module without evaluating JavaScript or resolving imports. */
|
|
|
|
|
export const analyzeJavaScriptJsonModule = (
|
|
|
|
|
file: JavaScriptArtifactFile,
|
|
|
|
|
): JavaScriptJsonModuleObservation => {
|
|
|
|
|
if (!file.text.included)
|
|
|
|
|
return {
|
|
|
|
|
path: file.path,
|
|
|
|
|
sha256: file.sha256,
|
|
|
|
|
status: "unavailable",
|
|
|
|
|
top_level_keys: [],
|
|
|
|
|
omitted_top_level_keys: null,
|
|
|
|
|
limitation: `JSON module text was unavailable: ${file.text.reason}.`,
|
|
|
|
|
};
|
|
|
|
|
let value: unknown;
|
|
|
|
|
try {
|
|
|
|
|
value = JSON.parse(file.text.value);
|
2026-10-06 05:58:46 +08:00
|
|
|
} catch (cause: unknown) {
|
|
|
|
|
void cause;
|
2026-07-17 23:57:23 +08:00
|
|
|
return {
|
|
|
|
|
path: file.path,
|
|
|
|
|
sha256: file.sha256,
|
|
|
|
|
status: "invalid",
|
|
|
|
|
top_level_keys: [],
|
|
|
|
|
omitted_top_level_keys: 0,
|
|
|
|
|
limitation: "JSON module is not valid JSON.",
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
const keys =
|
|
|
|
|
typeof value === "object" && value !== null && !Array.isArray(value)
|
|
|
|
|
? Object.keys(value).sort(compareCodePoints)
|
|
|
|
|
: [];
|
2026-09-29 10:53:45 +08:00
|
|
|
const retained = keys;
|
2026-07-17 23:57:23 +08:00
|
|
|
return {
|
|
|
|
|
path: file.path,
|
|
|
|
|
sha256: file.sha256,
|
|
|
|
|
status: "included",
|
|
|
|
|
top_level_keys: retained,
|
2026-09-29 10:53:45 +08:00
|
|
|
omitted_top_level_keys: 0,
|
2026-07-17 23:57:23 +08:00
|
|
|
limitation: null,
|
|
|
|
|
};
|
|
|
|
|
};
|