diff --git a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts index 1aabb1acca723..049fe58e1b419 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts @@ -196,6 +196,7 @@ export function createNewFunctionNode( } function insertNewOutlinedFunctionNode( + program: NodePath, originalFn: BabelFn, compiledFn: CodegenFunction, ): NodePath { @@ -216,14 +217,6 @@ function insertNewOutlinedFunctionNode( */ case 'ArrowFunctionExpression': case 'FunctionExpression': { - CompilerError.invariant( - originalFn.parentPath.isVariableDeclarator() && - originalFn.parentPath.parentPath.isVariableDeclaration(), - { - reason: 'Expected a variable declarator parent', - loc: originalFn.node.loc ?? null, - }, - ); const fn: t.FunctionDeclaration = { type: 'FunctionDeclaration', id: compiledFn.id, @@ -233,8 +226,7 @@ function insertNewOutlinedFunctionNode( params: compiledFn.params, body: compiledFn.body, }; - const varDecl = originalFn.parentPath.parentPath; - const insertedFuncDecl = varDecl.insertAfter(fn)[0]!; + const insertedFuncDecl = program.pushContainer('body', [fn])[0]!; CompilerError.invariant(insertedFuncDecl.isFunctionDeclaration(), { reason: 'Expected inserted function declaration', description: `Got: ${insertedFuncDecl}`, @@ -468,7 +460,11 @@ export function compileProgram( reason: 'Unexpected nested outlined functions', loc: outlined.fn.loc, }); - const fn = insertNewOutlinedFunctionNode(current.fn, outlined.fn); + const fn = insertNewOutlinedFunctionNode( + program, + current.fn, + outlined.fn, + ); fn.skip(); ALREADY_COMPILED.add(fn.node); if (outlined.type !== null) { diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-outlining-in-react-memo.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-outlining-in-react-memo.expect.md deleted file mode 100644 index e49df32c8c3eb..0000000000000 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-outlining-in-react-memo.expect.md +++ /dev/null @@ -1,62 +0,0 @@ - -## Input - -```javascript -function Component(props) { - return ; -} - -const View = React.memo(({items}) => { - return ( -
    - {items.map(item => ( -
  • {item.name}
  • - ))} -
- ); -}); - -export const FIXTURE_ENTRYPOINT = { - fn: Component, - params: [ - { - items: [ - {id: 2, name: 'foo'}, - {id: 3, name: 'bar'}, - ], - }, - ], -}; - -``` - - -## Error - -``` - 3 | } - 4 | -> 5 | const View = React.memo(({items}) => { - | ^^^^^^^^^^^^^^ -> 6 | return ( - | ^^^^^^^^^^ -> 7 |
    - | ^^^^^^^^^^ -> 8 | {items.map(item => ( - | ^^^^^^^^^^ -> 9 |
  • {item.name}
  • - | ^^^^^^^^^^ -> 10 | ))} - | ^^^^^^^^^^ -> 11 |
- | ^^^^^^^^^^ -> 12 | ); - | ^^^^^^^^^^ -> 13 | }); - | ^^ Invariant: Expected a variable declarator parent (5:13) - 14 | - 15 | export const FIXTURE_ENTRYPOINT = { - 16 | fn: Component, -``` - - \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-func-expr.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-func-expr.expect.md index b403368e8a6b7..d97c06481c2e1 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-func-expr.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-func-expr.expect.md @@ -50,9 +50,6 @@ const Component2 = (props) => { } return t1; }; -function _temp(item) { - return
  • {item.name}
  • ; -} export const FIXTURE_ENTRYPOINT = { fn: Component2, @@ -65,6 +62,9 @@ export const FIXTURE_ENTRYPOINT = { }, ], }; +function _temp(item) { + return
  • {item.name}
  • ; +} ``` diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-react-memo.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-react-memo.expect.md new file mode 100644 index 0000000000000..11d4646c65538 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-react-memo.expect.md @@ -0,0 +1,90 @@ + +## Input + +```javascript +function Component(props) { + return ; +} + +const View = React.memo(({items}) => { + return ( +
      + {items.map(item => ( +
    • {item.name}
    • + ))} +
    + ); +}); + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [ + { + items: [ + {id: 2, name: 'foo'}, + {id: 3, name: 'bar'}, + ], + }, + ], +}; + +``` + +## Code + +```javascript +import { c as _c } from "react/compiler-runtime"; +function Component(props) { + const $ = _c(2); + let t0; + if ($[0] !== props) { + t0 = ; + $[0] = props; + $[1] = t0; + } else { + t0 = $[1]; + } + return t0; +} + +const View = React.memo((t0) => { + const $ = _c(4); + const { items } = t0; + let t1; + if ($[0] !== items) { + t1 = items.map(_temp); + $[0] = items; + $[1] = t1; + } else { + t1 = $[1]; + } + let t2; + if ($[2] !== t1) { + t2 =
      {t1}
    ; + $[2] = t1; + $[3] = t2; + } else { + t2 = $[3]; + } + return t2; +}); + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [ + { + items: [ + { id: 2, name: "foo" }, + { id: 3, name: "bar" }, + ], + }, + ], +}; +function _temp(item) { + return
  • {item.name}
  • ; +} + +``` + +### Eval output +(kind: ok)
    • foo
    • bar
    \ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-outlining-in-react-memo.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-react-memo.js similarity index 100% rename from compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/error.bug-outlining-in-react-memo.js rename to compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/outlining-in-react-memo.js