diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts index 851b464853..57ee729045 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts @@ -84,6 +84,7 @@ class Visitor extends ReactiveFunctionVisitor { override visitInstruction(instr: ReactiveInstruction, state: Context): void { switch (instr.value.kind) { + case "OptionalExpression": case "SequenceExpression": case "ConditionalExpression": case "LogicalExpression": { diff --git a/compiler/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts b/compiler/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts index fc35300490..58616adece 100644 --- a/compiler/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts +++ b/compiler/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts @@ -14,7 +14,6 @@ import { InstructionKind, LValue, LValuePattern, - makeInstructionId, Phi, Place, } from "../HIR/HIR"; @@ -312,50 +311,6 @@ export function leaveSSA(fn: HIRFunction): void { } else { reassignmentPhis.push({ phi, block: phiBlock }); } - const hasBackEdge = backEdgePhis.has(phi); - const isPhiMutatedAfterCreation: boolean = - phi.id.mutableRange.end > - (phiBlock.instructions.at(0)?.id ?? phiBlock.terminal.id); - - /* - * Named variables whose phi doesn't have a back-edge can potentially be independenly - * memoized, depending on whether the phi is after its creation. - */ - if (phi.id.name !== null && !hasBackEdge) { - if (!isPhiMutatedAfterCreation) { - /* - * Simple case: predecesor-only values flowing into a phi, which is never modified: - * adjust the phi's range to clarify that the identifier does not mutate - */ - phi.id.mutableRange.start = terminal.id; - phi.id.mutableRange.end = makeInstructionId(terminal.id + 1); - } else { - /* - * Predecessor only values flow into a phi, which is modified later: - * all operands flow into the phi and can be modified, must extend their ranges - */ - for (const [, operand] of phi.operands) { - operand.mutableRange.end = phi.id.mutableRange.end; - } - } - continue; - } - /* - * Otherwise this is a temporary phi (logical or ternary) or occurs in a loop. In either - * case we can't independently memoize any of the values: unify their ranges to span the - * min(start) to max(end) so that we create a single scope for all the computation. - */ - let start = block.terminal.id as number; - let end = Number.MIN_SAFE_INTEGER; - const operands = [phi.id, ...phi.operands.values()]; - for (const operand of operands) { - start = Math.min(start, operand.mutableRange.start); - end = Math.max(end, operand.mutableRange.end); - } - for (const operand of operands) { - operand.mutableRange.start = makeInstructionId(start); - operand.mutableRange.end = makeInstructionId(end); - } } } const fallthroughId = terminalFallthrough(terminal); diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/destructuring-mixed-scope-and-local-variables-with-default.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/destructuring-mixed-scope-and-local-variables-with-default.expect.md index 60b8b74221..fa78a96465 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/destructuring-mixed-scope-and-local-variables-with-default.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/destructuring-mixed-scope-and-local-variables-with-default.expect.md @@ -56,7 +56,7 @@ function useFragment(_arg1, _arg2) { } function Component(props) { - const $ = useMemoCache(16); + const $ = useMemoCache(14); const post = useFragment(graphql`...`, props.post); let media; let allUrls; @@ -65,48 +65,40 @@ function Component(props) { allUrls = []; const { media: t0, comments: t1, urls: t2 } = post; + media = t0 === undefined ? null : t0; let t3; - if ($[4] !== t0) { - t3 = t0 === undefined ? null : t0; - $[4] = t0; + if ($[4] !== t1) { + t3 = t1 === undefined ? [] : t1; + $[4] = t1; $[5] = t3; } else { t3 = $[5]; } - media = t3; + const comments = t3; let t4; - if ($[6] !== t1) { - t4 = t1 === undefined ? [] : t1; - $[6] = t1; + if ($[6] !== t2) { + t4 = t2 === undefined ? [] : t2; + $[6] = t2; $[7] = t4; } else { t4 = $[7]; } - const comments = t4; + const urls = t4; let t5; - if ($[8] !== t2) { - t5 = t2 === undefined ? [] : t2; - $[8] = t2; - $[9] = t5; - } else { - t5 = $[9]; - } - const urls = t5; - let t6; - if ($[10] !== comments.length) { - t6 = (e) => { + if ($[8] !== comments.length) { + t5 = (e) => { if (!comments.length) { return; } console.log(comments.length); }; - $[10] = comments.length; - $[11] = t6; + $[8] = comments.length; + $[9] = t5; } else { - t6 = $[11]; + t5 = $[9]; } - onClick = t6; + onClick = t5; allUrls.push(...urls); $[0] = post; @@ -119,14 +111,14 @@ function Component(props) { onClick = $[3]; } let t0; - if ($[12] !== media || $[13] !== allUrls || $[14] !== onClick) { + if ($[10] !== media || $[11] !== allUrls || $[12] !== onClick) { t0 = ; - $[12] = media; - $[13] = allUrls; - $[14] = onClick; - $[15] = t0; + $[10] = media; + $[11] = allUrls; + $[12] = onClick; + $[13] = t0; } else { - t0 = $[15]; + t0 = $[13]; } return t0; } diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/escape-analysis-logical.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/escape-analysis-logical.expect.md index 38ddc62798..243e7a7064 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/escape-analysis-logical.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/escape-analysis-logical.expect.md @@ -24,7 +24,7 @@ export const FIXTURE_ENTRYPOINT = { ```javascript import { unstable_useMemoCache as useMemoCache } from "react"; function Component(props) { - const $ = useMemoCache(10); + const $ = useMemoCache(6); let t0; if ($[0] !== props.a) { t0 = [props.a]; @@ -52,17 +52,7 @@ function Component(props) { t2 = $[5]; } const c = t2; - let t3; - if ($[6] !== a || $[7] !== b || $[8] !== c) { - t3 = (a && b) || c; - $[6] = a; - $[7] = b; - $[8] = c; - $[9] = t3; - } else { - t3 = $[9]; - } - return t3; + return (a && b) || c; } export const FIXTURE_ENTRYPOINT = { diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/optional-computed-member-expression.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/optional-computed-member-expression.expect.md index 8815455a83..489063573c 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/optional-computed-member-expression.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/optional-computed-member-expression.expect.md @@ -14,7 +14,7 @@ function Component(props) { ```javascript import { unstable_useMemoCache as useMemoCache } from "react"; function Component(props) { - const $ = useMemoCache(5); + const $ = useMemoCache(2); let t0; if ($[0] !== props) { t0 = makeObject(props); @@ -24,16 +24,7 @@ function Component(props) { t0 = $[1]; } const object = t0; - let t1; - if ($[2] !== object || $[3] !== props) { - t1 = object?.[props.key]; - $[2] = object; - $[3] = props; - $[4] = t1; - } else { - t1 = $[4]; - } - return t1; + return object?.[props.key]; } ``` diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/optional-member-expression-with-optional-member-expr-as-property.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/optional-member-expression-with-optional-member-expr-as-property.expect.md index fc79abbd41..bfd4bd4031 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/optional-member-expression-with-optional-member-expr-as-property.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/optional-member-expression-with-optional-member-expr-as-property.expect.md @@ -14,7 +14,7 @@ function Component(props) { ```javascript import { unstable_useMemoCache as useMemoCache } from "react"; function Component(props) { - const $ = useMemoCache(3); + const $ = useMemoCache(1); let t0; if ($[0] === Symbol.for("react.memo_cache_sentinel")) { t0 = makeObject(); @@ -23,15 +23,7 @@ function Component(props) { t0 = $[0]; } const x = t0; - let t1; - if ($[1] !== props) { - t1 = x.y?.[props.a?.[props.b?.[props.c]]]; - $[1] = props; - $[2] = t1; - } else { - t1 = $[2]; - } - return t1; + return x.y?.[props.a?.[props.b?.[props.c]]]; } ``` diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-independently-memoized-property-load-for-method-call.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-independently-memoized-property-load-for-method-call.expect.md index 4ff0234428..59924c20f1 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-independently-memoized-property-load-for-method-call.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-independently-memoized-property-load-for-method-call.expect.md @@ -54,7 +54,7 @@ export const FIXTURE_ENTRYPOINT = { ```javascript import { unstable_useMemoCache as useMemoCache } from "react"; function Component(t0) { - const $ = useMemoCache(11); + const $ = useMemoCache(8); const { label, highlightedItem } = t0; const serverTime = useServerTime(); let t1; @@ -63,16 +63,8 @@ function Component(t0) { const highlight = new Highlight(highlightedItem); const time = serverTime.get(); - let t2; - if ($[5] !== time || $[6] !== label) { - t2 = time / 1000 || label; - $[5] = time; - $[6] = label; - $[7] = t2; - } else { - t2 = $[7]; - } - timestampLabel = t2; + + timestampLabel = time / 1000 || label; t1 = highlight.render(); $[0] = highlightedItem; @@ -85,18 +77,18 @@ function Component(t0) { timestampLabel = $[4]; } let t2; - if ($[8] !== t1 || $[9] !== timestampLabel) { + if ($[5] !== t1 || $[6] !== timestampLabel) { t2 = ( <> {t1} {timestampLabel} ); - $[8] = t1; - $[9] = timestampLabel; - $[10] = t2; + $[5] = t1; + $[6] = timestampLabel; + $[7] = t2; } else { - t2 = $[10]; + t2 = $[7]; } return t2; } diff --git a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-unreachable-code-early-return-in-useMemo.expect.md b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-unreachable-code-early-return-in-useMemo.expect.md index 14a5504a6d..eb1008fa55 100644 --- a/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-unreachable-code-early-return-in-useMemo.expect.md +++ b/compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/repro-unreachable-code-early-return-in-useMemo.expect.md @@ -49,60 +49,45 @@ import { import { ValidateMemoization, identity } from "shared-runtime"; function Component(t0) { - const $ = useMemoCache(10); + const $ = useMemoCache(7); const { value } = t0; let t1; bb13: { if (value == null) { - if ($[0] === Symbol.for("react.memo_cache_sentinel")) { - t1 = null; - break bb13; - $[0] = t1; - } else { - t1 = $[0]; - } + t1 = null; + break bb13; } try { let t3; - if ($[1] !== value) { + if ($[0] !== value) { t3 = { value }; - $[1] = value; - $[2] = t3; + $[0] = value; + $[1] = t3; } else { - t3 = $[2]; - } - if ($[3] === Symbol.for("react.memo_cache_sentinel")) { - t1 = t3; - $[3] = t1; - } else { - t1 = $[3]; + t3 = $[1]; } + t1 = t3; } catch (t2) { - if ($[4] === Symbol.for("react.memo_cache_sentinel")) { - t1 = null; - $[4] = t1; - } else { - t1 = $[4]; - } + t1 = null; } } const result = t1; let t2; - if ($[5] !== value) { + if ($[2] !== value) { t2 = [value]; - $[5] = value; - $[6] = t2; + $[2] = value; + $[3] = t2; } else { - t2 = $[6]; + t2 = $[3]; } let t3; - if ($[7] !== t2 || $[8] !== result) { + if ($[4] !== t2 || $[5] !== result) { t3 = ; - $[7] = t2; - $[8] = result; - $[9] = t3; + $[4] = t2; + $[5] = result; + $[6] = t3; } else { - t3 = $[9]; + t3 = $[6]; } return t3; }