feat(javascript): report observed export property presence (#1160)

* feat(javascript): report observed export property presence

Extend compare_javascript_export_shapes so each retained return variant
lists observed property names and each change reports presence independently
of value resolution. Complete parent coverage classifies one-sided names as
added or removed even when static values stay unknown.

Fixes #725

* test(javascript): match unknown export-shape values by availability

Nested availability objects include a reason when values stay unresolved.
Assert availability through objectContaining so presence-only added and
removed rows still verify unknown values.

* fix(javascript): preserve uncertain export property presence and locations

* fix(javascript): normalize presence and preserve local property coverage

* fix(javascript): require present discriminants for return pairing

* fix(javascript): normalize retained shapes before comparison

* refactor(javascript): share return projection with executable examples

* fix(javascript): localize uncertainty for missing mutated slots

* fix(javascript): bind advertised export examples to exact artifacts

* fix(javascript): keep uncertain property flow as candidates

---------

Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
Matt Van Hornandmorluto authored and GitHub committed 2026-10-09 18:30:31 +08:00
1 parent 04aef6df33
commit 45e3edc17f
25 files changed
+1552 -113

No files matched your search

@@ -299,6 +299,7 @@ const evaluateArray = (
context: EvaluationContext,
): JavaScriptSemanticValue => {
const items: JavaScriptSemanticValue[] = [];
const itemPresence: Record<number, "absent"> = {};
let unknownItems = false;
let omittedItems: number | null = 0;
for (const element of node.elements) {
@@ -309,8 +310,7 @@ const evaluateArray = (
break;
}
if (element === null) {
unknownItems = true;
if (omittedItems !== null) omittedItems += 1;
itemPresence[items.length] = "absent";
items.push({
status: "unknown",
reason: "Array hole has no primitive value.",
@@ -320,8 +320,14 @@ const evaluateArray = (
items.push(evaluateExpression(element, nestedContext(context)));
}
return unknownItems
? { status: "array", items, unknownItems: true, omittedItems }
: { status: "array", items, unknownItems: false, omittedItems: 0 };
? { status: "array", items, itemPresence, unknownItems: true, omittedItems }
: {
status: "array",
items,
itemPresence,
unknownItems: false,
omittedItems: 0,
};
};
const evaluateMember = (