Skip to content

Commit da996a1

Browse files
authoredMar 22, 2025
[compiler][be] Move e2e tests to BabelPlugin transformer (#32706)
Clean up jest-e2e setup since #32663 and other features need program context (e.g. changing imports) --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32706). * #32663 * __->__ #32706
1 parent 6b1a2c1 commit da996a1

File tree

6 files changed

+26
-135
lines changed

6 files changed

+26
-135
lines changed
 

‎compiler/packages/babel-plugin-react-compiler/scripts/jest/e2e-forget.config.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,4 @@
77

88
const makeE2EConfig = require('../jest/makeE2EConfig');
99

10-
const config = makeE2EConfig('e2e with forget', true);
11-
config.setupFilesAfterEnv = ['<rootDir>/../scripts/jest/setupEnvE2E.js'];
12-
13-
module.exports = config;
10+
module.exports = makeE2EConfig('e2e with forget', true);

‎compiler/packages/babel-plugin-react-compiler/scripts/jest/makeTransform.ts

+19-115
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,16 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
import {jsx} from '@babel/plugin-syntax-jsx';
98
import babelJest from 'babel-jest';
10-
import {compile} from 'babel-plugin-react-compiler';
11-
import {execSync} from 'child_process';
12-
13-
import type {NodePath, Visitor} from '@babel/traverse';
14-
import type {CallExpression, FunctionDeclaration} from '@babel/types';
15-
import * as t from '@babel/types';
169
import {
17-
EnvironmentConfig,
1810
validateEnvironmentConfig,
11+
EnvironmentConfig,
1912
} from 'babel-plugin-react-compiler';
20-
import {basename} from 'path';
13+
import {execSync} from 'child_process';
14+
15+
import type {NodePath, Visitor} from '@babel/traverse';
16+
import type {CallExpression} from '@babel/types';
17+
import BabelPluginReactCompiler from 'babel-plugin-react-compiler';
2118

2219
/**
2320
* -- IMPORTANT --
@@ -28,10 +25,19 @@ import {basename} from 'path';
2825
const e2eTransformerCacheKey = 1;
2926
const forgetOptions: EnvironmentConfig = validateEnvironmentConfig({
3027
enableAssumeHooksFollowRulesOfReact: true,
31-
enableFunctionOutlining: false,
3228
});
3329
const debugMode = process.env['DEBUG_FORGET_COMPILER'] != null;
3430

31+
const compilerCacheKey = execSync(
32+
'yarn --silent --cwd ../.. hash packages/babel-plugin-react-compiler/dist',
33+
)
34+
.toString()
35+
.trim();
36+
37+
if (debugMode) {
38+
console.log('cachebreaker', compilerCacheKey);
39+
}
40+
3541
module.exports = (useForget: boolean) => {
3642
function createTransformer() {
3743
return babelJest.createTransformer({
@@ -42,15 +48,14 @@ module.exports = (useForget: boolean) => {
4248
plugins: [
4349
useForget
4450
? [
45-
ReactForgetFunctionTransform,
51+
BabelPluginReactCompiler,
4652
{
53+
environment: forgetOptions,
4754
/*
4855
* Jest hashes the babel config as a cache breaker.
4956
* (see https://github.com/jestjs/jest/blob/v29.6.2/packages/babel-jest/src/index.ts#L84)
5057
*/
51-
compilerCacheKey: execSync(
52-
'yarn --silent --cwd ../.. hash packages/babel-plugin-react-compiler/dist',
53-
).toString(),
58+
compilerCacheKey,
5459
transformOptionsCacheKey: forgetOptions,
5560
e2eTransformerCacheKey,
5661
},
@@ -105,104 +110,3 @@ module.exports = (useForget: boolean) => {
105110
createTransformer,
106111
};
107112
};
108-
109-
// Mostly copied from react/scripts/babel/transform-forget.js
110-
function isReactComponentLike(fn: NodePath<FunctionDeclaration>): boolean {
111-
let isReactComponent = false;
112-
let hasNoUseForgetDirective = false;
113-
114-
/*
115-
* React components start with an upper case letter,
116-
* React hooks start with `use`
117-
*/
118-
if (
119-
fn.node.id == null ||
120-
(fn.node.id.name[0].toUpperCase() !== fn.node.id.name[0] &&
121-
!/^use[A-Z0-9]/.test(fn.node.id.name))
122-
) {
123-
return false;
124-
}
125-
126-
fn.traverse({
127-
DirectiveLiteral(path) {
128-
if (path.node.value === 'use no forget') {
129-
hasNoUseForgetDirective = true;
130-
}
131-
},
132-
133-
JSX(path) {
134-
// Is there is a JSX node created in the current function context?
135-
if (path.scope.getFunctionParent()?.path.node === fn.node) {
136-
isReactComponent = true;
137-
}
138-
},
139-
140-
CallExpression(path) {
141-
// Is there hook usage?
142-
if (
143-
path.node.callee.type === 'Identifier' &&
144-
!/^use[A-Z0-9]/.test(path.node.callee.name)
145-
) {
146-
isReactComponent = true;
147-
}
148-
},
149-
});
150-
151-
if (hasNoUseForgetDirective) {
152-
return false;
153-
}
154-
155-
return isReactComponent;
156-
}
157-
158-
function ReactForgetFunctionTransform() {
159-
const compiledFns = new Set();
160-
const visitor = {
161-
FunctionDeclaration(fn: NodePath<FunctionDeclaration>, state: any): void {
162-
if (compiledFns.has(fn.node)) {
163-
return;
164-
}
165-
166-
if (!isReactComponentLike(fn)) {
167-
return;
168-
}
169-
if (debugMode) {
170-
const filename = basename(state.file.opts.filename);
171-
if (fn.node.loc && fn.node.id) {
172-
console.log(
173-
` Compiling ${filename}:${fn.node.loc.start.line}:${fn.node.loc.start.column} ${fn.node.id.name}`,
174-
);
175-
} else {
176-
console.log(` Compiling ${filename} ${fn.node.id?.name}`);
177-
}
178-
}
179-
180-
const compiled = compile(
181-
fn,
182-
forgetOptions,
183-
'Other',
184-
'all_features',
185-
'_c',
186-
null,
187-
null,
188-
null,
189-
);
190-
compiledFns.add(compiled);
191-
192-
const fun = t.functionDeclaration(
193-
compiled.id,
194-
compiled.params,
195-
compiled.body,
196-
compiled.generator,
197-
compiled.async,
198-
);
199-
fn.replaceWith(fun);
200-
fn.skip();
201-
},
202-
};
203-
return {
204-
name: 'react-forget-e2e',
205-
inherits: jsx,
206-
visitor,
207-
};
208-
}

