mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[compiler] Add meta internal option for useMemoCache import (#31654)
Adds `target: 'donotuse_meta_internal'`, which inserts useMemoCache imports directly from `react`. Note that this is only valid for Meta bundles, as others do not [re-export the `c` function](https://github.com/facebook/react/blob/5b0ef217ef32333a8e56f39be04327c89efa346f/packages/react/index.fb.js#L68-L70). ```js // target=donotuse_meta_internal import {c as _c} from 'react'; // target=19 import {c as _c} from 'react/compiler-runtime'; // target=17,18 import {c as _c} from 'react-compiler-runtime'; ``` Meta is a bit special in that react runtime and compiler are guaranteed to be up-to-date and compatible. It also has its own bundling and module resolution logic, which makes importing from `react/compiler-runtime` tricky. I'm also fine with implementing the alternative which adds an internal stub for `react-compiler-runtime` and [bundles](https://github.com/facebook/react/blob/5b0ef217ef32333a8e56f39be04327c89efa346f/scripts/rollup/bundles.js#L120) the runtime for internal builds.
This commit is contained in:
@@ -121,7 +121,22 @@ export type PluginOptions = {
|
||||
target: CompilerReactTarget;
|
||||
};
|
||||
|
||||
const CompilerReactTargetSchema = z.enum(['17', '18', '19']);
|
||||
const CompilerReactTargetSchema = z.union([
|
||||
z.literal('17'),
|
||||
z.literal('18'),
|
||||
z.literal('19'),
|
||||
/**
|
||||
* Used exclusively for Meta apps which are guaranteed to have compatible
|
||||
* react runtime and compiler versions. Note that only the FB-internal bundles
|
||||
* re-export useMemoCache (see
|
||||
* https://github.com/facebook/react/blob/5b0ef217ef32333a8e56f39be04327c89efa346f/packages/react/index.fb.js#L68-L70),
|
||||
* so this option is invalid / creates runtime errors for open-source users.
|
||||
*/
|
||||
z.object({
|
||||
kind: z.literal('donotuse_meta_internal'),
|
||||
runtimeModule: z.string().default('react'),
|
||||
}),
|
||||
]);
|
||||
export type CompilerReactTarget = z.infer<typeof CompilerReactTargetSchema>;
|
||||
|
||||
const CompilationModeSchema = z.enum([
|
||||
|
||||
@@ -1123,30 +1123,23 @@ 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, {
|
||||
function getReactCompilerRuntimeModule(opts: PluginOptions): string {
|
||||
if (opts.target === '19') {
|
||||
return 'react/compiler-runtime'; // from react namespace
|
||||
} else if (opts.target === '17' || opts.target === '18') {
|
||||
return 'react-compiler-runtime'; // npm package
|
||||
} else {
|
||||
CompilerError.invariant(
|
||||
opts.target != null &&
|
||||
opts.target.kind === 'donotuse_meta_internal' &&
|
||||
typeof opts.target.runtimeModule === 'string',
|
||||
{
|
||||
reason: 'Expected target to already be validated',
|
||||
description: null,
|
||||
loc: null,
|
||||
suggestions: null,
|
||||
});
|
||||
},
|
||||
);
|
||||
return opts.target.runtimeModule;
|
||||
}
|
||||
return moduleName;
|
||||
}
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @target="donotuse_meta_internal"
|
||||
|
||||
function Component() {
|
||||
return <div>Hello world</div>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [],
|
||||
isComponent: true,
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { c as _c } from "react"; // @target="donotuse_meta_internal"
|
||||
|
||||
function Component() {
|
||||
const $ = _c(1);
|
||||
let t0;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t0 = <div>Hello world</div>;
|
||||
$[0] = t0;
|
||||
} else {
|
||||
t0 = $[0];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [],
|
||||
isComponent: true,
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// @target="donotuse_meta_internal"
|
||||
|
||||
function Component() {
|
||||
return <div>Hello world</div>;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [],
|
||||
isComponent: true,
|
||||
};
|
||||
@@ -504,6 +504,7 @@ const skipFilter = new Set([
|
||||
// Depends on external functions
|
||||
'idx-method-no-outlining-wildcard',
|
||||
'idx-method-no-outlining',
|
||||
'target-flag-meta-internal',
|
||||
|
||||
// needs to be executed as a module
|
||||
'meta-property',
|
||||
|
||||
@@ -18,6 +18,7 @@ import type {
|
||||
LoggerEvent,
|
||||
PanicThresholdOptions,
|
||||
PluginOptions,
|
||||
CompilerReactTarget,
|
||||
} from 'babel-plugin-react-compiler/src/Entrypoint';
|
||||
import type {Effect, ValueKind} from 'babel-plugin-react-compiler/src/HIR';
|
||||
import type {
|
||||
@@ -55,7 +56,7 @@ function makePluginOptions(
|
||||
let validatePreserveExistingMemoizationGuarantees = false;
|
||||
let customMacros: null | Array<Macro> = null;
|
||||
let validateBlocklistedImports = null;
|
||||
let target = '19' as const;
|
||||
let target: CompilerReactTarget = '19';
|
||||
|
||||
if (firstLine.indexOf('@compilationMode(annotation)') !== -1) {
|
||||
assert(
|
||||
@@ -81,8 +82,15 @@ function makePluginOptions(
|
||||
|
||||
const targetMatch = /@target="([^"]+)"/.exec(firstLine);
|
||||
if (targetMatch) {
|
||||
// @ts-ignore
|
||||
target = targetMatch[1];
|
||||
if (targetMatch[1] === 'donotuse_meta_internal') {
|
||||
target = {
|
||||
kind: targetMatch[1],
|
||||
runtimeModule: 'react',
|
||||
};
|
||||
} else {
|
||||
// @ts-ignore
|
||||
target = targetMatch[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (firstLine.includes('@panicThreshold(none)')) {
|
||||
|
||||
Reference in New Issue
Block a user