mirror of
https://github.com/morluto/rea.git
synced 2026-10-29 10:55:57 +00:00
fix(javascript): derive loop cardinality from exact literal values
Use the canonical cooked literal value for for-in and for-of string cardinality, preserving possible assignments and prototype uncertainty across quoted and template spellings. Validation: 473 focused tests across six files, including public CLI assignment Evidence and exported return shapes. Refs #4617
This commit is contained in:
1 parent
746a044e42
commit
c3e42385e7
3 files changed
+141
-5
No files matched your search
@@ -547,6 +547,62 @@ describe("nonfinite static values", () => {
|
||||
});
|
||||
|
||||
describe("binding write invalidation", () => {
|
||||
it.each(["in", "of"])(
|
||||
"retains prototype uncertainty for an empty template in for-%s",
|
||||
(operator) => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
String.prototype.extra = "possible inherited key";
|
||||
let selected = "before";
|
||||
for (selected ${operator} \`\`) {}
|
||||
const observed = selected;
|
||||
`);
|
||||
expect(
|
||||
topLevelBinding(ir, "selected").definitions.some(
|
||||
({ kind }) => kind === "assignment",
|
||||
),
|
||||
).toBe(true);
|
||||
expect(topLevelBinding(ir, "observed").value.status).not.toBe("literal");
|
||||
},
|
||||
);
|
||||
|
||||
it.each(
|
||||
[
|
||||
{ input: '"abc"', empty: false },
|
||||
{ input: "`abc`", empty: false },
|
||||
{ input: "`\\u0061`", empty: false },
|
||||
{ input: '""', empty: true },
|
||||
{ input: "``", empty: true },
|
||||
{ input: "`\\\n`", empty: true },
|
||||
].flatMap((literal) =>
|
||||
["in", "of"].flatMap((operator) =>
|
||||
["selected", "[selected]"].map((head) => ({
|
||||
...literal,
|
||||
operator,
|
||||
head,
|
||||
})),
|
||||
),
|
||||
),
|
||||
)(
|
||||
"preserves writes for $head $operator $input (empty=$empty)",
|
||||
({ input, empty, operator, head }) => {
|
||||
const ir = analyzeJavaScriptSemantics(`
|
||||
let selected = "before";
|
||||
for (${head} ${operator} ${input}) {}
|
||||
const observed = selected;
|
||||
export function result() { return observed; }
|
||||
`);
|
||||
expect(
|
||||
topLevelBinding(ir, "selected").definitions.some(
|
||||
({ kind }) => kind === "assignment",
|
||||
),
|
||||
).toBe(!empty);
|
||||
const value = topLevelBinding(ir, "observed").value;
|
||||
if (empty) expect(value).toEqual({ status: "literal", value: "before" });
|
||||
else expect(value).not.toEqual({ status: "literal", value: "before" });
|
||||
expect(onlyCallable(ir, "result").returnSites[0]?.value).toEqual(value);
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
["let value = 1; value++; const observed = value;", "unknown"],
|
||||
["let value = 1; --value; const observed = value;", "unknown"],
|
||||
|
||||
Reference in new issue
Block a user