Skip to content

Commit db83038

Browse files
authored
Merge branch 'main' into reactnativetypes-syntax
2 parents 571b688 + 372ec00 commit db83038

File tree

85 files changed

+2861
-547
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+2861
-547
lines changed

CHANGELOG.md

Lines changed: 272 additions & 0 deletions
Large diffs are not rendered by default.

compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,22 @@ export type PluginOptions = {
121121
target: CompilerReactTarget;
122122
};
123123

124-
const CompilerReactTargetSchema = z.enum(['17', '18', '19']);
124+
const CompilerReactTargetSchema = z.union([
125+
z.literal('17'),
126+
z.literal('18'),
127+
z.literal('19'),
128+
/**
129+
* Used exclusively for Meta apps which are guaranteed to have compatible
130+
* react runtime and compiler versions. Note that only the FB-internal bundles
131+
* re-export useMemoCache (see
132+
* https://github.com/facebook/react/blob/5b0ef217ef32333a8e56f39be04327c89efa346f/packages/react/index.fb.js#L68-L70),
133+
* so this option is invalid / creates runtime errors for open-source users.
134+
*/
135+
z.object({
136+
kind: z.literal('donotuse_meta_internal'),
137+
runtimeModule: z.string().default('react'),
138+
}),
139+
]);
125140
export type CompilerReactTarget = z.infer<typeof CompilerReactTargetSchema>;
126141

