fix(javascript)!: preserve property paths and uncertain slot presence

Use one explicit object/array slot model and JSON-pointer property identity across mutation analysis, return projection, and semantic graphs. Require observed presence for discriminants and resolve writes only through retained object or array receivers.

BREAKING CHANGE: projected return fields require explicit presence and semantic object operations carry full property paths.
This commit is contained in:
morluto
2026-10-09 20:03:19 +08:00
parent 63bf91405c
commit 475a0f84da
23 changed files with 831 additions and 560 deletions
@@ -32,25 +32,26 @@ export const invalidateSemanticMutationPath = (
return { ...value, properties };
}
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)
const name = String(key);
// Array length writes can remove every index; ordinary named properties
// and sparse indices affect only their own slot.
if (name === "length") return unknown;
const observed = value.items.some((item) => item.name === name);
const items = value.items.map((item) =>
item.name === name
? {
...item,
presence:
remaining.length === 0
? ("unknown-coverage" as const)
: item.presence,
value: invalidateSemanticMutationPath(item.value, remaining),
}
: item,
);
const itemPresence = {
...value.itemPresence,
...(remaining.length === 0 || value.items[index] === undefined
? { [index]: "unknown-coverage" as const }
: {}),
};
return { ...value, items, itemPresence };
if (!observed)
items.push({ name, presence: "unknown-coverage", value: unknown });
return { ...value, items };
}
return unknown;
};