2026-10-06 21:51:44 -05:00
|
|
|
import type { JavaScriptSemanticValue } from "./javascriptSemanticIr.js";
|
|
|
|
|
|
|
|
|
|
/** Invalidate only slots that an explicit mutation can affect. */
|
|
|
|
|
export const invalidateSemanticMutationPath = (
|
|
|
|
|
value: JavaScriptSemanticValue,
|
|
|
|
|
path: readonly (string | number | null)[],
|
|
|
|
|
): JavaScriptSemanticValue => {
|
|
|
|
|
const [key, ...remaining] = path;
|
|
|
|
|
const unknown: JavaScriptSemanticValue = {
|
|
|
|
|
status: "unknown",
|
|
|
|
|
reason: "This property may have been mutated.",
|
|
|
|
|
};
|
|
|
|
|
if (key === undefined || key === null) return unknown;
|
|
|
|
|
if (value.status === "object") {
|
|
|
|
|
const name = String(key);
|
|
|
|
|
const observed = value.properties.some(
|
|
|
|
|
(property) => property.name === name,
|
|
|
|
|
);
|
|
|
|
|
const properties = value.properties.map((property) =>
|
|
|
|
|
property.name === name
|
|
|
|
|
? {
|
|
|
|
|
...property,
|
2026-10-09 03:30:31 -07:00
|
|
|
...(remaining.length === 0
|
|
|
|
|
? { presence: "unknown-coverage" as const }
|
|
|
|
|
: {}),
|
2026-10-06 21:51:44 -05:00
|
|
|
value: invalidateSemanticMutationPath(property.value, remaining),
|
|
|
|
|
}
|
|
|
|
|
: property,
|
|
|
|
|
);
|
2026-10-09 03:30:31 -07:00
|
|
|
if (!observed)
|
|
|
|
|
properties.push({ name, value: unknown, presence: "unknown-coverage" });
|
|
|
|
|
return { ...value, properties };
|
2026-10-06 21:51:44 -05:00
|
|
|
}
|
|
|
|
|
if (value.status === "array") {
|
|
|
|
|
const index = typeof key === "number" ? key : Number(key);
|
|
|
|
|
if (
|
|
|
|
|
!Number.isSafeInteger(index) ||
|
|
|
|
|
index < 0 ||
|
|
|
|
|
String(index) !== String(key)
|
|
|
|
|
)
|
|
|
|
|
return unknown;
|
|
|
|
|
const items = value.items.map((item, position) =>
|
|
|
|
|
position === index
|
|
|
|
|
? invalidateSemanticMutationPath(item, remaining)
|
|
|
|
|
: item,
|
|
|
|
|
);
|
2026-10-09 03:30:31 -07:00
|
|
|
const itemPresence = {
|
|
|
|
|
...value.itemPresence,
|
|
|
|
|
...(remaining.length === 0 || value.items[index] === undefined
|
|
|
|
|
? { [index]: "unknown-coverage" as const }
|
|
|
|
|
: {}),
|
|
|
|
|
};
|
|
|
|
|
return { ...value, items, itemPresence };
|
2026-10-06 21:51:44 -05:00
|
|
|
}
|
|
|
|
|
return unknown;
|
|
|
|
|
};
|