From 5d8587b81ce59b7aa709cd22f235f62dfb3bb6a0 Mon Sep 17 00:00:00 2001 From: Sathya Gunasekaran Date: Wed, 9 Aug 2023 14:49:29 -0400 Subject: [PATCH] Add option to compile ReactScript --- .../src/Babel/BabelPlugin.ts | 4 +-- .../src/Babel/RunReactForgetBabelPlugin.ts | 27 +++++++++++----- .../{plugin-syntax-jsx.d.ts => types.d.ts} | 1 + .../src/Entrypoint/Options.ts | 8 +++++ .../src/Entrypoint/Program.ts | 6 ++++ ...fer-types-through-type-cast.flow.expect.md | 1 - .../compiler/reactscript-basic.flow.expect.md | 31 +++++++++++++++++++ .../compiler/reactscript-basic.flow.js | 4 +++ .../type-cast-expression.flow.expect.md | 2 +- .../packages/snap/src/compiler-worker.ts | 11 +++++-- 10 files changed, 80 insertions(+), 15 deletions(-) rename compiler/forget/packages/babel-plugin-react-forget/src/Babel/{plugin-syntax-jsx.d.ts => types.d.ts} (88%) create mode 100644 compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactscript-basic.flow.expect.md create mode 100644 compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactscript-basic.flow.js diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/Babel/BabelPlugin.ts b/compiler/forget/packages/babel-plugin-react-forget/src/Babel/BabelPlugin.ts index 3588a84058..6fac2035fe 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/Babel/BabelPlugin.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/Babel/BabelPlugin.ts @@ -5,10 +5,10 @@ * LICENSE file in the root directory of this source tree. */ -/// +/// -import jsx from "@babel/plugin-syntax-jsx"; import type * as BabelCore from "@babel/core"; +import jsx from "@babel/plugin-syntax-jsx"; import { compileProgram, parsePluginOptions } from "../Entrypoint"; /** diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin.ts b/compiler/forget/packages/babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin.ts index ddd955f304..d369309340 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/Babel/RunReactForgetBabelPlugin.ts @@ -7,11 +7,12 @@ import type * as BabelCore from "@babel/core"; import { transformFromAstSync } from "@babel/core"; -import * as parser from "@babel/parser"; +import * as BabelParser from "@babel/parser"; +import * as HermesParser from "hermes-parser"; import invariant from "invariant"; import prettier from "prettier"; -import ReactForgetBabelPlugin from "./BabelPlugin"; import type { PluginOptions } from "../Entrypoint"; +import ReactForgetBabelPlugin from "./BabelPlugin"; type ReactForgetBabelPluginResult = { ast: BabelCore.BabelFileResult["ast"]; @@ -21,16 +22,26 @@ type ReactForgetBabelPluginResult = { export function runReactForgetBabelPlugin( text: string, - file: string, language: "flow" | "typescript", options: PluginOptions | null ): ReactForgetBabelPluginResult { - const ast = parser.parse(text, { - sourceFilename: file, - plugins: ["jsx", language], - sourceType: "module", - }); + let ast; + if (language === "flow") { + ast = HermesParser.parse(text, { + babel: true, + flow: "all", + sourceFilename: file, + sourceType: "module", + enableExperimentalComponentSyntax: true, + }); + } else { + ast = BabelParser.parse(text, { + sourceFilename: file, + plugins: ["typescript", "jsx"], + sourceType: "module", + }); + } const result = transformFromAstSync(ast, text, { filename: file, highlightCode: false, diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/Babel/plugin-syntax-jsx.d.ts b/compiler/forget/packages/babel-plugin-react-forget/src/Babel/types.d.ts similarity index 88% rename from compiler/forget/packages/babel-plugin-react-forget/src/Babel/plugin-syntax-jsx.d.ts rename to compiler/forget/packages/babel-plugin-react-forget/src/Babel/types.d.ts index b85fcc23a1..bd8ea2dc65 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/Babel/plugin-syntax-jsx.d.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/Babel/types.d.ts @@ -6,3 +6,4 @@ */ declare module "@babel/plugin-syntax-jsx"; +declare module "hermes-parser"; diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/Entrypoint/Options.ts b/compiler/forget/packages/babel-plugin-react-forget/src/Entrypoint/Options.ts index ea99ca12da..d1850e56f0 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/Entrypoint/Options.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/Entrypoint/Options.ts @@ -87,6 +87,13 @@ export type PluginOptions = { * Defaults to false */ noEmit: boolean; + + /** + * Enable to make Forget only compile components written in ReactScript syntax + * and parsed by hermes-parser. + * + */ + enableOnlyOnReactScript: boolean; }; export type Logger = { @@ -94,6 +101,7 @@ export type Logger = { }; export const defaultOptions: PluginOptions = { + enableOnlyOnReactScript: false, enableOnlyOnUseForgetDirective: false, panicOnBailout: true, environment: null, diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts b/compiler/forget/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts index 8ddd56d499..b62f707340 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts +++ b/compiler/forget/packages/babel-plugin-react-forget/src/Entrypoint/Program.ts @@ -329,6 +329,12 @@ function shouldVisitNode( fn: NodePath, pass: CompilerPass ): boolean { + if (pass.opts.enableOnlyOnReactScript) { + if (!fn.get("__componentDeclaration")) { + return false; + } + } + if (pass.opts.enableOnlyOnUseForgetDirective) { const body = fn.get("body"); if (!body.isBlockStatement()) { diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/infer-types-through-type-cast.flow.expect.md b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/infer-types-through-type-cast.flow.expect.md index 67de8c28c9..398163bbdd 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/infer-types-through-type-cast.flow.expect.md +++ b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/infer-types-through-type-cast.flow.expect.md @@ -16,7 +16,6 @@ function Component(props) { ## Code ```javascript -// @flow function Component(props) { const x = foo(); return x; diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactscript-basic.flow.expect.md b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactscript-basic.flow.expect.md new file mode 100644 index 0000000000..d6940b0198 --- /dev/null +++ b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactscript-basic.flow.expect.md @@ -0,0 +1,31 @@ + +## Input + +```javascript +// @reactScriptDirective +export default component Foo(bar: number) { + return ; +} +``` + +## Code + +```javascript +import { unstable_useMemoCache as useMemoCache } from "react"; +export default function Foo(t7) { + const $ = useMemoCache(2); + const { bar } = t7; + const c_0 = $[0] !== bar; + let t0; + if (c_0) { + t0 = ; + $[0] = bar; + $[1] = t0; + } else { + t0 = $[1]; + } + return t0; +} + +``` + \ No newline at end of file diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactscript-basic.flow.js b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactscript-basic.flow.js new file mode 100644 index 0000000000..9f51b4b76a --- /dev/null +++ b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/reactscript-basic.flow.js @@ -0,0 +1,4 @@ +// @reactScriptDirective +export default component Foo(bar: number) { + return ; +} \ No newline at end of file diff --git a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/type-cast-expression.flow.expect.md b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/type-cast-expression.flow.expect.md index e55e032231..da7dd118a1 100644 --- a/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/type-cast-expression.flow.expect.md +++ b/compiler/forget/packages/babel-plugin-react-forget/src/__tests__/fixtures/compiler/type-cast-expression.flow.expect.md @@ -16,7 +16,7 @@ function Component(props) { ## Code ```javascript -import { unstable_useMemoCache as useMemoCache } from "react"; // @flow +import { unstable_useMemoCache as useMemoCache } from "react"; type Foo = { bar: string }; function Component(props) { const $ = useMemoCache(2); diff --git a/compiler/forget/packages/snap/src/compiler-worker.ts b/compiler/forget/packages/snap/src/compiler-worker.ts index e02aecb8a5..2449549ae3 100644 --- a/compiler/forget/packages/snap/src/compiler-worker.ts +++ b/compiler/forget/packages/snap/src/compiler-worker.ts @@ -87,6 +87,7 @@ export async function compile( // Extract the first line to quickly check for custom test directives const firstLine = input.substring(0, input.indexOf("\n")); + let language = parseLanguage(firstLine); let enableOnlyOnUseForgetDirective = false; let gating = null; @@ -100,6 +101,7 @@ export async function compile( let validateNoSetStateInRender = true; let enableEmitFreeze = null; let enableOptimizeFunctionExpressions = true; + let enableOnlyOnReactScript = false; if (firstLine.indexOf("@forgetDirective") !== -1) { enableOnlyOnUseForgetDirective = true; } @@ -145,11 +147,12 @@ export async function compile( importSpecifierName: "makeReadOnly", }; } - - const language = parseLanguage(firstLine); + if (firstLine.indexOf("@reactScriptDirective") !== -1) { + enableOnlyOnReactScript = true; + language = "flow"; + } code = runReactForgetBabelPlugin(input, basename, language, { - enableOnlyOnUseForgetDirective, environment: { customHooks: new Map([ [ @@ -174,6 +177,8 @@ export async function compile( enableOptimizeFunctionExpressions, assertValidMutableRanges: true, }, + enableOnlyOnUseForgetDirective, + enableOnlyOnReactScript, logger: null, gating, instrumentForget,