diff --git a/compiler/apps/playground/babel.config.js b/compiler/apps/playground/babel.config.js index 0edf2e9b72d70..f65e0a2a79046 100644 --- a/compiler/apps/playground/babel.config.js +++ b/compiler/apps/playground/babel.config.js @@ -13,7 +13,7 @@ module.exports = function (api) { [ 'babel-plugin-react-compiler', { - runtimeModule: 'react-compiler-runtime', + target: '18', }, ], ], diff --git a/compiler/packages/babel-plugin-react-compiler/package.json b/compiler/packages/babel-plugin-react-compiler/package.json index fa8d5c06cf4d7..d9bfe9de7320c 100644 --- a/compiler/packages/babel-plugin-react-compiler/package.json +++ b/compiler/packages/babel-plugin-react-compiler/package.json @@ -8,6 +8,7 @@ "dist" ], "scripts": { + "postinstall": "./scripts/link-react-compiler-runtime.sh", "build": "rimraf dist && rollup --config --bundleConfigAsCjs", "test": "yarn snap:ci", "jest": "yarn build && ts-node node_modules/.bin/jest", diff --git a/compiler/packages/babel-plugin-react-compiler/scripts/link-react-compiler-runtime.sh b/compiler/packages/babel-plugin-react-compiler/scripts/link-react-compiler-runtime.sh new file mode 100755 index 0000000000000..4d1bcf1ec35d0 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/scripts/link-react-compiler-runtime.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +set -eo pipefail + +yarn --silent workspace react-compiler-runtime link +yarn --silent workspace babel-plugin-react-compiler link react-compiler-runtime 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 c2c7d8d640846..d60f86e7fa4e2 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts +++ b/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts @@ -298,7 +298,6 @@ export function compileProgram( return; } const useMemoCacheIdentifier = program.scope.generateUidIdentifier('c'); - const moduleName = pass.opts.runtimeModule ?? 'react/compiler-runtime'; /* * Record lint errors and critical errors as depending on Forget's config, @@ -605,7 +604,7 @@ export function compileProgram( if (needsMemoCacheFunctionImport) { updateMemoCacheFunctionImport( program, - moduleName, + getReactCompilerRuntimeModule(pass.opts), useMemoCacheIdentifier.name, ); } @@ -638,8 +637,12 @@ function shouldSkipCompilation( } } - const moduleName = pass.opts.runtimeModule ?? 'react/compiler-runtime'; - if (hasMemoCacheFunctionImport(program, moduleName)) { + if ( + hasMemoCacheFunctionImport( + program, + getReactCompilerRuntimeModule(pass.opts), + ) + ) { return true; } return false; @@ -1126,3 +1129,31 @@ function checkFunctionReferencedBeforeDeclarationAtTopLevel( return errors.details.length > 0 ? errors : null; } + +type ReactCompilerRuntimeModule = + | 'react/compiler-runtime' // from react namespace + | 'react-compiler-runtime'; // npm package +function getReactCompilerRuntimeModule( + opts: PluginOptions, +): ReactCompilerRuntimeModule { + let moduleName: ReactCompilerRuntimeModule | null = null; + switch (opts.target) { + case '17': + case '18': { + moduleName = 'react-compiler-runtime'; + break; + } + case '19': { + moduleName = 'react/compiler-runtime'; + break; + } + default: + CompilerError.invariant(moduleName != null, { + reason: 'Expected target to already be validated', + description: null, + loc: null, + suggestions: null, + }); + } + return moduleName; +} diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag.expect.md new file mode 100644 index 0000000000000..b4cf41e369e79 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag.expect.md @@ -0,0 +1,45 @@ + +## Input + +```javascript +// @target="18" + +function Component() { + return
Hello world
; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [], + isComponent: true, +}; + +``` + +## Code + +```javascript +import { c as _c } from "react-compiler-runtime"; // @target="18" + +function Component() { + const $ = _c(1); + let t0; + if ($[0] === Symbol.for("react.memo_cache_sentinel")) { + t0 =
Hello world
; + $[0] = t0; + } else { + t0 = $[0]; + } + return t0; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [], + isComponent: true, +}; + +``` + +### Eval output +(kind: ok)
Hello world
\ No newline at end of file diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag.js new file mode 100644 index 0000000000000..5319d28f0ad59 --- /dev/null +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag.js @@ -0,0 +1,11 @@ +// @target="18" + +function Component() { + return
Hello world
; +} + +export const FIXTURE_ENTRYPOINT = { + fn: Component, + params: [], + isComponent: true, +}; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/userspace-use-memo-cache.expect.md b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/userspace-use-memo-cache.expect.md index 386d6afbb23e0..972d1069072bb 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/userspace-use-memo-cache.expect.md +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/userspace-use-memo-cache.expect.md @@ -2,7 +2,9 @@ ## Input ```javascript -// @runtimeModule="react-forget-runtime" +// @runtimeModule="react-compiler-runtime" +import {useState} from 'react'; + function Component(props) { const [x, setX] = useState(1); let y; @@ -10,10 +12,12 @@ function Component(props) { y = x * 2; } return ( - + }}> + Click me + ); } @@ -28,7 +32,9 @@ export const FIXTURE_ENTRYPOINT = { ## Code ```javascript -import { c as _c } from "react-forget-runtime"; // @runtimeModule="react-forget-runtime" +import { c as _c } from "react/compiler-runtime"; // @runtimeModule="react-compiler-runtime" +import { useState } from "react"; + function Component(props) { const $ = _c(5); const [x, setX] = useState(1); @@ -48,11 +54,13 @@ function Component(props) { let t1; if ($[3] !== t0) { t1 = ( - ); $[3] = t0; $[4] = t1; diff --git a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/userspace-use-memo-cache.js b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/userspace-use-memo-cache.js index 013a1be33081e..1e6d5f435dd32 100644 --- a/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/userspace-use-memo-cache.js +++ b/compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/userspace-use-memo-cache.js @@ -1,4 +1,6 @@ -// @runtimeModule="react-forget-runtime" +// @runtimeModule="react-compiler-runtime" +import {useState} from 'react'; + function Component(props) { const [x, setX] = useState(1); let y; @@ -6,10 +8,12 @@ function Component(props) { y = x * 2; } return ( - + }}> + Click me + ); }