mirror of
https://github.com/morluto/rea
synced 2026-10-27 06:33:32 -04:00
fix(javascript): resolve child ownership at receiver reads (#3819)
* fix(javascript): resolve child ownership at receiver reads * fix(javascript): preserve deferred field child candidates --------- Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
@@ -1,11 +1,74 @@
|
||||
import * as t from "@babel/types";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { semanticMutationInitializers } from "./javascriptSemanticMutationInitializers.js";
|
||||
import {
|
||||
semanticBindingAtRead,
|
||||
semanticMutationInitializers,
|
||||
semanticTopLevelEffectFollowsCapture,
|
||||
} from "./javascriptSemanticMutationInitializers.js";
|
||||
import type { JavaScriptSemanticBindingState } from "./javascriptSemanticState.js";
|
||||
import { traverseJavaScriptAst } from "./javascriptSemanticTraversal.js";
|
||||
import { parseJavaScriptSource } from "./javascriptSourceParser.js";
|
||||
|
||||
it.each([
|
||||
["public value", false, false],
|
||||
["private value", false, false],
|
||||
["accessor value", false, false],
|
||||
["public value", true, true],
|
||||
["private value", true, true],
|
||||
["accessor value", true, true],
|
||||
["public key", false, true],
|
||||
["accessor key", false, true],
|
||||
] as const)(
|
||||
"orders %s reads with static=%s only when evaluated at class definition",
|
||||
(kind, isStatic, ordered) => {
|
||||
const initializer = t.numericLiteral(1);
|
||||
const read = t.identifier("child");
|
||||
const inKey = kind.endsWith("key");
|
||||
const key = inKey ? read : t.identifier("field");
|
||||
const value = inKey ? t.numericLiteral(0) : read;
|
||||
const field = kind.startsWith("private")
|
||||
? t.classPrivateProperty(t.privateName(t.identifier("field")), value)
|
||||
: kind.startsWith("accessor")
|
||||
? t.classAccessorProperty(key, value, null, null, inKey)
|
||||
: t.classProperty(key, value, null, null, inKey);
|
||||
field.static = isStatic;
|
||||
const program = t.program([
|
||||
t.variableDeclaration("let", [
|
||||
t.variableDeclarator(t.identifier("child"), initializer),
|
||||
]),
|
||||
t.classDeclaration(t.identifier("Stop"), null, t.classBody([field])),
|
||||
]);
|
||||
const parents = new WeakMap<t.Node, t.Node>();
|
||||
traverseJavaScriptAst(program, {
|
||||
enter: (node, parent) => {
|
||||
if (parent !== null) parents.set(node, parent);
|
||||
},
|
||||
});
|
||||
const binding: JavaScriptSemanticBindingState = {
|
||||
bindingId: "program:child",
|
||||
scopeId: "program",
|
||||
name: "child",
|
||||
kind: "variable",
|
||||
declarationKinds: new Set(["let"]),
|
||||
mutable: true,
|
||||
memberWrites: [],
|
||||
escapedPaths: [],
|
||||
definitions: [],
|
||||
initializers: [{ node: initializer, projection: [] }],
|
||||
referenceInitializers: [],
|
||||
directOrigins: [],
|
||||
runtimeImport: false,
|
||||
};
|
||||
expect(semanticBindingAtRead(binding, read, parents).status).toBe(
|
||||
ordered ? "ordered" : "unresolved",
|
||||
);
|
||||
expect(
|
||||
semanticTopLevelEffectFollowsCapture(initializer, read, parents),
|
||||
).toBe(ordered);
|
||||
},
|
||||
);
|
||||
|
||||
describe("parameter references copied into function body bindings", () => {
|
||||
it.each([
|
||||
["var arg = []; mutate(arg);", false],
|
||||
|
||||
Reference in New Issue
Block a user