127142
const CompilationModeSchema = z.enum([

compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Pipeline.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
inferReactivePlaces,
3737
inferReferenceEffects,
3838
inlineImmediatelyInvokedFunctionExpressions,
39+
inferEffectDependencies,
3940
} from '../Inference';
4041
import {
4142
constantPropagation,
@@ -354,6 +355,10 @@ function* runWithEnvironment(
354355
value: hir,
355356
});
356357

358+
if (env.config.inferEffectDependencies) {
359+
inferEffectDependencies(hir);
360+
}
361+
357362
if (env.config.inlineJsxTransform) {
358363
inlineJsxTransform(hir, env.config.inlineJsxTransform);
359364
yield log({

compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Program.ts

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,30 +1123,23 @@ function checkFunctionReferencedBeforeDeclarationAtTopLevel(
11231123
return errors.details.length > 0 ? errors : null;
11241124
}
11251125

1126-
type ReactCompilerRuntimeModule =
1127-
| 'react/compiler-runtime' // from react namespace
1128-
| 'react-compiler-runtime'; // npm package
1129-
function getReactCompilerRuntimeModule(
1130-
opts: PluginOptions,
1131-
): ReactCompilerRuntimeModule {
1132-
let moduleName: ReactCompilerRuntimeModule | null = null;
1133-
switch (opts.target) {
1134-
case '17':
1135-
case '18': {
1136-
moduleName = 'react-compiler-runtime';
1137-
break;
1138-
}
1139-
case '19': {
1140-
moduleName = 'react/compiler-runtime';
1141-
break;
1142-
}
1143-
default:
1144-
CompilerError.invariant(moduleName != null, {
1126+
function getReactCompilerRuntimeModule(opts: PluginOptions): string {
1127+
if (opts.target === '19') {
1128+
return 'react/compiler-runtime'; // from react namespace
1129+
} else if (opts.target === '17' || opts.target === '18') {
1130+
return 'react-compiler-runtime'; // npm package
1131+
} else {
1132+
CompilerError.invariant(
1133+
opts.target != null &&
1134+
opts.target.kind === 'donotuse_meta_internal' &&
1135+
typeof opts.target.runtimeModule === 'string',
1136+
{
11451137
reason: 'Expected target to already be validated',
11461138
description: null,
11471139
loc: null,
11481140
suggestions: null,
1149-
});
1141+
},
1142+
);
1143+
return opts.target.runtimeModule;
11501144
}
1151-
return moduleName;
11521145
}

compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,12 @@ function lowerStatement(
10781078
const left = stmt.get('left');
10791079
const leftLoc = left.node.loc ?? GeneratedSource;
10801080
let test: Place;
1081+
const advanceIterator = lowerValueToTemporary(builder, {
1082+
kind: 'IteratorNext',
1083+
loc: leftLoc,
1084+
iterator: {...iterator},
1085+
collection: {...value},
1086+
});
10811087
if (left.isVariableDeclaration()) {
10821088
const declarations = left.get('declarations');
10831089
CompilerError.invariant(declarations.length === 1, {
@@ -1087,12 +1093,6 @@ function lowerStatement(
10871093
suggestions: null,
10881094
});
10891095
const id = declarations[0].get('id');
1090-
const advanceIterator = lowerValueToTemporary(builder, {
1091-
kind: 'IteratorNext',
1092-
loc: leftLoc,
1093-
iterator: {...iterator},
1094-
collection: {...value},
1095-
});
10961096
const assign = lowerAssignment(
10971097
builder,
10981098
leftLoc,
@@ -1103,13 +1103,19 @@ function lowerStatement(
11031103
);
11041104
test = lowerValueToTemporary(builder, assign);
11051105
} else {
1106-
builder.errors.push({
1107-
reason: `(BuildHIR::lowerStatement) Handle ${left.type} inits in ForOfStatement`,
1108-
severity: ErrorSeverity.Todo,
1109-
loc: left.node.loc ?? null,
1110-
suggestions: null,
1106+
CompilerError.invariant(left.isLVal(), {
1107+
loc: leftLoc,
1108+
reason: 'Expected ForOf init to be a variable declaration or lval',
11111109
});
1112-
return;
1110+
const assign = lowerAssignment(
1111+
builder,
1112+
leftLoc,
1113+
InstructionKind.Reassign,
1114+
left,
1115+
advanceIterator,
1116+
'Assignment',
1117+
);
1118+
test = lowerValueToTemporary(builder, assign);
11131119
}
11141120
builder.terminateWithContinuation(
11151121
{
@@ -1166,6 +1172,11 @@ function lowerStatement(
11661172
const left = stmt.get('left');
11671173
const leftLoc = left.node.loc ?? GeneratedSource;
11681174
let test: Place;
1175+
const nextPropertyTemp = lowerValueToTemporary(builder, {
1176+
kind: 'NextPropertyOf',
1177+
loc: leftLoc,
1178+
value,
1179+
});
11691180
if (left.isVariableDeclaration()) {
11701181
const declarations = left.get('declarations');
11711182
CompilerError.invariant(declarations.length === 1, {
@@ -1175,11 +1186,6 @@ function lowerStatement(
11751186
suggestions: null,
11761187
});
11771188
const id = declarations[0].get('id');
1178-
const nextPropertyTemp = lowerValueToTemporary(builder, {
1179-
kind: 'NextPropertyOf',
1180-
loc: leftLoc,
1181-
value,
1182-
});
11831189
const assign = lowerAssignment(
11841190
builder,
11851191
leftLoc,
@@ -1190,13 +1196,19 @@ function lowerStatement(
11901196
);
11911197
test = lowerValueToTemporary(builder, assign);
11921198
} else {
1193-
builder.errors.push({
1194-
reason: `(BuildHIR::lowerStatement) Handle ${left.type} inits in ForInStatement`,
1195-
severity: ErrorSeverity.Todo,
1196-
loc: left.node.loc ?? null,
1197-
suggestions: null,
1199+
CompilerError.invariant(left.isLVal(), {
1200+
loc: leftLoc,
1201+
reason: 'Expected ForIn init to be a variable declaration or lval',
11981202
});
1199-
return;
1203+
const assign = lowerAssignment(
1204+
builder,
1205+
leftLoc,
1206+
InstructionKind.Reassign,
1207+
left,
1208+
nextPropertyTemp,
1209+
'Assignment',
1210+
);
1211+
test = lowerValueToTemporary(builder, assign);
12001212
}
12011213
builder.terminateWithContinuation(
12021214
{

compiler/packages/babel-plugin-react-compiler/src/HIR/Environment.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,50 @@ const EnvironmentConfigSchema = z.object({
233233

234234
enableFunctionDependencyRewrite: z.boolean().default(true),
235235

236+
/**
237+
* Enables inference of optional dependency chains. Without this flag
238+
* a property chain such as `props?.items?.foo` will infer as a dep on
239+
* just `props`. With this flag enabled, we'll infer that full path as
240+
* the dependency.
241+
*/
242+
enableOptionalDependencies: z.boolean().default(true),
243+
244+
/**
245+
* Enables inference and auto-insertion of effect dependencies. Takes in an array of
246+
* configurable module and import pairs to allow for user-land experimentation. For example,
247+
* [
248+
* {
249+
* module: 'react',
250+
* imported: 'useEffect',
251+
* numRequiredArgs: 1,
252+
* },{
253+
* module: 'MyExperimentalEffectHooks',
254+
* imported: 'useExperimentalEffect',
255+
* numRequiredArgs: 2,
256+
* },
257+
* ]
258+
* would insert dependencies for calls of `useEffect` imported from `react` and calls of
259+
* useExperimentalEffect` from `MyExperimentalEffectHooks`.
260+
*
261+
* `numRequiredArgs` tells the compiler the amount of arguments required to append a dependency
262+
* array to the end of the call. With the configuration above, we'd insert dependencies for
263+
* `useEffect` if it is only given a single argument and it would be appended to the argument list.
264+
*
265+
* numRequiredArgs must always be greater than 0, otherwise there is no function to analyze for dependencies
266+
*
267+
* Still experimental.
268+
*/
269+
inferEffectDependencies: z
270+
.nullable(
271+
z.array(
272+
z.object({
273+
function: ExternalFunctionSchema,
274+
numRequiredArgs: z.number(),
275+
}),
276+
),
277+
)
278+
.default(null),
279+
236280
/**
237281
* Enables inlining ReactElement object literals in place of JSX
238282
* An alternative to the standard JSX transform which replaces JSX with React's jsxProd() runtime
@@ -601,6 +645,29 @@ const testComplexConfigDefaults: PartialEnvironmentConfig = {
601645
source: 'react-compiler-runtime',
602646
importSpecifierName: 'useContext_withSelector',
603647
},
648+
inferEffectDependencies: [
649+
{
650+
function: {
651+
source: 'react',
652+
importSpecifierName: 'useEffect',
653+
},
654+
numRequiredArgs: 1,
655+
},
656+
{
657+
function: {
658+
source: 'shared-runtime',
659+
importSpecifierName: 'useSpecialEffect',
660+
},
661+
numRequiredArgs: 2,
662+
},
663+
{
664+
function: {
665+
source: 'useEffectWrapper',
666+
importSpecifierName: 'default',
667+
},
668+
numRequiredArgs: 1,
669+
},
670+
],
604671
};
605672

606673
/**
@@ -1087,3 +1154,5 @@ export function tryParseExternalFunction(
10871154
suggestions: null,
10881155
});
10891156
}
1157+
1158+
export const DEFAULT_EXPORT = 'default';

0 commit comments

Comments
 (0)