[rcr] Update default runtimeModule to react-compiler-runtime (#31144)
Updates the compiler to always import from `react-compiler-runtime` by default. The runtime then decides whether to use the official or userspace implementation of useMemoCache.
lauren committed
Oct 7, 2024 at 17:59 UTC
3fd3364107ba1fa0e8edf86ee9cb9562a9be3929
8 files changed
+124
-14
compiler/apps/playground/babel.config.js
+1
-1
@@ -13,7 +13,7 @@ module.exports = function (api) {
13
[
14
'babel-plugin-react-compiler',
15
{
16
- runtimeModule: 'react-compiler-runtime',
16
+ target: '18',
17
},
18
],
19
],
compiler/packages/babel-plugin-react-compiler/package.json
+1
@@ -8,6 +8,7 @@
8
"dist"
9
],
10
"scripts": {
11
+ "postinstall": "./scripts/link-react-compiler-runtime.sh",
12
"build": "rimraf dist && rollup --config --bundleConfigAsCjs",
13
"test": "yarn snap:ci",
14
"jest": "yarn build && ts-node node_modules/.bin/jest",
compiler/packages/babel-plugin-react-compiler/scripts/link-react-compiler-runtime.sh
new
+10
@@ -0,0 +1,10 @@
1
+#!/usr/bin/env bash
2
+# Copyright (c) Meta Platforms, Inc. and affiliates.
3
+#
4
+# This source code is licensed under the MIT license found in the
5
+# LICENSE file in the root directory of this source tree.
6
+
7
+set -eo pipefail
8
+
9
+yarn --silent workspace react-compiler-runtime link
10
+yarn --silent workspace babel-plugin-react-compiler link react-compiler-runtime
compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts
+35
-4
@@ -298,7 +298,6 @@ export function compileProgram(
298
return;
299
}
300
const useMemoCacheIdentifier = program.scope.generateUidIdentifier('c');
301
- const moduleName = pass.opts.runtimeModule ?? 'react/compiler-runtime';
301
302
/*
303
* Record lint errors and critical errors as depending on Forget's config,
@@ -605,7 +604,7 @@ export function compileProgram(
604
if (needsMemoCacheFunctionImport) {
605
updateMemoCacheFunctionImport(
606
program,
608
- moduleName,
607
+ getReactCompilerRuntimeModule(pass.opts),
608
useMemoCacheIdentifier.name,
609
);
610
}
@@ -638,8 +637,12 @@ function shouldSkipCompilation(
637
}
638
}
639
641
- const moduleName = pass.opts.runtimeModule ?? 'react/compiler-runtime';
642
- if (hasMemoCacheFunctionImport(program, moduleName)) {
640
+ if (
641
+ hasMemoCacheFunctionImport(
642
+ program,
643
+ getReactCompilerRuntimeModule(pass.opts),
644
+ )
645
+ ) {
646
return true;
647
}
648
return false;
@@ -1126,3 +1129,31 @@ function checkFunctionReferencedBeforeDeclarationAtTopLevel(
1129
1130
return errors.details.length > 0 ? errors : null;
1131
}
1132
+
1133
+type ReactCompilerRuntimeModule =
1134
+ | 'react/compiler-runtime' // from react namespace
1135
+ | 'react-compiler-runtime'; // npm package
1136
+function getReactCompilerRuntimeModule(
1137
+ opts: PluginOptions,
1138
+): ReactCompilerRuntimeModule {
1139
+ let moduleName: ReactCompilerRuntimeModule | null = null;
1140
+ switch (opts.target) {
1141
+ case '17':
1142
+ case '18': {
1143
+ moduleName = 'react-compiler-runtime';
1144
+ break;
1145
+ }
1146
+ case '19': {
1147
+ moduleName = 'react/compiler-runtime';
1148
+ break;
1149
+ }
1150
+ default:
1151
+ CompilerError.invariant(moduleName != null, {
1152
+ reason: 'Expected target to already be validated',
1153
+ description: null,
1154
+ loc: null,
1155
+ suggestions: null,
1156
+ });
1157
+ }
1158
+ return moduleName;
1159
+}
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag.expect.md
new
+45
@@ -0,0 +1,45 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+// @target="18"
6
+
7
+function Component() {
8
+ return <div>Hello world</div>;
9
+}
10
+
11
+export const FIXTURE_ENTRYPOINT = {
12
+ fn: Component,
13
+ params: [],
14
+ isComponent: true,
15
+};
16
+
17
+```
18
+
19
+## Code
20
+
21
+```javascript
22
+import { c as _c } from "react-compiler-runtime"; // @target="18"
23
+
24
+function Component() {
25
+ const $ = _c(1);
26
+ let t0;
27
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
28
+ t0 = <div>Hello world</div>;
29
+ $[0] = t0;
30
+ } else {
31
+ t0 = $[0];
32
+ }
33
+ return t0;
34
+}
35
+
36
+export const FIXTURE_ENTRYPOINT = {
37
+ fn: Component,
38
+ params: [],
39
+ isComponent: true,
40
+};
41
+
42
+```
43
+
44
+### Eval output
45
+(kind: ok) <div>Hello world</div>
\ No newline at end of file
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/target-flag.js
new
+11
@@ -0,0 +1,11 @@
1
+// @target="18"
2
+
3
+function Component() {
4
+ return <div>Hello world</div>;
5
+}
6
+
7
+export const FIXTURE_ENTRYPOINT = {
8
+ fn: Component,
9
+ params: [],
10
+ isComponent: true,
11
+};
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/userspace-use-memo-cache.expect.md
+14
-6
@@ -2,7 +2,9 @@
2
## Input
3
4
```javascript
5
-// @runtimeModule="react-forget-runtime"
5
+// @runtimeModule="react-compiler-runtime"
6
+import {useState} from 'react';
7
+
8
function Component(props) {
9
const [x, setX] = useState(1);
10
let y;
@@ -10,10 +12,12 @@ function Component(props) {
12
y = x * 2;
13
}
14
return (
13
- <Button
15
+ <button
16
onClick={() => {
17
setX(10 * y);
16
- }}></Button>
18
+ }}>
19
+ Click me
20
+ </button>
21
);
22
}
23
@@ -28,7 +32,9 @@ export const FIXTURE_ENTRYPOINT = {
32
## Code
33
34
```javascript
31
-import { c as _c } from "react-forget-runtime"; // @runtimeModule="react-forget-runtime"
35
+import { c as _c } from "react/compiler-runtime"; // @runtimeModule="react-compiler-runtime"
36
+import { useState } from "react";
37
+
38
function Component(props) {
39
const $ = _c(5);
40
const [x, setX] = useState(1);
@@ -48,11 +54,13 @@ function Component(props) {
54
let t1;
55
if ($[3] !== t0) {
56
t1 = (
51
- <Button
57
+ <button
58
onClick={() => {
59
setX(10 * y);
60
}}
55
- />
61
+ >
62
+ Click me
63
+ </button>
64
);
65
$[3] = t0;
66
$[4] = t1;
compiler/packages/babel-plugin-react-compiler/src/__tests__/fixtures/compiler/userspace-use-memo-cache.js
+7
-3
@@ -1,4 +1,6 @@
1
-// @runtimeModule="react-forget-runtime"
1
+// @runtimeModule="react-compiler-runtime"
2
+import {useState} from 'react';
3
+
4
function Component(props) {
5
const [x, setX] = useState(1);
6
let y;
@@ -6,10 +8,12 @@ function Component(props) {
8
y = x * 2;
9
}
10
return (
9
- <Button
11
+ <button
12
onClick={() => {
13
setX(10 * y);
12
- }}></Button>
14
+ }}>
15
+ Click me
16
+ </button>
17
);
18
}
19