‎compiler/packages/babel-plugin-react-compiler/scripts/jest/setupEnvE2E.js

-16
This file was deleted.

‎compiler/packages/babel-plugin-react-compiler/src/__tests__/e2e/constant-prop.e2e.js

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ globalThis.constantValue = 'global test value';
1212

1313
test('literal-constant-propagation', () => {
1414
function Component() {
15+
'use memo';
1516
const x = 'test value 1';
1617
return <div>{x}</div>;
1718
}
@@ -38,6 +39,7 @@ test('literal-constant-propagation', () => {
3839

3940
test('global-constant-propagation', () => {
4041
function Component() {
42+
'use memo';
4143
const x = constantValue;
4244

4345
return <div>{x}</div>;
@@ -65,6 +67,7 @@ test('global-constant-propagation', () => {
6567

6668
test('lambda-constant-propagation', () => {
6769
function Component() {
70+
'use memo';
6871
const x = 'test value 1';
6972
const getDiv = () => <div>{x}</div>;
7073
return getDiv();
@@ -92,6 +95,7 @@ test('lambda-constant-propagation', () => {
9295

9396
test('lambda-constant-propagation-of-phi-node', () => {
9497
function Component({noopCallback}) {
98+
'use memo';
9599
const x = 'test value 1';
96100
if (constantValue) {
97101
noopCallback();

‎compiler/packages/babel-plugin-react-compiler/src/__tests__/e2e/update-button.e2e.js

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ function Button({label}) {
1616

1717
let currentTheme = 'light';
1818
function useTheme() {
19+
'use memo';
1920
return currentTheme;
2021
}
2122

‎compiler/packages/babel-plugin-react-compiler/src/__tests__/e2e/update-expressions.e2e.js

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import * as React from 'react';
1010
import {expectLogsAndClear, log} from './expectLogs';
1111

1212
function Counter(props) {
13+
'use memo';
1314
let value = props.value;
1415
let a = value++;
1516
expect(a).toBe(props.value); // postfix

0 commit comments

Comments
 (0)
Failed to load comments.