@samitouri / QOS-React-2 / commits / 41c23e87c5

Disable compilation of "Components" inside class methods

Minimal repro extracted from our internal codebase. Our inference mode sees that this arrow function is component-like and attempts to compile it, which then fails because the function accesses `this` which we bailout on.

Joe Savona committed Aug 31, 2023 at 23:16 UTC 41c23e87c52b958f7c93b0f94940abc50a2ead8d
4 files changed +70
compiler/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts
+14
@@ -270,6 +270,20 @@ export function compileProgram(
270 // Main traversal to compile with Forget
271 program.traverse(
272 {
273 + ClassDeclaration(node: NodePath<t.ClassDeclaration>) {
274 + // Don't visit functions defined inside classes, because they
275 + // can reference `this` which is unsafe for compilation
276 + node.skip();
277 + return;
278 + },
279 +
280 + ClassExpression(node: NodePath<t.ClassExpression>) {
281 + // Don't visit functions defined inside classes, because they
282 + // can reference `this` which is unsafe for compilation
283 + node.skip();
284 + return;
285 + },
286 +
287 FunctionDeclaration(
288 fn: NodePath<t.FunctionDeclaration>,
289 pass: CompilerPass
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/class-component-with-render-helper.expect.md new
+41
@@ -0,0 +1,41 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @compilationMode(infer)
6 +class Component {
7 + _renderMessage = () => {
8 + const Message = () => {
9 + const message = this.state.message;
10 + return <div>{message}</div>;
11 + };
12 + return <Message />;
13 + };
14 +
15 + render() {
16 + return this._renderMessage();
17 + }
18 +}
19 +
20 +```
21 +
22 +## Code
23 +
24 +```javascript
25 +// @compilationMode(infer)
26 +class Component {
27 + _renderMessage = () => {
28 + const Message = () => {
29 + const message = this.state.message;
30 + return <div>{message}</div>;
31 + };
32 + return <Message />;
33 + };
34 +
35 + render() {
36 + return this._renderMessage();
37 + }
38 +}
39 +
40 +```
41 +
\ No newline at end of file
compiler/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/class-component-with-render-helper.js new
+14
@@ -0,0 +1,14 @@
1 +// @compilationMode(infer)
2 +class Component {
3 + _renderMessage = () => {
4 + const Message = () => {
5 + const message = this.state.message;
6 + return <div>{message}</div>;
7 + };
8 + return <Message />;
9 + };
10 +
11 + render() {
12 + return this._renderMessage();
13 + }
14 +}
compiler/packages/sprout/src/SproutTodoFilter.ts
+1
@@ -450,6 +450,7 @@ const skipFilter = new Set([
450 "infer-function-expression-component",
451 "infer-function-expression-React-memo-gating",
452 "infer-skip-components-without-hooks-or-jsx",
453 + "class-component-with-render-helper",
454 ]);
455
456 export default skipFilter;