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: [
// @babel/register is the require() hook, so it will always be CJS-based
"packages/babel-register/**/*.js",
"packages/babel-register/**/*.{js,ts}",
],
rules: {
"no-restricted-globals": ["error", ...cjsGlobals],

View File

@ -61,7 +61,7 @@ function mapSrcToLib(srcPath) {
function mapToDts(packageName) {
return packageName.replace(
/(?<=\\|\/|^)(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);
let message,

View File

@ -2,13 +2,13 @@ import type { PluginObject } from "./validation/plugins";
export default class Plugin {
key: string | undefined | null;
manipulateOptions: ((options: unknown, parserOpts: unknown) => void) | void;
post: Function | void;
pre: Function | void;
manipulateOptions?: (options: unknown, parserOpts: unknown) => void;
post?: Function;
pre?: Function;
visitor: {};
parserOverride: Function | void;
generatorOverride: Function | void;
parserOverride?: Function;
generatorOverride?: Function;
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(): any {
get() {
this._flush();
const map = this._map;

View File

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

View File

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

View File

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

View File

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

View File

@ -1,15 +1,17 @@
import explode from "@babel/helper-explode-assignable-expression";
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;
return {
const visitor: Visitor = {
AssignmentExpression(path) {
const { node, scope } = path;
if (node.operator !== operator + "=") return;
const nodes = [];
// @ts-expect-error todo(flow->ts)
const exploded = explode(node.left, nodes, this, scope);
nodes.push(
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/types": "workspace:^"
},
"devDependencies": {
"@babel/traverse": "workspace:^"
},
"engines": {
"node": ">=6.9.0"
},

View File

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

View File

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

View File

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

View File

@ -482,8 +482,7 @@ function getLocalExportMetadata(
(initializeReexports || !child.node.source)
) {
if (child.node.declaration) {
// todo: flow->ts babel-types node field types
const declaration = child.get("declaration") as NodePath;
const declaration = child.get("declaration");
const ids = declaration.getOuterBindingIdentifierPaths();
Object.keys(ids).forEach(name => {
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) => {
let clonedApi;
@ -10,6 +25,7 @@ export function declare(builder) {
clonedApi[name] = apiPolyfills[name](clonedApi);
}
// @ts-ignore
return builder(clonedApi ?? api, options || {}, dirname);
};
}
@ -101,12 +117,9 @@ function throwVersionError(range, version) {
Error.stackTraceLimit = limit;
}
throw Object.assign(
err,
({
code: "BABEL_VERSION_UNSUPPORTED",
version,
range,
}: any),
);
throw Object.assign(err, {
code: "BABEL_VERSION_UNSUPPORTED",
version,
range,
} as any);
}

View File

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

View File

@ -9,6 +9,7 @@ import {
isRestElement,
returnStatement,
} from "@babel/types";
import type * as t from "@babel/types";
const buildAnonymousExpressionWrapper = template.expression(`
(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 body = node.body;
@ -57,12 +61,12 @@ function classOrObjectMethod(path: NodePath, callId: Object) {
node.generator = false;
// Unwrap the wrapper IIFE's environment so super and this and such still work.
path
.get("body.body.0.argument.callee.arguments.0")
.unwrapFunctionEnvironment();
(
path.get("body.body.0.argument.callee.arguments.0") as NodePath
).unwrapFunctionEnvironment();
}
function plainFunction(path: NodePath, callId: Object, noNewArrows: boolean) {
function plainFunction(path: NodePath<any>, callId: any, noNewArrows: boolean) {
const node = path.node;
const isDeclaration = path.isFunctionDeclaration();
const functionId = node.id;
@ -109,6 +113,7 @@ function plainFunction(path: NodePath, callId: Object, noNewArrows: boolean) {
path.replaceWith(container[0]);
path.insertAfter(container[1]);
} else {
// @ts-expect-error todo(flow->ts) separate `wrapper` for `isDeclaration` and `else` branches
const retFunction = container.callee.body.body[1].argument;
if (!functionId) {
nameFunction({
@ -120,6 +125,7 @@ function plainFunction(path: NodePath, callId: Object, noNewArrows: boolean) {
if (!retFunction || retFunction.id || node.params.length) {
// 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);
} else {
// 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(
path: NodePath,
callId: Object,
callId: any,
// TODO(Babel 8): Consider defaulting to false for spec compliancy
noNewArrows: boolean = true,
) {

View File

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

View File

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

View File

@ -28,7 +28,9 @@
},
"devDependencies": {
"@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",
"engines": {

View File

@ -6,11 +6,13 @@ import {
FEATURES,
} 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`
*
* @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
*/
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
// is enabled it can generte optimized output without passing from the intermediate
// private fields representation.
ClassBody(classBody: NodePath<Class>) {
ClassBody(classBody: NodePath<t.ClassBody>) {
const { scope } = classBody;
const privateNames = new Set();
const privateNames = new Set<string>();
const body = classBody.get("body");
for (const path of body) {
if (path.isPrivate()) {
@ -60,7 +62,9 @@ export default declare(({ types: t, template, assertVersion }) => {
path.replaceWith(
t.classPrivateProperty(
staticBlockRef,
template.expression.ast`(() => { ${path.node.body} })()`,
template.expression.ast`(() => { ${
(path.node as t.StaticBlock).body
} })()`,
[],
/* static */ true,
),

View File

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

View File

@ -1,18 +1,19 @@
// Fork of https://github.com/loganfsmyth/babel-plugin-proposal-decorators-legacy
import { template, types as t } from "@babel/core";
import type { Visitor } from "@babel/traverse";
const buildClassDecorator = template(`
DECORATOR(CLASS_REF = INNER) || CLASS_REF;
`);
`) as (replacements: { DECORATOR; CLASS_REF; INNER }) => t.ExpressionStatement;
const buildClassPrototype = template(`
CLASS_REF.prototype;
`);
`) as (replacements: { CLASS_REF }) => t.ExpressionStatement;
const buildGetDescriptor = template(`
Object.getOwnPropertyDescriptor(TARGET, PROPERTY);
`);
`) as (replacements: { TARGET; PROPERTY }) => t.ExpressionStatement;
const buildGetObjectInitializer = template(`
(TEMP = Object.getOwnPropertyDescriptor(TARGET, PROPERTY), (TEMP = TEMP ? TEMP.value : undefined), {
@ -23,7 +24,7 @@ const buildGetObjectInitializer = template(`
return TEMP;
}
})
`);
`) as (replacements: { TEMP; TARGET; PROPERTY }) => t.ExpressionStatement;
const WARNING_CALLS = new WeakSet();
@ -241,6 +242,7 @@ export default {
replacement,
t.exportNamedDeclaration(null, [
t.exportSpecifier(
// @ts-expect-error todo(flow->ts) might be add more specific return type for decoratedClassToExpression
t.cloneNode(replacement.declarations[0].id),
t.identifier("default"),
),
@ -263,7 +265,7 @@ export default {
// class decorators, and a second pass to process method decorators.
const decoratedClass =
applyEnsureOrdering(path) ||
applyClassDecorators(path, state) ||
applyClassDecorators(path) ||
applyMethodDecorators(path, state);
if (decoratedClass) path.replaceWith(decoratedClass);
@ -280,12 +282,17 @@ export default {
path.replaceWith(
t.callExpression(state.addHelper("initializerDefineProperty"), [
// @ts-expect-error todo(flow->ts) typesafe NodePath.get
t.cloneNode(path.get("left.object").node),
t.stringLiteral(
// @ts-expect-error todo(flow->ts) typesafe NodePath.get
path.get("left.property").node.name ||
// @ts-expect-error todo(flow->ts) typesafe NodePath.get
path.get("left.property").node.value,
),
// @ts-expect-error todo(flow->ts)
t.cloneNode(path.get("right.arguments")[0].node),
// @ts-expect-error todo(flow->ts)
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
// 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) {
return;
}
@ -305,9 +313,11 @@ export default {
t.callExpression(state.addHelper("initializerDefineProperty"), [
t.cloneNode(path.get("arguments")[0].node),
t.cloneNode(path.get("arguments")[1].node),
// @ts-expect-error todo(flow->ts)
t.cloneNode(path.get("arguments.2.arguments")[0].node),
// @ts-expect-error todo(flow->ts)
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.
`;
declare const PACKAGE_JSON: { name: string; version: string };
export default declare(api => {
api.assertVersion(7);

View File

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

View File

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

View File

@ -1,5 +1,7 @@
import { declare } from "@babel/helper-plugin-utils";
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
@ -7,9 +9,11 @@ import syntaxNumericSeparator from "@babel/plugin-syntax-numeric-separator";
*
* @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;
// @ts-expect-error todo(flow->ts)
if (extra?.raw?.includes("_")) {
// @ts-expect-error todo(flow->ts)
extra.raw = extra.raw.replace(/_/g, "");
}
}

View File

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

View File

@ -1,4 +1,5 @@
import { types as t, template } from "@babel/core";
import type { NodePath } from "@babel/traverse";
import {
skipTransparentExprWrapperNodes,
skipTransparentExprWrappers,
@ -48,7 +49,7 @@ export function transform(
{
pureGetters,
noDocumentAll,
}: { pureGetters: boolean, noDocumentAll: boolean },
}: { pureGetters: boolean; noDocumentAll: boolean },
) {
const { scope } = path;
// 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)() ){}`
// so the temporary variable can be injected in correct scope
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
return;
}
@ -83,15 +84,19 @@ export function transform(
}
if (optionalPath.isOptionalMemberExpression()) {
// @ts-expect-error todo(flow->ts) avoid changing more type
optionalPath.node.type = "MemberExpression";
// @ts-expect-error todo(flow->ts)
optionalPath = skipTransparentExprWrappers(optionalPath.get("object"));
} else if (optionalPath.isOptionalCallExpression()) {
// @ts-expect-error todo(flow->ts) avoid changing more type
optionalPath.node.type = "CallExpression";
// @ts-expect-error todo(flow->ts)
optionalPath = skipTransparentExprWrappers(optionalPath.get("callee"));
}
}
let replacementPath = path;
let replacementPath: NodePath<any> = path;
if (parentPath.isUnaryExpression({ operator: "delete" })) {
replacementPath = parentPath;
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.
// `a.?b.?()` translates roughly to `(_b = _a.b) != null && _b.call(_a)`
const { object } = chain;
let context = scope.maybeGenerateMemoised(object);
let context: t.Expression = scope.maybeGenerateMemoised(object);
if (context) {
chain.object = t.assignmentExpression("=", context, object);
} else if (t.isSuper(object)) {
@ -194,6 +199,7 @@ export function transform(
t.logicalExpression("&&", nonNullishCheck, replacement),
);
replacementPath = skipTransparentExprWrappers(
// @ts-expect-error todo(flow->ts)
replacementPath.get("right"),
);
} else {
@ -207,6 +213,7 @@ export function transform(
t.conditionalExpression(nullishCheck, returnValue, replacement),
);
replacementPath = skipTransparentExprWrappers(
// @ts-expect-error todo(flow->ts)
replacementPath.get("alternate"),
);
}

View File

@ -1,3 +1,4 @@
import type { NodePath } from "@babel/traverse";
import { isTransparentExprWrapper } from "@babel/helper-skip-transparent-expression-wrappers";
/**
* 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 {
let maybeWrapped = path;
path.findParent(p => {
if (!isTransparentExprWrapper(p)) return true;
if (!isTransparentExprWrapper(p.node)) return true;
maybeWrapped = p;
});
return maybeWrapped;

View File

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

View File

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

View File

@ -1,5 +1,6 @@
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) => {
api.assertVersion(7);
@ -10,9 +11,7 @@ export default declare((api, options) => {
name: "transform-arrow-functions",
visitor: {
ArrowFunctionExpression(
path: NodePath<BabelNodeArrowFunctionExpression>,
) {
ArrowFunctionExpression(path: NodePath<t.ArrowFunctionExpression>) {
// In some conversion cases, it may have already been converted to a function while this callback
// was queued up.
if (!path.isArrowFunctionExpression()) return;

View File

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

View File

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

View File

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

View File

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

View File

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

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