Transform updates to support Flow this annotation syntax (#25918)
Flow introduced a new syntax to annotated the context type of a function, this tries to update the rest and add 1 example usage. - 2b1fb91a55deb9b7b60452cb57184c2f182a42fd already added the changes required for eslint. - Jest transform is updated to use the recommended `hermes-parser` which can parse current and Flow syntax and will be updated in the future. - Rollup uses a new plugin to strip the flow types. This isn't ideal as the npm module is deprecated in favor of using `hermes-parser`, but I couldn't figure out how to integrate that with Rollup.
Jan Kassens committed
Jan 5, 2023 at 15:41 UTC
b83baf63f71669ca7bf222afec305b7a6fd782b7
16 files changed
+95
-8
package.json
+2
@@ -62,11 +62,13 @@
62
"fbjs-scripts": "1.2.0",
63
"filesize": "^6.0.1",
64
"flow-bin": "^0.190.0",
65
+ "flow-remove-types": "^2.196.1",
66
"glob": "^7.1.6",
67
"glob-stream": "^6.1.0",
68
"google-closure-compiler": "^20200517.0.0",
69
"gzip-size": "^5.1.1",
70
"hermes-eslint": "^0.9.0",
71
+ "hermes-parser": "^0.9.0",
72
"jasmine-check": "^1.0.0-rc.0",
73
"jest": "^26.6.3",
74
"jest-cli": "^26.6.3",
packages/react-dom-bindings/src/shared/DOMNamespaces.js
+2
@@ -3,6 +3,8 @@
3
*
4
* This source code is licensed under the MIT license found in the
5
* LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @noflow
8
*/
9
10
export const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
packages/react-dom-bindings/src/shared/ReactControlledValuePropTypes.js
+2
@@ -3,6 +3,8 @@
3
*
4
* This source code is licensed under the MIT license found in the
5
* LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @noflow
8
*/
9
10
const hasReadOnlyValue = {
packages/react-dom-bindings/src/shared/assertValidProps.js
+2
@@ -3,6 +3,8 @@
3
*
4
* This source code is licensed under the MIT license found in the
5
* LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @noflow
8
*/
9
10
import voidElementTags from './voidElementTags';
packages/react-dom/src/test-utils/ReactTestUtils.js
+2
@@ -3,6 +3,8 @@
3
*
4
* This source code is licensed under the MIT license found in the
5
* LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @noflow
8
*/
9
10
import * as React from 'react';
packages/react-native-renderer/src/legacy-events/ResponderEventPlugin.js
+2
@@ -3,6 +3,8 @@
3
*
4
* This source code is licensed under the MIT license found in the
5
* LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @noflow
8
*/
9
10
import {
packages/react-server/src/ReactFizzServer.js
+1
-1
@@ -1668,7 +1668,7 @@ function erroredTask(
1668
}
1669
}
1670
1671
-function abortTaskSoft(task: Task): void {
1671
+function abortTaskSoft(this: Request, task: Task): void {
1672
// This aborts task without aborting the parent boundary that it blocks.
1673
// It's used for when we didn't need this task to complete the tree.
1674
// If task was needed, then it should use abortTask instead.
packages/react/src/ReactForwardRef.js
+2
@@ -3,6 +3,8 @@
3
*
4
* This source code is licensed under the MIT license found in the
5
* LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @noflow
8
*/
9
10
import {REACT_FORWARD_REF_TYPE, REACT_MEMO_TYPE} from 'shared/ReactSymbols';
packages/react/src/ReactMemo.js
+2
@@ -3,6 +3,8 @@
3
*
4
* This source code is licensed under the MIT license found in the
5
* LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @noflow
8
*/
9
10
import {REACT_MEMO_TYPE} from 'shared/ReactSymbols';
packages/shared/forks/invokeGuardedCallbackImpl.www.js
+2
@@ -3,6 +3,8 @@
3
*
4
* This source code is licensed under the MIT license found in the
5
* LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @noflow
8
*/
9
10
// Provided by www
scripts/babel/getComments.js
new
+31
@@ -0,0 +1,31 @@
1
+/**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+'use strict';
9
+
10
+function getComments(path) {
11
+ const allComments = path.hub.file.ast.comments;
12
+ if (path.node.leadingComments) {
13
+ // Babel AST includes comments.
14
+ return path.node.leadingComments;
15
+ }
16
+ // In Hermes AST we need to find the comments by range.
17
+ const comments = [];
18
+ let line = path.node.loc.start.line;
19
+ let i = allComments.length - 1;
20
+ while (i >= 0 && allComments[i].loc.end.line >= line) {
21
+ i--;
22
+ }
23
+ while (i >= 0 && allComments[i].loc.end.line === line - 1) {
24
+ line = allComments[i].loc.start.line;
25
+ comments.unshift(allComments[i]);
26
+ i--;
27
+ }
28
+ return comments;
29
+}
30
+
31
+module.exports = getComments;
scripts/babel/transform-react-version-pragma.js
+4
-2
@@ -2,6 +2,8 @@
2
3
/* eslint-disable no-for-of-loops/no-for-of-loops */
4
5
+const getComments = require('./getComments');
6
+
7
const GATE_VERSION_STR = '@reactVersion ';
8
9
function transform(babel) {
@@ -65,7 +67,7 @@ function transform(babel) {
67
callee.name === 'it' ||
68
callee.name === 'fit'
69
) {
68
- const comments = statement.leadingComments;
70
+ const comments = getComments(path);
71
const condition = buildGateVersionCondition(comments);
72
if (condition !== null) {
73
callee.name =
@@ -87,7 +89,7 @@ function transform(babel) {
89
callee.property.type === 'Identifier' &&
90
callee.property.name === 'only'
91
) {
90
- const comments = statement.leadingComments;
92
+ const comments = getComments(path);
93
const condition = buildGateVersionCondition(comments);
94
if (condition !== null) {
95
statement.expression = t.callExpression(
scripts/babel/transform-test-gate-pragma.js
+4
-2
@@ -2,6 +2,8 @@
2
3
/* eslint-disable no-for-of-loops/no-for-of-loops */
4
5
+const getComments = require('./getComments');
6
+
7
function transform(babel) {
8
const {types: t} = babel;
9
@@ -278,7 +280,7 @@ function transform(babel) {
280
callee.name === 'it' ||
281
callee.name === 'fit'
282
) {
281
- const comments = statement.leadingComments;
283
+ const comments = getComments(path);
284
if (comments !== undefined) {
285
const condition = buildGateCondition(comments);
286
if (condition !== null) {
@@ -304,7 +306,7 @@ function transform(babel) {
306
callee.property.type === 'Identifier' &&
307
callee.property.name === 'only'
308
) {
307
- const comments = statement.leadingComments;
309
+ const comments = getComments(path);
310
if (comments !== undefined) {
311
const condition = buildGateCondition(comments);
312
if (condition !== null) {
scripts/jest/preprocessor.js
+4
-1
@@ -4,6 +4,7 @@ const path = require('path');
4
5
const babel = require('@babel/core');
6
const coffee = require('coffee-script');
7
+const hermesParser = require('hermes-parser');
8
9
const tsPreprocessor = require('./typescript/preprocessor');
10
const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction');
@@ -93,7 +94,9 @@ module.exports = {
94
) {
95
plugins.push(pathToTransformReactVersionPragma);
96
}
96
- return babel.transform(
97
+ let sourceAst = hermesParser.parse(src, {babel: true});
98
+ return babel.transformFromAstSync(
99
+ sourceAst,
100
src,
101
Object.assign(
102
{filename: path.relative(process.cwd(), filePath)},
scripts/rollup/build.js
+11
-1
@@ -4,6 +4,7 @@ const rollup = require('rollup');
4
const babel = require('rollup-plugin-babel');
5
const closure = require('./plugins/closure-plugin');
6
const commonjs = require('rollup-plugin-commonjs');
7
+const flowRemoveTypes = require('flow-remove-types');
8
const prettier = require('rollup-plugin-prettier');
9
const replace = require('rollup-plugin-replace');
10
const stripBanner = require('rollup-plugin-strip-banner');
@@ -99,7 +100,6 @@ const syncWWWPath = argv['sync-www'];
100
// Non-ES2015 stuff applied before closure compiler.
101
const babelPlugins = [
102
// These plugins filter out non-ES2015.
102
- '@babel/plugin-transform-flow-strip-types',
103
['@babel/plugin-proposal-class-properties', {loose: true}],
104
'syntax-trailing-function-commas',
105
// These use loose mode which avoids embedding a runtime.
@@ -325,6 +325,16 @@ function getPlugins(
325
bundleType === RN_FB_PROFILING;
326
const shouldStayReadable = isFBWWWBundle || isRNBundle || forcePrettyOutput;
327
return [
328
+ {
329
+ name: 'rollup-plugin-flow-remove-types',
330
+ transform(code) {
331
+ const transformed = flowRemoveTypes(code);
332
+ return {
333
+ code: transformed.toString(),
334
+ map: transformed.generateMap(),
335
+ };
336
+ },
337
+ },
338
// Shim any modules that need forking in this environment.
339
useForks(forks),
340
// Ensure we don't try to bundle any fbjs modules.
yarn.lock
+22
-1
@@ -7920,6 +7920,20 @@ flow-bin@^0.190.0:
7920
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.190.0.tgz#cfc50e1474facf8150232a6c498fe66a6bb75969"
7921
integrity sha512-Qo3bvN3cmGFXsq63ZxcHFZXQDvgx84fCuq8cXuKk5xbvuebBGwMqS+ku/rH+gEkciRrcTYrXqoSzb9b6ShcoJg==
7922
7923
+flow-parser@^0.196.1:
7924
+ version "0.196.1"
7925
+ resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.196.1.tgz#3c31f102454518f0c68eeb99f57501c2a0c9bff0"
7926
+ integrity sha512-V3yaKHyBWhl+LF6sxgbfqxMlwoFKs8UKh2DYTrGj1AHi9ST7Zyp+9ToF4l9eoL6l/DxdFwCNF3MAJ1vCVrgJmw==
7927
+
7928
+flow-remove-types@^2.196.1:
7929
+ version "2.196.1"
7930
+ resolved "https://registry.yarnpkg.com/flow-remove-types/-/flow-remove-types-2.196.1.tgz#c77ab53679beb1b1ba420c16865cea714a67defc"
7931
+ integrity sha512-pAEe2B/fKtV96MVGWQgmjP5Z1nLeFFe++r83ql1Zj86+p+3IujsbvwxiXCiF/SS6ObbB6TmciCxxd+FsOUyY3Q==
7932
+ dependencies:
7933
+ flow-parser "^0.196.1"
7934
+ pirates "^3.0.2"
7935
+ vlq "^0.2.1"
7936
+
7937
fluent-syntax@0.13.0:
7938
version "0.13.0"
7939
resolved "https://registry.yarnpkg.com/fluent-syntax/-/fluent-syntax-0.13.0.tgz#417144d99cba94ff474c422b3e6623d5a842855a"
@@ -8749,7 +8763,7 @@ hermes-estree@0.9.0:
8763
resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.9.0.tgz#026e0abe6db1dcf50a81a79014b779a83db3b814"
8764
integrity sha512-5DZ7Y0CbHVk8zPqgRCvqp8iw+P05svnQDI1aJFjdqCfXJ/1CZ+8aYpGlhJ29zCG5SE5duGTzSxogAYYI4QqXqw==
8765
8752
-hermes-parser@0.9.0:
8766
+hermes-parser@0.9.0, hermes-parser@^0.9.0:
8767
version "0.9.0"
8768
resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.9.0.tgz#ede3044d50479c61843cef5bbdcea83933d4e4ec"
8769
integrity sha512-IcvJIlAn+9tpHkP+HTsxWKrIdQPp0gvGrrQmxlL4XnNS+Oh6R/Fpxbcoflm2kY3zgQjEvxZxLiK/2+k3/5wsrw==
@@ -12991,6 +13005,13 @@ pinpoint@^1.1.0:
13005
resolved "https://registry.yarnpkg.com/pinpoint/-/pinpoint-1.1.0.tgz#0cf7757a6977f1bf7f6a32207b709e377388e874"
13006
integrity sha1-DPd1eml38b9/ajIge3CeN3OI6HQ=
13007
13008
+pirates@^3.0.2:
13009
+ version "3.0.2"
13010
+ resolved "https://registry.yarnpkg.com/pirates/-/pirates-3.0.2.tgz#7e6f85413fd9161ab4e12b539b06010d85954bb9"
13011
+ integrity sha512-c5CgUJq6H2k6MJz72Ak1F5sN9n9wlSlJyEnwvpm9/y3WB4E3pHBDT2c6PEiS1vyJvq2bUxUAIu0EGf8Cx4Ic7Q==
13012
+ dependencies:
13013
+ node-modules-regexp "^1.0.0"
13014
+
13015
pirates@^4.0.0, pirates@^4.0.1:
13016
version "4.0.1"
13017
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87"