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;