mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Add option to compile ReactScript
This commit is contained in:
@@ -5,10 +5,10 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/// <reference path="./plugin-syntax-jsx.d.ts" />
|
||||
/// <reference path="./types.d.ts" />
|
||||
|
||||
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";
|
||||
|
||||
/**
|
||||
|
||||
+19
-8
@@ -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,
|
||||
|
||||
+1
@@ -6,3 +6,4 @@
|
||||
*/
|
||||
|
||||
declare module "@babel/plugin-syntax-jsx";
|
||||
declare module "hermes-parser";
|
||||
@@ -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,
|
||||
|
||||
@@ -329,6 +329,12 @@ function shouldVisitNode(
|
||||
fn: NodePath<t.FunctionDeclaration | t.ArrowFunctionExpression>,
|
||||
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()) {
|
||||
|
||||
-1
@@ -16,7 +16,6 @@ function Component(props) {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
// @flow
|
||||
function Component(props) {
|
||||
const x = foo();
|
||||
return x;
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @reactScriptDirective
|
||||
export default component Foo(bar: number) {
|
||||
return <Bar bar={bar} />;
|
||||
}
|
||||
```
|
||||
|
||||
## 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 = <Bar bar={bar} />;
|
||||
$[0] = bar;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
// @reactScriptDirective
|
||||
export default component Foo(bar: number) {
|
||||
return <Bar bar={bar} />;
|
||||
}
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user