@samitouri / QOS-React-1 / commits / 5d8587b81c

Add option to compile ReactScript

Sathya Gunasekaran committed Aug 9, 2023 at 14:49 UTC 5d8587b81ce59b7aa709cd22f235f62dfb3bb6a0
10 files changed +80 -15
compiler/forget/packages/babel-plugin-react-forget/src/Babel/BabelPlugin.ts
+2 -2
@@ -5,10 +5,10 @@
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 -/// <reference path="./plugin-syntax-jsx.d.ts" />
8 +/// <reference path="./types.d.ts" />
9
10 -import jsx from "@babel/plugin-syntax-jsx";
10 import type * as BabelCore from "@babel/core";
11 +import jsx from "@babel/plugin-syntax-jsx";
12 import { compileProgram, parsePluginOptions } from "../Entrypoint";
13
14 /**
compiler/forget/packages/babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin.ts
+19 -8
@@ -7,11 +7,12 @@
7
8 import type * as BabelCore from "@babel/core";
9 import { transformFromAstSync } from "@babel/core";
10 -import * as parser from "@babel/parser";
10 +import * as BabelParser from "@babel/parser";
11 +import * as HermesParser from "hermes-parser";
12 import invariant from "invariant";
13 import prettier from "prettier";
13 -import ReactForgetBabelPlugin from "./BabelPlugin";
14 import type { PluginOptions } from "../Entrypoint";
15 +import ReactForgetBabelPlugin from "./BabelPlugin";
16
17 type ReactForgetBabelPluginResult = {
18 ast: BabelCore.BabelFileResult["ast"];
@@ -21,16 +22,26 @@ type ReactForgetBabelPluginResult = {
22
23 export function runReactForgetBabelPlugin(
24 text: string,
24 -
25 file: string,
26 language: "flow" | "typescript",
27 options: PluginOptions | null
28 ): ReactForgetBabelPluginResult {
29 - const ast = parser.parse(text, {
30 - sourceFilename: file,
31 - plugins: ["jsx", language],
32 - sourceType: "module",
33 - });
29 + let ast;
30 + if (language === "flow") {
31 + ast = HermesParser.parse(text, {
32 + babel: true,
33 + flow: "all",
34 + sourceFilename: file,
35 + sourceType: "module",
36 + enableExperimentalComponentSyntax: true,
37 + });
38 + } else {
39 + ast = BabelParser.parse(text, {
40 + sourceFilename: file,
41 + plugins: ["typescript", "jsx"],
42 + sourceType: "module",
43 + });
44 + }
45 const result = transformFromAstSync(ast, text, {
46 filename: file,
47 highlightCode: false,
compiler/forget/packages/babel-plugin-react-forget/src/Babel/types.d.ts renamed
+1
@@ -6,3 +6,4 @@
6 */
7
8 declare module "@babel/plugin-syntax-jsx";
9 +declare module "hermes-parser";
compiler/forget/packages/babel-plugin-react-forget/src/Entrypoint/Options.ts
+8
@@ -87,6 +87,13 @@ export type PluginOptions = {
87 * Defaults to false
88 */
89 noEmit: boolean;
90 +
91 + /**
92 + * Enable to make Forget only compile components written in ReactScript syntax
93 + * and parsed by hermes-parser.
94 + *
95 + */
96 + enableOnlyOnReactScript: boolean;
97 };
98
99 export type Logger = {
@@ -94,6 +101,7 @@ export type Logger = {
101 };
102
103 export const defaultOptions: PluginOptions = {
104 + enableOnlyOnReactScript: false,
105 enableOnlyOnUseForgetDirective: false,
106 panicOnBailout: true,
107 environment: null,
compiler/forget/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts
+6
@@ -329,6 +329,12 @@ function shouldVisitNode(
329 fn: NodePath<t.FunctionDeclaration | t.ArrowFunctionExpression>,
330 pass: CompilerPass
331 ): boolean {
332 + if (pass.opts.enableOnlyOnReactScript) {
333 + if (!fn.get("__componentDeclaration")) {
334 + return false;
335 + }
336 + }
337 +
338 if (pass.opts.enableOnlyOnUseForgetDirective) {
339 const body = fn.get("body");
340 if (!body.isBlockStatement()) {
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/infer-types-through-type-cast.flow.expect.md
-1
@@ -16,7 +16,6 @@ function Component(props) {
16 ## Code
17
18 ```javascript
19 -// @flow
19 function Component(props) {
20 const x = foo();
21 return x;
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactscript-basic.flow.expect.md new
+31
@@ -0,0 +1,31 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @reactScriptDirective
6 +export default component Foo(bar: number) {
7 + return <Bar bar={bar} />;
8 +}
9 +```
10 +
11 +## Code
12 +
13 +```javascript
14 +import { unstable_useMemoCache as useMemoCache } from "react";
15 +export default function Foo(t7) {
16 + const $ = useMemoCache(2);
17 + const { bar } = t7;
18 + const c_0 = $[0] !== bar;
19 + let t0;
20 + if (c_0) {
21 + t0 = <Bar bar={bar} />;
22 + $[0] = bar;
23 + $[1] = t0;
24 + } else {
25 + t0 = $[1];
26 + }
27 + return t0;
28 +}
29 +
30 +```
31 +
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactscript-basic.flow.js new
+4
@@ -0,0 +1,4 @@
1 +// @reactScriptDirective
2 +export default component Foo(bar: number) {
3 + return <Bar bar={bar} />;
4 +}
\ No newline at end of file
compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/type-cast-expression.flow.expect.md
+1 -1
@@ -16,7 +16,7 @@ function Component(props) {
16 ## Code
17
18 ```javascript
19 -import { unstable_useMemoCache as useMemoCache } from "react"; // @flow
19 +import { unstable_useMemoCache as useMemoCache } from "react";
20 type Foo = { bar: string };
21 function Component(props) {
22 const $ = useMemoCache(2);
compiler/forget/packages/snap/src/compiler-worker.ts
+8 -3
@@ -87,6 +87,7 @@ export async function compile(
87
88 // Extract the first line to quickly check for custom test directives
89 const firstLine = input.substring(0, input.indexOf("\n"));
90 + let language = parseLanguage(firstLine);
91
92 let enableOnlyOnUseForgetDirective = false;
93 let gating = null;
@@ -100,6 +101,7 @@ export async function compile(
101 let validateNoSetStateInRender = true;
102 let enableEmitFreeze = null;
103 let enableOptimizeFunctionExpressions = true;
104 + let enableOnlyOnReactScript = false;
105 if (firstLine.indexOf("@forgetDirective") !== -1) {
106 enableOnlyOnUseForgetDirective = true;
107 }
@@ -145,11 +147,12 @@ export async function compile(
147 importSpecifierName: "makeReadOnly",
148 };
149 }
148 -
149 - const language = parseLanguage(firstLine);
150 + if (firstLine.indexOf("@reactScriptDirective") !== -1) {
151 + enableOnlyOnReactScript = true;
152 + language = "flow";
153 + }
154
155 code = runReactForgetBabelPlugin(input, basename, language, {
152 - enableOnlyOnUseForgetDirective,
156 environment: {
157 customHooks: new Map([
158 [
@@ -174,6 +177,8 @@ export async function compile(
177 enableOptimizeFunctionExpressions,
178 assertValidMutableRanges: true,
179 },
180 + enableOnlyOnUseForgetDirective,
181 + enableOnlyOnReactScript,
182 logger: null,
183 gating,
184 instrumentForget,