Migrate Babel from Flow to TypeScript (except Babel parser) (#11578)

Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
Bogdan Savluk 2021-11-25 23:09:13 +01:00 committed by GitHub
parent 473f145b27
commit 0058b7fef4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
162 changed files with 672 additions and 133 deletions

View File

@ -84,7 +84,7 @@ module.exports = {
], ],
excludedFiles: [ excludedFiles: [
// @babel/register is the require() hook, so it will always be CJS-based // @babel/register is the require() hook, so it will always be CJS-based
"packages/babel-register/**/*.js", "packages/babel-register/**/*.{js,ts}",
], ],
rules: { rules: {
"no-restricted-globals": ["error", ...cjsGlobals], "no-restricted-globals": ["error", ...cjsGlobals],

View File

@ -61,7 +61,7 @@ function mapSrcToLib(srcPath) {
function mapToDts(packageName) { function mapToDts(packageName) {
return packageName.replace( return packageName.replace(
/(?<=\\|\/|^)(packages|eslint|codemods)(?=\\|\/)/, /(?<=\\|\/|^)(packages|eslint|codemods)(?=\\|\/)/,
"dts" "dts/$1"
); );
} }

View File

@ -47,7 +47,7 @@ function isOneLinerBlock(context, node) {
); );
} }
function report(context, node, missing) { function report(context, node, missing?) {
const lastToken = context.getSourceCode().getLastToken(node); const lastToken = context.getSourceCode().getLastToken(node);
let message, let message,

View File

@ -2,13 +2,13 @@ import type { PluginObject } from "./validation/plugins";
export default class Plugin { export default class Plugin {
key: string | undefined | null; key: string | undefined | null;
manipulateOptions: ((options: unknown, parserOpts: unknown) => void) | void; manipulateOptions?: (options: unknown, parserOpts: unknown) => void;
post: Function | void; post?: Function;
pre: Function | void; pre?: Function;
visitor: {}; visitor: {};
parserOverride: Function | void; parserOverride?: Function;
generatorOverride: Function | void; generatorOverride?: Function;
options: {}; options: {};

View File

@ -38,7 +38,7 @@ export default class Buffer {
* Get the final string output from the buffer, along with the sourcemap if one exists. * Get the final string output from the buffer, along with the sourcemap if one exists.
*/ */
get(): any { get() {
this._flush(); this._flush();
const map = this._map; const map = this._map;

View File

@ -67,7 +67,7 @@ export function JSXElement(this: Printer, node: t.JSXElement) {
if (open.selfClosing) return; if (open.selfClosing) return;
this.indent(); this.indent();
for (const child of node.children as Array<any>) { for (const child of node.children) {
this.print(child, node); this.print(child, node);
} }
this.dedent(); this.dedent();
@ -109,7 +109,7 @@ export function JSXFragment(this: Printer, node: t.JSXFragment) {
this.print(node.openingFragment, node); this.print(node.openingFragment, node);
this.indent(); this.indent();
for (const child of node.children as Array<any>) { for (const child of node.children) {
this.print(child, node); this.print(child, node);
} }
this.dedent(); this.dedent();

View File

@ -267,7 +267,7 @@ export function VariableDeclaration(
let hasInits = false; let hasInits = false;
// don't add whitespace to loop heads // don't add whitespace to loop heads
if (!isFor(parent)) { if (!isFor(parent)) {
for (const declar of node.declarations as Array<any>) { for (const declar of node.declarations) {
if (declar.init) { if (declar.init) {
// has an init so let's split it up over multiple lines // has an init so let's split it up over multiple lines
hasInits = true; hasInits = true;

View File

@ -246,7 +246,7 @@ export default function generate(
ast: t.Node, ast: t.Node,
opts?: GeneratorOptions, opts?: GeneratorOptions,
code?: string | { [filename: string]: string }, code?: string | { [filename: string]: string },
): any { ) {
const gen = new Generator(ast, opts, code); const gen = new Generator(ast, opts, code);
return gen.generate(); return gen.generate();
} }

View File

@ -375,7 +375,7 @@ class Printer {
* `undefined` will be returned and not `foo` due to the terminator. * `undefined` will be returned and not `foo` due to the terminator.
*/ */
startTerminatorless(isLabel: boolean = false): any { startTerminatorless(isLabel: boolean = false) {
if (isLabel) { if (isLabel) {
this._noLineTerminator = true; this._noLineTerminator = true;
return null; return null;

View File

@ -1,15 +1,17 @@
import explode from "@babel/helper-explode-assignable-expression"; import explode from "@babel/helper-explode-assignable-expression";
import { assignmentExpression, sequenceExpression } from "@babel/types"; import { assignmentExpression, sequenceExpression } from "@babel/types";
import type { Visitor } from "@babel/traverse";
export default function (opts: { build: Function, operator: string }): Object { export default function (opts: { build: Function; operator: string }) {
const { build, operator } = opts; const { build, operator } = opts;
return { const visitor: Visitor = {
AssignmentExpression(path) { AssignmentExpression(path) {
const { node, scope } = path; const { node, scope } = path;
if (node.operator !== operator + "=") return; if (node.operator !== operator + "=") return;
const nodes = []; const nodes = [];
// @ts-expect-error todo(flow->ts)
const exploded = explode(node.left, nodes, this, scope); const exploded = explode(node.left, nodes, this, scope);
nodes.push( nodes.push(
assignmentExpression( assignmentExpression(
@ -28,4 +30,5 @@ export default function (opts: { build: Function, operator: string }): Object {
} }
}, },
}; };
return visitor;
} }

View File

@ -17,6 +17,9 @@
"@babel/helper-annotate-as-pure": "workspace:^", "@babel/helper-annotate-as-pure": "workspace:^",
"@babel/types": "workspace:^" "@babel/types": "workspace:^"
}, },
"devDependencies": {
"@babel/traverse": "workspace:^"
},
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
}, },

View File

@ -24,17 +24,19 @@ import {
thisExpression, thisExpression,
} from "@babel/types"; } from "@babel/types";
import annotateAsPure from "@babel/helper-annotate-as-pure"; import annotateAsPure from "@babel/helper-annotate-as-pure";
import type { Visitor } from "@babel/traverse";
type ElementState = { type ElementState = {
tagExpr: Object, // tag node tagExpr: any; // tag node,
tagName: ?string, // raw string tag name tagName: string | undefined | null; // raw string tag name,
args: Array<Object>, // array of call arguments args: Array<any>; // array of call arguments,
call?: Object, // optional call property that can be set to override the call expression returned call?: any; // optional call property that can be set to override the call expression returned,
pure: boolean, // true if the element can be marked with a #__PURE__ annotation pure: boolean; // true if the element can be marked with a #__PURE__ annotation
callee?: any;
}; };
export default function (opts) { export default function (opts) {
const visitor = {}; const visitor: Visitor = {};
visitor.JSXNamespacedName = function (path) { visitor.JSXNamespacedName = function (path) {
if (opts.throwIfNamespace) { if (opts.throwIfNamespace) {
@ -81,6 +83,7 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
if (node.name === "this" && isReferenced(node, parent)) { if (node.name === "this" && isReferenced(node, parent)) {
return thisExpression(); return thisExpression();
} else if (isValidIdentifier(node.name, false)) { } else if (isValidIdentifier(node.name, false)) {
// @ts-expect-error todo(flow->ts) avoid type unsafe mutations
node.type = "Identifier"; node.type = "Identifier";
} else { } else {
return stringLiteral(node.name); return stringLiteral(node.name);
@ -152,6 +155,7 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`,
if (isIdentifier(tagExpr)) { if (isIdentifier(tagExpr)) {
tagName = tagExpr.name; tagName = tagExpr.name;
} else if (isLiteral(tagExpr)) { } else if (isLiteral(tagExpr)) {
// @ts-expect-error todo(flow->ts) NullLiteral
tagName = tagExpr.value; tagName = tagExpr.value;
} }

View File

@ -19,6 +19,7 @@ import {
isLoose, isLoose,
} from "./features"; } from "./features";
import { assertFieldTransformed } from "./typescript"; import { assertFieldTransformed } from "./typescript";
import type { ParserOptions } from "@babel/parser";
export { FEATURES, enableFeature, injectInitialization }; export { FEATURES, enableFeature, injectInitialization };
@ -38,7 +39,7 @@ interface Options {
feature: number; feature: number;
loose?: boolean; loose?: boolean;
// same as PluginObject.manipulateOptions // same as PluginObject.manipulateOptions
manipulateOptions: (options: unknown, parserOpts: unknown) => void; manipulateOptions: (options: unknown, parserOpts: ParserOptions) => void;
// TODO(flow->ts): change to babel api // TODO(flow->ts): change to babel api
api?: { assumption: (key?: string) => boolean | undefined }; api?: { assumption: (key?: string) => boolean | undefined };
} }

View File

@ -18,7 +18,7 @@ import {
toKeyAlias, toKeyAlias,
} from "@babel/types"; } from "@babel/types";
function toKind(node: Object) { function toKind(node: any) {
if (isClassMethod(node) || isObjectMethod(node)) { if (isClassMethod(node) || isObjectMethod(node)) {
if (node.kind === "get" || node.kind === "set") { if (node.kind === "get" || node.kind === "set") {
return node.kind; return node.kind;
@ -30,18 +30,12 @@ function toKind(node: Object) {
const has = Function.prototype.call.bind(Object.prototype.hasOwnProperty); const has = Function.prototype.call.bind(Object.prototype.hasOwnProperty);
export function push( export function push(mutatorMap: any, node: any, kind: string, file, scope?) {
mutatorMap: Object,
node: Object,
kind: string,
file,
scope?,
): Object {
const alias = toKeyAlias(node); const alias = toKeyAlias(node);
// //
let map = {}; let map = {} as any;
if (has(mutatorMap, alias)) map = mutatorMap[alias]; if (has(mutatorMap, alias)) map = mutatorMap[alias];
mutatorMap[alias] = map; mutatorMap[alias] = map;
@ -79,6 +73,7 @@ export function push(
} else if (isObjectMethod(node) || isClassMethod(node)) { } else if (isObjectMethod(node) || isClassMethod(node)) {
value = functionExpression( value = functionExpression(
null, null,
// @ts-expect-error todo(flow->ts) TSParameterProperty is not assignable to parameter of type 'Identifier | RestElement | Pattern'.
node.params, node.params,
node.body, node.body,
node.generator, node.generator,
@ -110,7 +105,7 @@ export function push(
return map; return map;
} }
export function hasComputed(mutatorMap: Object): boolean { export function hasComputed(mutatorMap: any): boolean {
for (const key of Object.keys(mutatorMap)) { for (const key of Object.keys(mutatorMap)) {
if (mutatorMap[key]._computed) { if (mutatorMap[key]._computed) {
return true; return true;
@ -119,7 +114,7 @@ export function hasComputed(mutatorMap: Object): boolean {
return false; return false;
} }
export function toComputedObjectFromClass(obj: Object): Object { export function toComputedObjectFromClass(obj: any) {
const objExpr = arrayExpression([]); const objExpr = arrayExpression([]);
for (let i = 0; i < obj.properties.length; i++) { for (let i = 0; i < obj.properties.length; i++) {
@ -134,7 +129,7 @@ export function toComputedObjectFromClass(obj: Object): Object {
return objExpr; return objExpr;
} }
export function toClassObject(mutatorMap: Object): Object { export function toClassObject(mutatorMap: any) {
const objExpr = objectExpression([]); const objExpr = objectExpression([]);
Object.keys(mutatorMap).forEach(function (mutatorMapKey) { Object.keys(mutatorMap).forEach(function (mutatorMapKey) {
@ -160,7 +155,7 @@ export function toClassObject(mutatorMap: Object): Object {
return objExpr; return objExpr;
} }
export function toDefineObject(mutatorMap: Object): Object { export function toDefineObject(mutatorMap: any) {
Object.keys(mutatorMap).forEach(function (key) { Object.keys(mutatorMap).forEach(function (key) {
const map = mutatorMap[key]; const map = mutatorMap[key];
if (map.value) map.writable = booleanLiteral(true); if (map.value) map.writable = booleanLiteral(true);

View File

@ -482,8 +482,7 @@ function getLocalExportMetadata(
(initializeReexports || !child.node.source) (initializeReexports || !child.node.source)
) { ) {
if (child.node.declaration) { if (child.node.declaration) {
// todo: flow->ts babel-types node field types const declaration = child.get("declaration");
const declaration = child.get("declaration") as NodePath;
const ids = declaration.getOuterBindingIdentifierPaths(); const ids = declaration.getOuterBindingIdentifierPaths();
Object.keys(ids).forEach(name => { Object.keys(ids).forEach(name => {
if (name === "__esModule") { if (name === "__esModule") {

View File

@ -1,4 +1,19 @@
export function declare(builder) { export function declare<
Args extends
| [any]
| [any, any?]
| [any, any?, any?]
| [any, any]
| [any, any, any?]
| [any, any, any],
Builder extends (...args: Args) => any,
>(
builder: Builder,
// todo(flow->ts) maybe add stricter type for returned function
// reason any is there to not expose exact implementation details in type
// example of issue with this packages/babel-preset-typescript/src/index.ts
): Builder extends (...args: infer A) => any ? (...args: A) => any : never {
// @ts-ignore
return (api, options, dirname) => { return (api, options, dirname) => {
let clonedApi; let clonedApi;
@ -10,6 +25,7 @@ export function declare(builder) {
clonedApi[name] = apiPolyfills[name](clonedApi); clonedApi[name] = apiPolyfills[name](clonedApi);
} }
// @ts-ignore
return builder(clonedApi ?? api, options || {}, dirname); return builder(clonedApi ?? api, options || {}, dirname);
}; };
} }
@ -101,12 +117,9 @@ function throwVersionError(range, version) {
Error.stackTraceLimit = limit; Error.stackTraceLimit = limit;
} }
throw Object.assign( throw Object.assign(err, {
err, code: "BABEL_VERSION_UNSUPPORTED",
({ version,
code: "BABEL_VERSION_UNSUPPORTED", range,
version, } as any);
range,
}: any),
);
} }

View File

@ -30,8 +30,11 @@ const awaitVisitor = {
}; };
export default function ( export default function (
path: NodePath, path: NodePath<any>,
helpers: { wrapAsync: Object, wrapAwait: Object }, helpers: {
wrapAsync: any;
wrapAwait?: any;
},
noNewArrows?: boolean, noNewArrows?: boolean,
) { ) {
path.traverse(awaitVisitor, { path.traverse(awaitVisitor, {

View File

@ -9,6 +9,7 @@ import {
isRestElement, isRestElement,
returnStatement, returnStatement,
} from "@babel/types"; } from "@babel/types";
import type * as t from "@babel/types";
const buildAnonymousExpressionWrapper = template.expression(` const buildAnonymousExpressionWrapper = template.expression(`
(function () { (function () {
@ -37,7 +38,10 @@ const buildDeclarationWrapper = template(`
} }
`); `);
function classOrObjectMethod(path: NodePath, callId: Object) { function classOrObjectMethod(
path: NodePath<t.ClassMethod | t.ClassPrivateMethod | t.ObjectMethod>,
callId: any,
) {
const node = path.node; const node = path.node;
const body = node.body; const body = node.body;
@ -57,12 +61,12 @@ function classOrObjectMethod(path: NodePath, callId: Object) {
node.generator = false; node.generator = false;
// Unwrap the wrapper IIFE's environment so super and this and such still work. // Unwrap the wrapper IIFE's environment so super and this and such still work.
path (
.get("body.body.0.argument.callee.arguments.0") path.get("body.body.0.argument.callee.arguments.0") as NodePath
.unwrapFunctionEnvironment(); ).unwrapFunctionEnvironment();
} }
function plainFunction(path: NodePath, callId: Object, noNewArrows: boolean) { function plainFunction(path: NodePath<any>, callId: any, noNewArrows: boolean) {
const node = path.node; const node = path.node;
const isDeclaration = path.isFunctionDeclaration(); const isDeclaration = path.isFunctionDeclaration();
const functionId = node.id; const functionId = node.id;
@ -109,6 +113,7 @@ function plainFunction(path: NodePath, callId: Object, noNewArrows: boolean) {
path.replaceWith(container[0]); path.replaceWith(container[0]);
path.insertAfter(container[1]); path.insertAfter(container[1]);
} else { } else {
// @ts-expect-error todo(flow->ts) separate `wrapper` for `isDeclaration` and `else` branches
const retFunction = container.callee.body.body[1].argument; const retFunction = container.callee.body.body[1].argument;
if (!functionId) { if (!functionId) {
nameFunction({ nameFunction({
@ -120,6 +125,7 @@ function plainFunction(path: NodePath, callId: Object, noNewArrows: boolean) {
if (!retFunction || retFunction.id || node.params.length) { if (!retFunction || retFunction.id || node.params.length) {
// we have an inferred function id or params so we need this wrapper // we have an inferred function id or params so we need this wrapper
// @ts-expect-error todo(flow->ts) separate `wrapper` for `isDeclaration` and `else` branches
path.replaceWith(container); path.replaceWith(container);
} else { } else {
// we can omit this wrapper as the conditions it protects for do not apply // we can omit this wrapper as the conditions it protects for do not apply
@ -130,7 +136,7 @@ function plainFunction(path: NodePath, callId: Object, noNewArrows: boolean) {
export default function wrapFunction( export default function wrapFunction(
path: NodePath, path: NodePath,
callId: Object, callId: any,
// TODO(Babel 8): Consider defaulting to false for spec compliancy // TODO(Babel 8): Consider defaulting to false for spec compliancy
noNewArrows: boolean = true, noNewArrows: boolean = true,
) { ) {

View File

@ -67,6 +67,7 @@ program.option(
program.option("-w, --plugins [string]", "", collect); program.option("-w, --plugins [string]", "", collect);
program.option("-b, --presets [string]", "", collect); program.option("-b, --presets [string]", "", collect);
declare const PACKAGE_JSON: { name: string; version: string };
program.version(PACKAGE_JSON.version); program.version(PACKAGE_JSON.version);
program.usage("[options] [ -e script | script.js ] [arguments]"); program.usage("[options] [ -e script | script.js ] [arguments]");
program.parse(process.argv); program.parse(process.argv);
@ -144,17 +145,26 @@ if (program.eval || program.print) {
let code = program.eval; let code = program.eval;
if (!code || code === true) code = program.print; if (!code || code === true) code = program.print;
// @ts-expect-error todo(flow->ts)
global.__filename = "[eval]"; global.__filename = "[eval]";
// @ts-expect-error todo(flow->ts)
global.__dirname = process.cwd(); global.__dirname = process.cwd();
// @ts-expect-error todo(flow->ts)
const module = new Module(global.__filename); const module = new Module(global.__filename);
// @ts-expect-error todo(flow->ts)
module.filename = global.__filename; module.filename = global.__filename;
// @ts-expect-error todo(flow->ts)
module.paths = Module._nodeModulePaths(global.__dirname); module.paths = Module._nodeModulePaths(global.__dirname);
// @ts-expect-error todo(flow->ts)
global.exports = module.exports; global.exports = module.exports;
// @ts-expect-error todo(flow->ts)
global.module = module; global.module = module;
// @ts-expect-error todo(flow->ts)
global.require = module.require.bind(module); global.require = module.require.bind(module);
// @ts-expect-error todo(flow->ts)
const result = _eval(code, global.__filename); const result = _eval(code, global.__filename);
if (program.print) { if (program.print) {
const output = typeof result === "string" ? result : inspect(result); const output = typeof result === "string" ? result : inspect(result);

View File

@ -61,6 +61,7 @@ export default function (path, { getAsyncIterator }) {
}); });
// remove async function wrapper // remove async function wrapper
// @ts-expect-error todo(flow->ts) improve type annotation for buildForAwait
template = template.body.body; template = template.body.body;
const isLabeledParent = t.isLabeledStatement(parent); const isLabeledParent = t.isLabeledStatement(parent);

View File

@ -28,7 +28,9 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "workspace:^", "@babel/core": "workspace:^",
"@babel/helper-plugin-test-runner": "workspace:^" "@babel/helper-plugin-test-runner": "workspace:^",
"@babel/traverse": "workspace:^",
"@babel/types": "workspace:^"
}, },
"homepage": "https://babel.dev/docs/en/next/babel-plugin-proposal-class-static-block", "homepage": "https://babel.dev/docs/en/next/babel-plugin-proposal-class-static-block",
"engines": { "engines": {

View File

@ -6,11 +6,13 @@ import {
FEATURES, FEATURES,
} from "@babel/helper-create-class-features-plugin"; } from "@babel/helper-create-class-features-plugin";
import type * as t from "@babel/types";
import type { NodePath } from "@babel/traverse";
/** /**
* Generate a uid that is not in `denyList` * Generate a uid that is not in `denyList`
* *
* @param {*} scope * @param {*} scope
* @param {Set<string>} a deny list that the generated uid should avoid * @param {Set<string>} denyList a deny list that the generated uid should avoid
* @returns * @returns
*/ */
function generateUid(scope, denyList: Set<string>) { function generateUid(scope, denyList: Set<string>) {
@ -41,9 +43,9 @@ export default declare(({ types: t, template, assertVersion }) => {
// Run on ClassBody and not on class so that if @babel/helper-create-class-features-plugin // Run on ClassBody and not on class so that if @babel/helper-create-class-features-plugin
// is enabled it can generte optimized output without passing from the intermediate // is enabled it can generte optimized output without passing from the intermediate
// private fields representation. // private fields representation.
ClassBody(classBody: NodePath<Class>) { ClassBody(classBody: NodePath<t.ClassBody>) {
const { scope } = classBody; const { scope } = classBody;
const privateNames = new Set(); const privateNames = new Set<string>();
const body = classBody.get("body"); const body = classBody.get("body");
for (const path of body) { for (const path of body) {
if (path.isPrivate()) { if (path.isPrivate()) {
@ -60,7 +62,9 @@ export default declare(({ types: t, template, assertVersion }) => {
path.replaceWith( path.replaceWith(
t.classPrivateProperty( t.classPrivateProperty(
staticBlockRef, staticBlockRef,
template.expression.ast`(() => { ${path.node.body} })()`, template.expression.ast`(() => { ${
(path.node as t.StaticBlock).body
} })()`,
[], [],
/* static */ true, /* static */ true,
), ),

View File

@ -30,6 +30,7 @@
"devDependencies": { "devDependencies": {
"@babel/core": "workspace:^", "@babel/core": "workspace:^",
"@babel/helper-plugin-test-runner": "workspace:^", "@babel/helper-plugin-test-runner": "workspace:^",
"@babel/traverse": "workspace:^",
"babel-plugin-polyfill-es-shims": "^0.6.0", "babel-plugin-polyfill-es-shims": "^0.6.0",
"object.getownpropertydescriptors": "^2.1.1" "object.getownpropertydescriptors": "^2.1.1"
}, },

View File

@ -1,18 +1,19 @@
// Fork of https://github.com/loganfsmyth/babel-plugin-proposal-decorators-legacy // Fork of https://github.com/loganfsmyth/babel-plugin-proposal-decorators-legacy
import { template, types as t } from "@babel/core"; import { template, types as t } from "@babel/core";
import type { Visitor } from "@babel/traverse";
const buildClassDecorator = template(` const buildClassDecorator = template(`
DECORATOR(CLASS_REF = INNER) || CLASS_REF; DECORATOR(CLASS_REF = INNER) || CLASS_REF;
`); `) as (replacements: { DECORATOR; CLASS_REF; INNER }) => t.ExpressionStatement;
const buildClassPrototype = template(` const buildClassPrototype = template(`
CLASS_REF.prototype; CLASS_REF.prototype;
`); `) as (replacements: { CLASS_REF }) => t.ExpressionStatement;
const buildGetDescriptor = template(` const buildGetDescriptor = template(`
Object.getOwnPropertyDescriptor(TARGET, PROPERTY); Object.getOwnPropertyDescriptor(TARGET, PROPERTY);
`); `) as (replacements: { TARGET; PROPERTY }) => t.ExpressionStatement;
const buildGetObjectInitializer = template(` const buildGetObjectInitializer = template(`
(TEMP = Object.getOwnPropertyDescriptor(TARGET, PROPERTY), (TEMP = TEMP ? TEMP.value : undefined), { (TEMP = Object.getOwnPropertyDescriptor(TARGET, PROPERTY), (TEMP = TEMP ? TEMP.value : undefined), {
@ -23,7 +24,7 @@ const buildGetObjectInitializer = template(`
return TEMP; return TEMP;
} }
}) })
`); `) as (replacements: { TEMP; TARGET; PROPERTY }) => t.ExpressionStatement;
const WARNING_CALLS = new WeakSet(); const WARNING_CALLS = new WeakSet();
@ -241,6 +242,7 @@ export default {
replacement, replacement,
t.exportNamedDeclaration(null, [ t.exportNamedDeclaration(null, [
t.exportSpecifier( t.exportSpecifier(
// @ts-expect-error todo(flow->ts) might be add more specific return type for decoratedClassToExpression
t.cloneNode(replacement.declarations[0].id), t.cloneNode(replacement.declarations[0].id),
t.identifier("default"), t.identifier("default"),
), ),
@ -263,7 +265,7 @@ export default {
// class decorators, and a second pass to process method decorators. // class decorators, and a second pass to process method decorators.
const decoratedClass = const decoratedClass =
applyEnsureOrdering(path) || applyEnsureOrdering(path) ||
applyClassDecorators(path, state) || applyClassDecorators(path) ||
applyMethodDecorators(path, state); applyMethodDecorators(path, state);
if (decoratedClass) path.replaceWith(decoratedClass); if (decoratedClass) path.replaceWith(decoratedClass);
@ -280,12 +282,17 @@ export default {
path.replaceWith( path.replaceWith(
t.callExpression(state.addHelper("initializerDefineProperty"), [ t.callExpression(state.addHelper("initializerDefineProperty"), [
// @ts-expect-error todo(flow->ts) typesafe NodePath.get
t.cloneNode(path.get("left.object").node), t.cloneNode(path.get("left.object").node),
t.stringLiteral( t.stringLiteral(
// @ts-expect-error todo(flow->ts) typesafe NodePath.get
path.get("left.property").node.name || path.get("left.property").node.name ||
// @ts-expect-error todo(flow->ts) typesafe NodePath.get
path.get("left.property").node.value, path.get("left.property").node.value,
), ),
// @ts-expect-error todo(flow->ts)
t.cloneNode(path.get("right.arguments")[0].node), t.cloneNode(path.get("right.arguments")[0].node),
// @ts-expect-error todo(flow->ts)
t.cloneNode(path.get("right.arguments")[1].node), t.cloneNode(path.get("right.arguments")[1].node),
]), ]),
); );
@ -297,6 +304,7 @@ export default {
// If the class properties plugin isn't enabled, this line will add an unused helper // If the class properties plugin isn't enabled, this line will add an unused helper
// to the code. It's not ideal, but it's ok since the configuration is not valid anyway. // to the code. It's not ideal, but it's ok since the configuration is not valid anyway.
// @ts-expect-error todo(flow->ts) check that `callee` is Identifier
if (path.node.callee.name !== state.addHelper("defineProperty").name) { if (path.node.callee.name !== state.addHelper("defineProperty").name) {
return; return;
} }
@ -305,9 +313,11 @@ export default {
t.callExpression(state.addHelper("initializerDefineProperty"), [ t.callExpression(state.addHelper("initializerDefineProperty"), [
t.cloneNode(path.get("arguments")[0].node), t.cloneNode(path.get("arguments")[0].node),
t.cloneNode(path.get("arguments")[1].node), t.cloneNode(path.get("arguments")[1].node),
// @ts-expect-error todo(flow->ts)
t.cloneNode(path.get("arguments.2.arguments")[0].node), t.cloneNode(path.get("arguments.2.arguments")[0].node),
// @ts-expect-error todo(flow->ts)
t.cloneNode(path.get("arguments.2.arguments")[1].node), t.cloneNode(path.get("arguments.2.arguments")[1].node),
]), ]),
); );
}, },
}; } as Visitor<any>;

View File

@ -16,6 +16,8 @@ the @babel/plugin-syntax-dynamic-import plugin and let your
bundler handle dynamic imports. bundler handle dynamic imports.
`; `;
declare const PACKAGE_JSON: { name: string; version: string };
export default declare(api => { export default declare(api => {
api.assertVersion(7); api.assertVersion(7);

View File

@ -34,6 +34,7 @@ export default declare(api => {
lhs.property = t.assignmentExpression( lhs.property = t.assignmentExpression(
"=", "=",
t.cloneNode(memo), t.cloneNode(memo),
// @ts-expect-error todo(flow->ts): property can be t.PrivateName
property, property,
); );
} }

View File

@ -25,7 +25,9 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "workspace:^", "@babel/core": "workspace:^",
"@babel/helper-plugin-test-runner": "workspace:^" "@babel/helper-plugin-test-runner": "workspace:^",
"@babel/traverse": "workspace:^",
"@babel/types": "workspace:^"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"

View File

@ -1,5 +1,7 @@
import { declare } from "@babel/helper-plugin-utils"; import { declare } from "@babel/helper-plugin-utils";
import syntaxNumericSeparator from "@babel/plugin-syntax-numeric-separator"; import syntaxNumericSeparator from "@babel/plugin-syntax-numeric-separator";
import type { NodePath } from "@babel/traverse";
import type * as t from "@babel/types";
/** /**
* Given a bigIntLiteral or NumericLiteral, remove numeric * Given a bigIntLiteral or NumericLiteral, remove numeric
@ -7,9 +9,11 @@ import syntaxNumericSeparator from "@babel/plugin-syntax-numeric-separator";
* *
* @param {NodePath<BigIntLiteral | NumericLiteral>} { node }: A Babel AST node path * @param {NodePath<BigIntLiteral | NumericLiteral>} { node }: A Babel AST node path
*/ */
function remover({ node }: NodePath<BigIntLiteral | NumericLiteral>) { function remover({ node }: NodePath<t.BigIntLiteral | t.NumericLiteral>) {
const { extra } = node; const { extra } = node;
// @ts-expect-error todo(flow->ts)
if (extra?.raw?.includes("_")) { if (extra?.raw?.includes("_")) {
// @ts-expect-error todo(flow->ts)
extra.raw = extra.raw.replace(/_/g, ""); extra.raw = extra.raw.replace(/_/g, "");
} }
} }

View File

@ -27,7 +27,8 @@
"devDependencies": { "devDependencies": {
"@babel/core": "workspace:^", "@babel/core": "workspace:^",
"@babel/helper-plugin-test-runner": "workspace:^", "@babel/helper-plugin-test-runner": "workspace:^",
"@babel/plugin-transform-block-scoping": "workspace:^" "@babel/plugin-transform-block-scoping": "workspace:^",
"@babel/traverse": "workspace:^"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"

View File

@ -1,4 +1,5 @@
import { types as t, template } from "@babel/core"; import { types as t, template } from "@babel/core";
import type { NodePath } from "@babel/traverse";
import { import {
skipTransparentExprWrapperNodes, skipTransparentExprWrapperNodes,
skipTransparentExprWrappers, skipTransparentExprWrappers,
@ -48,7 +49,7 @@ export function transform(
{ {
pureGetters, pureGetters,
noDocumentAll, noDocumentAll,
}: { pureGetters: boolean, noDocumentAll: boolean }, }: { pureGetters: boolean; noDocumentAll: boolean },
) { ) {
const { scope } = path; const { scope } = path;
// maybeWrapped points to the outermost transparent expression wrapper // maybeWrapped points to the outermost transparent expression wrapper
@ -69,7 +70,7 @@ export function transform(
// Replace `function (a, x = a.b?.c) {}` to `function (a, x = (() => a.b?.c)() ){}` // Replace `function (a, x = a.b?.c) {}` to `function (a, x = (() => a.b?.c)() ){}`
// so the temporary variable can be injected in correct scope // so the temporary variable can be injected in correct scope
if (scope.path.isPattern() && needsMemoize(optionalPath)) { if (scope.path.isPattern() && needsMemoize(optionalPath)) {
path.replaceWith(template.ast`(() => ${path.node})()`); path.replaceWith(template.ast`(() => ${path.node})()` as t.Statement);
// The injected optional chain will be queued and eventually transformed when visited // The injected optional chain will be queued and eventually transformed when visited
return; return;
} }
@ -83,15 +84,19 @@ export function transform(
} }
if (optionalPath.isOptionalMemberExpression()) { if (optionalPath.isOptionalMemberExpression()) {
// @ts-expect-error todo(flow->ts) avoid changing more type
optionalPath.node.type = "MemberExpression"; optionalPath.node.type = "MemberExpression";
// @ts-expect-error todo(flow->ts)
optionalPath = skipTransparentExprWrappers(optionalPath.get("object")); optionalPath = skipTransparentExprWrappers(optionalPath.get("object"));
} else if (optionalPath.isOptionalCallExpression()) { } else if (optionalPath.isOptionalCallExpression()) {
// @ts-expect-error todo(flow->ts) avoid changing more type
optionalPath.node.type = "CallExpression"; optionalPath.node.type = "CallExpression";
// @ts-expect-error todo(flow->ts)
optionalPath = skipTransparentExprWrappers(optionalPath.get("callee")); optionalPath = skipTransparentExprWrappers(optionalPath.get("callee"));
} }
} }
let replacementPath = path; let replacementPath: NodePath<any> = path;
if (parentPath.isUnaryExpression({ operator: "delete" })) { if (parentPath.isUnaryExpression({ operator: "delete" })) {
replacementPath = parentPath; replacementPath = parentPath;
isDeleteOperation = true; isDeleteOperation = true;
@ -145,7 +150,7 @@ export function transform(
// Otherwise, we need to memoize the context object, and change the call into a Function#call. // Otherwise, we need to memoize the context object, and change the call into a Function#call.
// `a.?b.?()` translates roughly to `(_b = _a.b) != null && _b.call(_a)` // `a.?b.?()` translates roughly to `(_b = _a.b) != null && _b.call(_a)`
const { object } = chain; const { object } = chain;
let context = scope.maybeGenerateMemoised(object); let context: t.Expression = scope.maybeGenerateMemoised(object);
if (context) { if (context) {
chain.object = t.assignmentExpression("=", context, object); chain.object = t.assignmentExpression("=", context, object);
} else if (t.isSuper(object)) { } else if (t.isSuper(object)) {
@ -194,6 +199,7 @@ export function transform(
t.logicalExpression("&&", nonNullishCheck, replacement), t.logicalExpression("&&", nonNullishCheck, replacement),
); );
replacementPath = skipTransparentExprWrappers( replacementPath = skipTransparentExprWrappers(
// @ts-expect-error todo(flow->ts)
replacementPath.get("right"), replacementPath.get("right"),
); );
} else { } else {
@ -207,6 +213,7 @@ export function transform(
t.conditionalExpression(nullishCheck, returnValue, replacement), t.conditionalExpression(nullishCheck, returnValue, replacement),
); );
replacementPath = skipTransparentExprWrappers( replacementPath = skipTransparentExprWrappers(
// @ts-expect-error todo(flow->ts)
replacementPath.get("alternate"), replacementPath.get("alternate"),
); );
} }

View File

@ -1,3 +1,4 @@
import type { NodePath } from "@babel/traverse";
import { isTransparentExprWrapper } from "@babel/helper-skip-transparent-expression-wrappers"; import { isTransparentExprWrapper } from "@babel/helper-skip-transparent-expression-wrappers";
/** /**
* Test if a NodePath will be cast to boolean when evaluated. * Test if a NodePath will be cast to boolean when evaluated.
@ -58,7 +59,7 @@ export function willPathCastToBoolean(path: NodePath): boolean {
export function findOutermostTransparentParent(path: NodePath): NodePath { export function findOutermostTransparentParent(path: NodePath): NodePath {
let maybeWrapped = path; let maybeWrapped = path;
path.findParent(p => { path.findParent(p => {
if (!isTransparentExprWrapper(p)) return true; if (!isTransparentExprWrapper(p.node)) return true;
maybeWrapped = p; maybeWrapped = p;
}); });
return maybeWrapped; return maybeWrapped;

View File

@ -20,6 +20,7 @@ import { types as t } from "@babel/core";
import { addNamed, isModule } from "@babel/helper-module-imports"; import { addNamed, isModule } from "@babel/helper-module-imports";
import { OptionValidator } from "@babel/helper-validator-option"; import { OptionValidator } from "@babel/helper-validator-option";
declare const PACKAGE_JSON: { name: string; version: string };
const v = new OptionValidator(PACKAGE_JSON.name); const v = new OptionValidator(PACKAGE_JSON.name);
export default declare((api, options) => { export default declare((api, options) => {

View File

@ -25,7 +25,8 @@
"devDependencies": { "devDependencies": {
"@babel/core": "workspace:^", "@babel/core": "workspace:^",
"@babel/helper-plugin-test-runner": "workspace:^", "@babel/helper-plugin-test-runner": "workspace:^",
"@babel/traverse": "workspace:^" "@babel/traverse": "workspace:^",
"@babel/types": "workspace:^"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"

View File

@ -1,5 +1,6 @@
import { declare } from "@babel/helper-plugin-utils"; import { declare } from "@babel/helper-plugin-utils";
import type NodePath from "@babel/traverse"; import type { NodePath } from "@babel/traverse";
import type * as t from "@babel/types";
export default declare((api, options) => { export default declare((api, options) => {
api.assertVersion(7); api.assertVersion(7);
@ -10,9 +11,7 @@ export default declare((api, options) => {
name: "transform-arrow-functions", name: "transform-arrow-functions",
visitor: { visitor: {
ArrowFunctionExpression( ArrowFunctionExpression(path: NodePath<t.ArrowFunctionExpression>) {
path: NodePath<BabelNodeArrowFunctionExpression>,
) {
// In some conversion cases, it may have already been converted to a function while this callback // In some conversion cases, it may have already been converted to a function while this callback
// was queued up. // was queued up.
if (!path.isArrowFunctionExpression()) return; if (!path.isArrowFunctionExpression()) return;

View File

@ -5,7 +5,7 @@ export default declare(api => {
api.assertVersion(7); api.assertVersion(7);
function statementList(key, path) { function statementList(key, path) {
const paths: Array = path.get(key); const paths = path.get(key);
for (const path of paths) { for (const path of paths) {
const func = path.node; const func = path.node;
@ -16,6 +16,7 @@ export default declare(api => {
]); ]);
// hoist it up above everything else // hoist it up above everything else
// @ts-expect-error todo(flow->ts): avoid mutations
declar._blockHoist = 2; declar._blockHoist = 2;
// todo: name this // todo: name this

View File

@ -920,7 +920,7 @@ class BlockScoping {
* later on. * later on.
*/ */
checkLoop(): any { checkLoop() {
const state: LoopVisitorState = { const state: LoopVisitorState = {
hasBreakContinue: false, hasBreakContinue: false,
ignoreLabeless: false, ignoreLabeless: false,

View File

@ -32,7 +32,7 @@ export default declare((api, options) => {
function pushAssign(objId, prop, body) { function pushAssign(objId, prop, body) {
if (prop.kind === "get" && prop.kind === "set") { if (prop.kind === "get" && prop.kind === "set") {
pushMutatorDefine(objId, prop, body); pushMutatorDefine(objId, prop);
} else { } else {
body.push( body.push(
t.expressionStatement( t.expressionStatement(
@ -43,6 +43,7 @@ export default declare((api, options) => {
prop.key, prop.key,
prop.computed || t.isLiteral(prop.key), prop.computed || t.isLiteral(prop.key),
), ),
// @ts-expect-error todo(flow->ts): double-check type error
getValue(prop), getValue(prop),
), ),
), ),
@ -65,12 +66,12 @@ export default declare((api, options) => {
} }
body.push( body.push(
...buildMutatorMapAssign({ ...(buildMutatorMapAssign({
MUTATOR_MAP_REF: getMutatorId(), MUTATOR_MAP_REF: getMutatorId(),
KEY: t.cloneNode(key), KEY: t.cloneNode(key),
VALUE: getValue(prop), VALUE: getValue(prop),
KIND: t.identifier(prop.kind), KIND: t.identifier(prop.kind),
}), }) as t.Statement[]),
); );
} }
@ -122,7 +123,7 @@ export default declare((api, options) => {
exit(path, state) { exit(path, state) {
const { node, parent, scope } = path; const { node, parent, scope } = path;
let hasComputed = false; let hasComputed = false;
for (const prop of (node.properties: Array<Object>)) { for (const prop of node.properties) {
hasComputed = prop.computed === true; hasComputed = prop.computed === true;
if (hasComputed) break; if (hasComputed) break;
} }
@ -194,6 +195,7 @@ export default declare((api, options) => {
); );
} }
// @ts-expect-error todo(flow->ts) `void` should not be used as variable
if (single) { if (single) {
path.replaceWith(single); path.replaceWith(single);
} else { } else {

View File

@ -24,7 +24,8 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "workspace:^", "@babel/core": "workspace:^",
"@babel/helper-plugin-test-runner": "workspace:^" "@babel/helper-plugin-test-runner": "workspace:^",
"@babel/traverse": "workspace:^"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"

View File

@ -1,5 +1,6 @@
import { declare } from "@babel/helper-plugin-utils"; import { declare } from "@babel/helper-plugin-utils";
import { types as t } from "@babel/core"; import { types as t } from "@babel/core";
import type { Scope } from "@babel/traverse";
export default declare((api, options) => { export default declare((api, options) => {
api.assertVersion(7); api.assertVersion(7);
@ -23,7 +24,7 @@ export default declare((api, options) => {
*/ */
function variableDeclarationHasPattern(node) { function variableDeclarationHasPattern(node) {
for (const declar of (node.declarations: Array)) { for (const declar of node.declarations) {
if (t.isPattern(declar.id)) { if (t.isPattern(declar.id)) {
return true; return true;
} }
@ -36,7 +37,7 @@ export default declare((api, options) => {
*/ */
function hasRest(pattern) { function hasRest(pattern) {
for (const elem of (pattern.elements: Array)) { for (const elem of pattern.elements) {
if (t.isRestElement(elem)) { if (t.isRestElement(elem)) {
return true; return true;
} }
@ -49,7 +50,7 @@ export default declare((api, options) => {
*/ */
function hasObjectRest(pattern) { function hasObjectRest(pattern) {
for (const elem of (pattern.properties: Array)) { for (const elem of pattern.properties) {
if (t.isRestElement(elem)) { if (t.isRestElement(elem)) {
return true; return true;
} }
@ -77,6 +78,15 @@ export default declare((api, options) => {
}; };
class DestructuringTransformer { class DestructuringTransformer {
private blockHoist: any;
private operator: any;
arrays: any;
private nodes: any;
private scope: Scope;
private kind: any;
private iterableIsArray: any;
private arrayLikeIsIterable: any;
private addHelper: any;
constructor(opts) { constructor(opts) {
this.blockHoist = opts.blockHoist; this.blockHoist = opts.blockHoist;
this.operator = opts.operator; this.operator = opts.operator;
@ -118,6 +128,7 @@ export default declare((api, options) => {
const declar = t.variableDeclaration("var", [ const declar = t.variableDeclaration("var", [
t.variableDeclarator(t.cloneNode(id), t.cloneNode(init)), t.variableDeclarator(t.cloneNode(id), t.cloneNode(init)),
]); ]);
// @ts-expect-error todo(flow->ts): avoid mutations
declar._blockHoist = this.blockHoist; declar._blockHoist = this.blockHoist;
return declar; return declar;
} }
@ -135,7 +146,7 @@ export default declare((api, options) => {
} }
} }
toArray(node, count) { toArray(node, count?) {
if ( if (
this.iterableIsArray || this.iterableIsArray ||
(t.isIdentifier(node) && this.arrays[node.name]) (t.isIdentifier(node) && this.arrays[node.name])
@ -208,6 +219,7 @@ export default declare((api, options) => {
keys.push(t.cloneNode(key)); keys.push(t.cloneNode(key));
hasTemplateLiteral = true; hasTemplateLiteral = true;
} else if (t.isLiteral(key)) { } else if (t.isLiteral(key)) {
// @ts-expect-error todo(flow->ts) NullLiteral
keys.push(t.stringLiteral(String(key.value))); keys.push(t.stringLiteral(String(key.value)));
} else { } else {
keys.push(t.cloneNode(key)); keys.push(t.cloneNode(key));
@ -222,7 +234,7 @@ export default declare((api, options) => {
t.cloneNode(objRef), t.cloneNode(objRef),
]); ]);
} else { } else {
let keyExpression = t.arrayExpression(keys); let keyExpression: t.Expression = t.arrayExpression(keys);
if (!allLiteral) { if (!allLiteral) {
keyExpression = t.callExpression( keyExpression = t.callExpression(
@ -342,7 +354,7 @@ export default declare((api, options) => {
return false; return false;
} }
for (const elem of (pattern.elements: Array)) { for (const elem of pattern.elements) {
// deopt on holes // deopt on holes
if (!elem) return false; if (!elem) return false;
@ -350,7 +362,7 @@ export default declare((api, options) => {
if (t.isMemberExpression(elem)) return false; if (t.isMemberExpression(elem)) return false;
} }
for (const elem of (arr.elements: Array)) { for (const elem of arr.elements) {
// deopt on spread elements // deopt on spread elements
if (t.isSpreadElement(elem)) return false; if (t.isSpreadElement(elem)) return false;

Some files were not shown because too many files have changed in this diff Show More