Migrate Babel from Flow to TypeScript (except Babel parser) (#11578)
Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
parent
473f145b27
commit
0058b7fef4
@ -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],
|
||||
|
||||
@ -61,7 +61,7 @@ function mapSrcToLib(srcPath) {
|
||||
function mapToDts(packageName) {
|
||||
return packageName.replace(
|
||||
/(?<=\\|\/|^)(packages|eslint|codemods)(?=\\|\/)/,
|
||||
"dts"
|
||||
"dts/$1"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
@ -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: {};
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
@ -17,6 +17,9 @@
|
||||
"@babel/helper-annotate-as-pure": "workspace:^",
|
||||
"@babel/types": "workspace:^"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/traverse": "workspace:^"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 };
|
||||
}
|
||||
|
||||
@ -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);
|
||||
@ -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") {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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, {
|
||||
@ -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,
|
||||
) {
|
||||
@ -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);
|
||||
@ -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);
|
||||
@ -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": {
|
||||
|
||||
@ -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,
|
||||
),
|
||||
@ -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"
|
||||
},
|
||||
|
||||
@ -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>;
|
||||
@ -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);
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
@ -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"
|
||||
|
||||
@ -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, "");
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
|
||||
@ -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"),
|
||||
);
|
||||
}
|
||||
@ -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;
|
||||
@ -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) => {
|
||||
@ -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"
|
||||
|
||||
@ -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;
|
||||
@ -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
|
||||
@ -920,7 +920,7 @@ class BlockScoping {
|
||||
* later on.
|
||||
*/
|
||||
|
||||
checkLoop(): any {
|
||||
checkLoop() {
|
||||
const state: LoopVisitorState = {
|
||||
hasBreakContinue: false,
|
||||
ignoreLabeless: false,
|
||||
|
||||
@ -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 {
|
||||
@ -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"
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user