@samitouri / QOS-React / commits / 41c23e87c5
Fork 0

The library for web and native user interfaces.

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;