mirror of
https://github.com/morluto/rea.git
synced 2026-11-11 01:13:39 +00:00
fix(javascript): preserve effects through yielded array references (#1437)
This commit is contained in:
1 parent
dc5af6d68f
commit
0a14ca41b4
4 files changed
+188
-4
No files matched your search
@@ -565,9 +565,21 @@ const bindAssignment = (
|
||||
else if (t.isForOfStatement(node) || t.isForInStatement(node))
|
||||
for (const pattern of t.isVariableDeclaration(node.left)
|
||||
? node.left.declarations.map(({ id }) => id)
|
||||
: [node.left])
|
||||
: [node.left]) {
|
||||
for (const identifier of assignedPatternIdentifiers(pattern))
|
||||
addAssignment(identifier, node, scope, state);
|
||||
if (t.isForOfStatement(node))
|
||||
// Keep the loop value unknown, but preserve references yielded into
|
||||
// each bound slot so writes/escapes can reach their iterable origins.
|
||||
bindPattern({
|
||||
pattern,
|
||||
initializer: node,
|
||||
scope,
|
||||
state,
|
||||
mutable: true,
|
||||
referenceOnly: true,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const assignedPatternIdentifiers = (
|
||||
@@ -780,7 +792,11 @@ const bindPattern = (input: BindPatternInput): void => {
|
||||
}
|
||||
if (t.isIdentifier(pattern)) {
|
||||
if (referenceOnly) {
|
||||
const binding = scope.bindings.get(pattern.name);
|
||||
const binding = resolveSemanticBindingFromScope(
|
||||
scope,
|
||||
pattern.name,
|
||||
state,
|
||||
);
|
||||
if (binding !== undefined && initializer !== null)
|
||||
binding.referenceInitializers.push({
|
||||
node: initializer,
|
||||
|
||||
@@ -8,8 +8,9 @@ interface IterationSourceValue {
|
||||
readonly projection: readonly (string | number | null)[];
|
||||
}
|
||||
|
||||
/** An implicit iterator receiver, with guards for destructuring defaults. */
|
||||
/** An iterator receiver or yielded reference store, with default guards. */
|
||||
export interface SemanticIterationSource extends IterationSourceValue {
|
||||
readonly kind: "iteration" | "reference-store";
|
||||
readonly mutation: t.Node;
|
||||
readonly fallbackSources?: readonly IterationSourceValue[];
|
||||
readonly requiredSources?: readonly IterationSourceValue[];
|
||||
@@ -30,8 +31,10 @@ const add = (
|
||||
source: IterationSourceValue,
|
||||
mutation: t.Node,
|
||||
guards: SourceGuards,
|
||||
kind: SemanticIterationSource["kind"] = "iteration",
|
||||
): void => {
|
||||
sources.push({
|
||||
kind,
|
||||
node: source.node,
|
||||
projection: source.projection,
|
||||
mutation,
|
||||
@@ -66,6 +69,13 @@ const visit = (
|
||||
guards: SourceGuards = {},
|
||||
): void => {
|
||||
const { sources, mutation } = context;
|
||||
if (t.isForOfStatement(mutation) && t.isMemberExpression(pattern)) {
|
||||
// Storing a yielded reference in a property has no lexical loop binding.
|
||||
// Preserve its escape rather than assuming later writes cannot reach it.
|
||||
if (source !== undefined)
|
||||
add(sources, source, mutation, guards, "reference-store");
|
||||
return;
|
||||
}
|
||||
if (t.isTSParameterProperty(pattern)) {
|
||||
visit(context, pattern.parameter, source, guards);
|
||||
return;
|
||||
|
||||
@@ -324,7 +324,7 @@ export const collectSemanticMemberMutations = (
|
||||
bindings: new Set(),
|
||||
effect: "escape",
|
||||
originAt: source.mutation,
|
||||
iterationOnly: true,
|
||||
iterationOnly: source.kind === "iteration",
|
||||
});
|
||||
if (t.isAssignmentExpression(node)) markTarget(node.left, node);
|
||||
else if (t.isUpdateExpression(node)) markTarget(node.argument, node);
|
||||
@@ -369,6 +369,19 @@ export const collectSemanticMemberMutations = (
|
||||
const { initializer } = reference;
|
||||
if (referenceSourcesInactive(initializer, state))
|
||||
pendingReferences.push(reference);
|
||||
else if (t.isForOfStatement(initializer.node))
|
||||
deferIterable({
|
||||
node: initializer.node.right,
|
||||
projection: [],
|
||||
path: [null, ...reference.path],
|
||||
fallbackPath: [],
|
||||
bindings: reference.bindings,
|
||||
effect: reference.effect,
|
||||
originAt: initializer.node,
|
||||
...(reference.mutation === undefined
|
||||
? {}
|
||||
: { mutation: reference.mutation }),
|
||||
});
|
||||
else if (
|
||||
initializer.copyKind === "array-rest" &&
|
||||
initializer.copyProjectionOffset !== undefined
|
||||
|
||||
Reference in new issue
Block a user