diff --git a/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts b/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts index cc0d2c08d6..ce62779834 100644 --- a/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts +++ b/compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts @@ -106,6 +106,7 @@ export function mergeOverlappingReactiveScopes(fn: ReactiveFunction): void { context.enter(() => { visitBlock(context, fn.body); }); + context.complete(); } function visitBlock(context: Context, block: ReactiveBlock): void { @@ -205,6 +206,7 @@ class Context { scopes: Array = []; seenScopes: Set = new Set(); joinedScopes: DisjointSet = new DisjointSet(); + operandScopes: Map = new Map(); visitId(id: InstructionId): void { const currentBlock = this.scopes[this.scopes.length - 1]!; @@ -223,6 +225,7 @@ class Context { if (scope === null) { return; } + this.operandScopes.set(place, scope); const currentBlock = this.scopes[this.scopes.length - 1]!; // Fast-path for the first time we see a new scope if (!this.seenScopes.has(scope.id)) { @@ -290,19 +293,24 @@ class Context { this.scopes.push(new BlockScope()); fn(); this.scopes.pop(); - if (this.scopes.length === 0) { - this.joinedScopes.forEach((scope, groupScope) => { - if (scope !== groupScope) { - groupScope.range.start = makeInstructionId( - Math.min(groupScope.range.start, scope.range.start) - ); - groupScope.range.end = makeInstructionId( - Math.max(groupScope.range.end, scope.range.end) - ); - scope.range = groupScope.range; - scope.id = groupScope.id; - } - }); + } + + complete(): void { + this.joinedScopes.forEach((scope, groupScope) => { + if (scope !== groupScope) { + groupScope.range.start = makeInstructionId( + Math.min(groupScope.range.start, scope.range.start) + ); + groupScope.range.end = makeInstructionId( + Math.max(groupScope.range.end, scope.range.end) + ); + } + }); + for (const [operand, originalScope] of this.operandScopes) { + const mergedScope = this.joinedScopes.find(originalScope); + if (mergedScope !== null) { + operand.identifier.scope = mergedScope; + } } } } diff --git a/compiler/forget/src/__tests__/fixtures/hir/chained-assignment-expressions.expect.md b/compiler/forget/src/__tests__/fixtures/hir/chained-assignment-expressions.expect.md index 5fe3218d8a..78b824d246 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/chained-assignment-expressions.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/chained-assignment-expressions.expect.md @@ -17,11 +17,18 @@ function foo() { ```javascript function foo() { - const x = { x: 0 }; - const y = { z: 0 }; - const z = { z: 0 }; - x.x = x.x + (y.y = y.y * 1); - z.z = z.z + (y.y = y.y * (x.x = x.x & 3)); + const $ = React.useMemoCache(); + let z; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + const x = { x: 0 }; + const y = { z: 0 }; + z = { z: 0 }; + x.x = x.x + (y.y = y.y * 1); + z.z = z.z + (y.y = y.y * (x.x = x.x & 3)); + $[0] = z; + } else { + z = $[0]; + } return z; } diff --git a/compiler/forget/src/__tests__/fixtures/hir/conditional-on-mutable.expect.md b/compiler/forget/src/__tests__/fixtures/hir/conditional-on-mutable.expect.md index 00db775091..48ca4ec80c 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/conditional-on-mutable.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/conditional-on-mutable.expect.md @@ -40,9 +40,10 @@ function Component(props) { const c_1 = $[1] !== props.p1; const c_2 = $[2] !== props.p2; let a; + let b; if (c_0 || c_1 || c_2) { a = []; - const b = []; + b = []; if (b) { a.push(props.p0); } @@ -53,21 +54,23 @@ function Component(props) { $[1] = props.p1; $[2] = props.p2; $[3] = a; + $[4] = b; } else { a = $[3]; + b = $[4]; } - const c_4 = $[4] !== a; - const c_5 = $[5] !== b; - let t6; - if (c_4 || c_5) { - t6 = ; - $[4] = a; - $[5] = b; - $[6] = t6; + const c_5 = $[5] !== a; + const c_6 = $[6] !== b; + let t7; + if (c_5 || c_6) { + t7 = ; + $[5] = a; + $[6] = b; + $[7] = t7; } else { - t6 = $[6]; + t7 = $[7]; } - return t6; + return t7; } function Component(props) { @@ -76,9 +79,10 @@ function Component(props) { const c_1 = $[1] !== props.p1; const c_2 = $[2] !== props.p2; let a; + let b; if (c_0 || c_1 || c_2) { a = []; - const b = []; + b = []; if (mayMutate(b)) { a.push(props.p0); } @@ -89,21 +93,23 @@ function Component(props) { $[1] = props.p1; $[2] = props.p2; $[3] = a; + $[4] = b; } else { a = $[3]; + b = $[4]; } - const c_4 = $[4] !== a; - const c_5 = $[5] !== b; - let t6; - if (c_4 || c_5) { - t6 = ; - $[4] = a; - $[5] = b; - $[6] = t6; + const c_5 = $[5] !== a; + const c_6 = $[6] !== b; + let t7; + if (c_5 || c_6) { + t7 = ; + $[5] = a; + $[6] = b; + $[7] = t7; } else { - t6 = $[6]; + t7 = $[7]; } - return t6; + return t7; } function Foo() {} diff --git a/compiler/forget/src/__tests__/fixtures/hir/independent-across-if.expect.md b/compiler/forget/src/__tests__/fixtures/hir/independent-across-if.expect.md index 45e3e57a78..1b554966c2 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/independent-across-if.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/independent-across-if.expect.md @@ -61,9 +61,10 @@ function Component(props) { const c_1 = $[1] !== props.b; const c_2 = $[2] !== props.c; let a; + let b; if (c_0 || c_1 || c_2) { a = compute(props.a); - const b = compute(props.b); + b = compute(props.b); if (props.c) { mutate(a); mutate(b); @@ -72,21 +73,23 @@ function Component(props) { $[1] = props.b; $[2] = props.c; $[3] = a; + $[4] = b; } else { a = $[3]; + b = $[4]; } - const c_4 = $[4] !== a; - const c_5 = $[5] !== b; - let t6; - if (c_4 || c_5) { - t6 = ; - $[4] = a; - $[5] = b; - $[6] = t6; + const c_5 = $[5] !== a; + const c_6 = $[6] !== b; + let t7; + if (c_5 || c_6) { + t7 = ; + $[5] = a; + $[6] = b; + $[7] = t7; } else { - t6 = $[6]; + t7 = $[7]; } - return t6; + return t7; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md b/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md index f74bef2326..6b2c6710d4 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md @@ -36,10 +36,11 @@ function Component(props) { const c_0 = $[0] !== props.p0; const c_1 = $[1] !== props.p2; let x; + let y$0; if (c_0 || c_1) { x = []; const y = undefined; - let y$0 = y; + y$0 = y; bb1: switch (props.p0) { case 1: { break bb1; @@ -47,11 +48,11 @@ function Component(props) { case true: { x.push(props.p2); let y$1; - if ($[3] === Symbol.for("react.memo_cache_sentinel")) { + if ($[4] === Symbol.for("react.memo_cache_sentinel")) { y$1 = []; - $[3] = y$1; + $[4] = y$1; } else { - y$1 = $[3]; + y$1 = $[4]; } y$0 = y$1; break bb1; @@ -67,31 +68,33 @@ function Component(props) { $[0] = props.p0; $[1] = props.p2; $[2] = x; + $[3] = y$0; } else { x = $[2]; + y$0 = $[3]; } - const c_4 = $[4] !== x; + const c_5 = $[5] !== x; let child; - if (c_4) { + if (c_5) { child = ; - $[4] = x; - $[5] = child; + $[5] = x; + $[6] = child; } else { - child = $[5]; + child = $[6]; } y$0.push(props.p4); - const c_6 = $[6] !== y$0; - const c_7 = $[7] !== child; - let t8; - if (c_6 || c_7) { - t8 = {child}; - $[6] = y$0; - $[7] = child; - $[8] = t8; + const c_7 = $[7] !== y$0; + const c_8 = $[8] !== child; + let t9; + if (c_7 || c_8) { + t9 = {child}; + $[7] = y$0; + $[8] = child; + $[9] = t9; } else { - t8 = $[8]; + t9 = $[9]; } - return t8; + return t9; } ``` diff --git a/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md b/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md index 334cec3a31..5ed54310bb 100644 --- a/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md +++ b/compiler/forget/src/__tests__/fixtures/hir/switch.expect.md @@ -32,10 +32,11 @@ function Component(props) { const c_1 = $[1] !== props.p2; const c_2 = $[2] !== props.p3; let x; + let y$0; if (c_0 || c_1 || c_2) { x = []; const y = undefined; - let y$0 = y; + y$0 = y; switch (props.p0) { case true: { x.push(props.p2); @@ -51,31 +52,33 @@ function Component(props) { $[1] = props.p2; $[2] = props.p3; $[3] = x; + $[4] = y$0; } else { x = $[3]; + y$0 = $[4]; } - const c_4 = $[4] !== x; + const c_5 = $[5] !== x; let child; - if (c_4) { + if (c_5) { child = ; - $[4] = x; - $[5] = child; + $[5] = x; + $[6] = child; } else { - child = $[5]; + child = $[6]; } y$0.push(props.p4); - const c_6 = $[6] !== y$0; - const c_7 = $[7] !== child; - let t8; - if (c_6 || c_7) { - t8 = {child}; - $[6] = y$0; - $[7] = child; - $[8] = t8; + const c_7 = $[7] !== y$0; + const c_8 = $[8] !== child; + let t9; + if (c_7 || c_8) { + t9 = {child}; + $[7] = y$0; + $[8] = child; + $[9] = t9; } else { - t8 = $[8]; + t9 = $[9]; } - return t8; + return t9; } ```