convert @babel/helper-module-transforms to typescript (#12928)
Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
This commit is contained in:
parent
e5e37b94a5
commit
6ac07a1647
@ -208,3 +208,7 @@ declare module "@babel/highlight" {
|
||||
declare module "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" {
|
||||
declare module.exports: any;
|
||||
}
|
||||
|
||||
declare module "@babel/helper-module-transforms" {
|
||||
declare module.exports: any;
|
||||
}
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
// @flow
|
||||
|
||||
export default function getModuleName(
|
||||
rootOpts: Object,
|
||||
pluginOpts: Object,
|
||||
): ?string {
|
||||
rootOpts: any,
|
||||
pluginOpts: any,
|
||||
): string | undefined | null {
|
||||
const {
|
||||
filename,
|
||||
filenameRelative = filename,
|
||||
@ -9,9 +9,13 @@ import rewriteLiveReferences from "./rewrite-live-references";
|
||||
import normalizeAndLoadModuleMetadata, {
|
||||
hasExports,
|
||||
isSideEffectImport,
|
||||
type ModuleMetadata,
|
||||
type SourceModuleMetadata,
|
||||
} from "./normalize-and-load-metadata";
|
||||
import type {
|
||||
InteropType,
|
||||
ModuleMetadata,
|
||||
SourceModuleMetadata,
|
||||
} from "./normalize-and-load-metadata";
|
||||
import type { NodePath } from "@babel/traverse";
|
||||
|
||||
export { default as getModuleName } from "./get-module-name";
|
||||
|
||||
@ -24,7 +28,7 @@ export { hasExports, isSideEffectImport, isModule, rewriteThis };
|
||||
* and returns a list of statements for use when initializing the module.
|
||||
*/
|
||||
export function rewriteModuleStatementsAndPrepareHeader(
|
||||
path: NodePath,
|
||||
path: NodePath<t.Program>,
|
||||
{
|
||||
// TODO(Babel 8): Remove this
|
||||
loose,
|
||||
@ -39,6 +43,17 @@ export function rewriteModuleStatementsAndPrepareHeader(
|
||||
|
||||
constantReexports = loose,
|
||||
enumerableModuleMeta = loose,
|
||||
}: {
|
||||
exportName?;
|
||||
strict;
|
||||
allowTopLevelThis?;
|
||||
strictMode;
|
||||
loose?;
|
||||
noInterop?;
|
||||
lazy?;
|
||||
esNamespaceOnly?;
|
||||
constantReexports?;
|
||||
enumerableModuleMeta?;
|
||||
},
|
||||
) {
|
||||
assert(isModule(path), "Cannot process module statements in a script");
|
||||
@ -106,9 +121,9 @@ export function ensureStatementsHoisted(statements) {
|
||||
*/
|
||||
export function wrapInterop(
|
||||
programPath: NodePath,
|
||||
expr: Node,
|
||||
expr: t.Expression,
|
||||
type: InteropType,
|
||||
): Node {
|
||||
): t.CallExpression {
|
||||
if (type === "none") {
|
||||
return null;
|
||||
}
|
||||
@ -138,7 +153,7 @@ export function buildNamespaceInitStatements(
|
||||
) {
|
||||
const statements = [];
|
||||
|
||||
let srcNamespace = t.identifier(sourceMetadata.name);
|
||||
let srcNamespace: t.Node = t.identifier(sourceMetadata.name);
|
||||
if (sourceMetadata.lazy) srcNamespace = t.callExpression(srcNamespace, []);
|
||||
|
||||
for (const localName of sourceMetadata.importsNamespace) {
|
||||
@ -329,7 +344,7 @@ function buildExportNameListDeclaration(
|
||||
exportedVars[exportName] = true;
|
||||
}
|
||||
|
||||
hasReexport = hasReexport || data.reexportAll;
|
||||
hasReexport = hasReexport || !!data.reexportAll;
|
||||
}
|
||||
|
||||
if (!hasReexport || Object.keys(exportedVars).length === 0) return null;
|
||||
@ -1,61 +1,52 @@
|
||||
import { basename, extname } from "path";
|
||||
import type * as t from "@babel/types";
|
||||
|
||||
import { isIdentifierName } from "@babel/helper-validator-identifier";
|
||||
import splitExportDeclaration from "@babel/helper-split-export-declaration";
|
||||
import type { NodePath } from "@babel/traverse";
|
||||
|
||||
export type ModuleMetadata = {
|
||||
exportName: string,
|
||||
|
||||
export interface ModuleMetadata {
|
||||
exportName: string;
|
||||
// The name of the variable that will reference an object containing export names.
|
||||
exportNameListName: null | string,
|
||||
|
||||
hasExports: boolean,
|
||||
|
||||
exportNameListName: null | string;
|
||||
hasExports: boolean;
|
||||
// Lookup from local binding to export information.
|
||||
local: Map<string, LocalExportMetadata>,
|
||||
|
||||
local: Map<string, LocalExportMetadata>;
|
||||
// Lookup of source file to source file metadata.
|
||||
source: Map<string, SourceModuleMetadata>,
|
||||
|
||||
source: Map<string, SourceModuleMetadata>;
|
||||
// List of names that should only be printed as string literals.
|
||||
// i.e. `import { "any unicode" as foo } from "some-module"`
|
||||
// `stringSpecifiers` is Set(1) ["any unicode"]
|
||||
// In most cases `stringSpecifiers` is an empty Set
|
||||
stringSpecifiers: Set<string>,
|
||||
};
|
||||
stringSpecifiers: Set<string>;
|
||||
}
|
||||
|
||||
export type InteropType = "default" | "namespace" | "none";
|
||||
|
||||
export type SourceModuleMetadata = {
|
||||
export interface SourceModuleMetadata {
|
||||
// A unique variable name to use for this namespace object. Centralized for simplicity.
|
||||
name: string,
|
||||
|
||||
loc: ?BabelNodeSourceLocation,
|
||||
|
||||
interop: InteropType,
|
||||
|
||||
name: string;
|
||||
loc: t.SourceLocation | undefined | null;
|
||||
interop: InteropType;
|
||||
// Local binding to reference from this source namespace. Key: Local name, value: Import name
|
||||
imports: Map<string, string>,
|
||||
|
||||
imports: Map<string, string>;
|
||||
// Local names that reference namespace object.
|
||||
importsNamespace: Set<string>,
|
||||
|
||||
importsNamespace: Set<string>;
|
||||
// Reexports to create for namespace. Key: Export name, value: Import name
|
||||
reexports: Map<string, string>,
|
||||
|
||||
reexports: Map<string, string>;
|
||||
// List of names to re-export namespace as.
|
||||
reexportNamespace: Set<string>,
|
||||
|
||||
reexportNamespace: Set<string>;
|
||||
// Tracks if the source should be re-exported.
|
||||
reexportAll: null | {
|
||||
loc: ?BabelNodeSourceLocation,
|
||||
},
|
||||
loc: t.SourceLocation | undefined | null;
|
||||
};
|
||||
lazy?;
|
||||
}
|
||||
|
||||
export type LocalExportMetadata = {
|
||||
name: Array<string>, // names of exports
|
||||
kind: "import" | "hoisted" | "block" | "var",
|
||||
};
|
||||
export interface LocalExportMetadata {
|
||||
names: Array<string>; // names of exports,
|
||||
kind: "import" | "hoisted" | "block" | "var";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the module has any exports that need handling.
|
||||
@ -82,7 +73,7 @@ export function isSideEffectImport(source: SourceModuleMetadata) {
|
||||
* needed to reconstruct the module's behavior.
|
||||
*/
|
||||
export default function normalizeModuleAndLoadMetadata(
|
||||
programPath: NodePath,
|
||||
programPath: NodePath<t.Program>,
|
||||
exportName?: string,
|
||||
{
|
||||
noInterop = false,
|
||||
@ -94,7 +85,7 @@ export default function normalizeModuleAndLoadMetadata(
|
||||
if (!exportName) {
|
||||
exportName = programPath.scope.generateUidIdentifier("exports").name;
|
||||
}
|
||||
const stringSpecifiers = new Set();
|
||||
const stringSpecifiers = new Set<string>();
|
||||
|
||||
nameAnonymousExports(programPath);
|
||||
|
||||
@ -166,11 +157,15 @@ function getExportSpecifierName(
|
||||
* Get metadata about the imports and exports present in this module.
|
||||
*/
|
||||
function getModuleMetadata(
|
||||
programPath: NodePath,
|
||||
programPath: NodePath<t.Program>,
|
||||
{
|
||||
lazy,
|
||||
initializeReexports,
|
||||
}: { lazy: boolean, initializeReexports: boolean },
|
||||
}: {
|
||||
// todo(flow-ts) changed from boolean, to match expected usage inside the function
|
||||
lazy: boolean | string[] | Function;
|
||||
initializeReexports: boolean;
|
||||
},
|
||||
stringSpecifiers: Set<string>,
|
||||
) {
|
||||
const localData = getLocalExportMetadata(
|
||||
@ -289,7 +284,9 @@ function getModuleMetadata(
|
||||
data.reexports.set(exportName, importName);
|
||||
|
||||
if (exportName === "__esModule") {
|
||||
throw exportName.buildCodeFrameError('Illegal export "__esModule".');
|
||||
throw spec
|
||||
.get("exported")
|
||||
.buildCodeFrameError('Illegal export "__esModule".');
|
||||
}
|
||||
});
|
||||
} else if (
|
||||
@ -360,13 +357,13 @@ function getModuleMetadata(
|
||||
* Get metadata about local variables that are exported.
|
||||
*/
|
||||
function getLocalExportMetadata(
|
||||
programPath: NodePath,
|
||||
programPath: NodePath<t.Program>,
|
||||
initializeReexports: boolean,
|
||||
stringSpecifiers: Set<string>,
|
||||
): Map<string, LocalExportMetadata> {
|
||||
const bindingKindLookup = new Map();
|
||||
|
||||
programPath.get("body").forEach(child => {
|
||||
programPath.get("body").forEach((child: any) => {
|
||||
let kind;
|
||||
if (child.isImportDeclaration()) {
|
||||
kind = "import";
|
||||
@ -434,7 +431,8 @@ function getLocalExportMetadata(
|
||||
(initializeReexports || !child.node.source)
|
||||
) {
|
||||
if (child.node.declaration) {
|
||||
const declaration = child.get("declaration");
|
||||
// todo: flow->ts babel-types node field types
|
||||
const declaration = child.get("declaration") as NodePath;
|
||||
const ids = declaration.getOuterBindingIdentifierPaths();
|
||||
Object.keys(ids).forEach(name => {
|
||||
if (name === "__esModule") {
|
||||
@ -463,6 +461,7 @@ function getLocalExportMetadata(
|
||||
declaration.isFunctionDeclaration() ||
|
||||
declaration.isClassDeclaration()
|
||||
) {
|
||||
// @ts-expect-error todo(flow->ts): improve babel-types
|
||||
getLocalMetadata(declaration.get("id")).names.push("default");
|
||||
} else {
|
||||
// These should have been removed by the nameAnonymousExports() call.
|
||||
@ -478,7 +477,7 @@ function getLocalExportMetadata(
|
||||
/**
|
||||
* Ensure that all exported values have local binding names.
|
||||
*/
|
||||
function nameAnonymousExports(programPath: NodePath) {
|
||||
function nameAnonymousExports(programPath: NodePath<t.Program>) {
|
||||
// Name anonymous exported locals.
|
||||
programPath.get("body").forEach(child => {
|
||||
if (!child.isExportDefaultDeclaration()) return;
|
||||
@ -486,12 +485,13 @@ function nameAnonymousExports(programPath: NodePath) {
|
||||
});
|
||||
}
|
||||
|
||||
function removeModuleDeclarations(programPath: NodePath) {
|
||||
function removeModuleDeclarations(programPath: NodePath<t.Program>) {
|
||||
programPath.get("body").forEach(child => {
|
||||
if (child.isImportDeclaration()) {
|
||||
child.remove();
|
||||
} else if (child.isExportNamedDeclaration()) {
|
||||
if (child.node.declaration) {
|
||||
// @ts-expect-error todo(flow->ts): avoid mutations
|
||||
child.node.declaration._blockHoist = child.node._blockHoist;
|
||||
child.replaceWith(child.node.declaration);
|
||||
} else {
|
||||
@ -504,6 +504,7 @@ function removeModuleDeclarations(programPath: NodePath) {
|
||||
declaration.isFunctionDeclaration() ||
|
||||
declaration.isClassDeclaration()
|
||||
) {
|
||||
// @ts-expect-error todo(flow->ts): avoid mutations
|
||||
declaration._blockHoist = child.node._blockHoist;
|
||||
child.replaceWith(declaration);
|
||||
} else {
|
||||
@ -1,12 +1,33 @@
|
||||
import assert from "assert";
|
||||
import * as t from "@babel/types";
|
||||
import template from "@babel/template";
|
||||
import type { NodePath, Visitor, Scope } from "@babel/traverse";
|
||||
import simplifyAccess from "@babel/helper-simple-access";
|
||||
|
||||
import type { ModuleMetadata } from "./normalize-and-load-metadata";
|
||||
|
||||
interface RewriteReferencesVisitorState {
|
||||
exported: Map<any, any>;
|
||||
metadata: ModuleMetadata;
|
||||
requeueInParent: (path) => void;
|
||||
scope: Scope;
|
||||
imported: Map<any, any>;
|
||||
buildImportReference: (
|
||||
[source, importName, localName]: readonly [any, any, any],
|
||||
identNode,
|
||||
) => any;
|
||||
seen: WeakSet<object>;
|
||||
}
|
||||
|
||||
interface RewriteBindingInitVisitorState {
|
||||
exported: Map<any, any>;
|
||||
metadata: ModuleMetadata;
|
||||
requeueInParent: (path) => void;
|
||||
scope: Scope;
|
||||
}
|
||||
|
||||
export default function rewriteLiveReferences(
|
||||
programPath: NodePath,
|
||||
programPath: NodePath<t.Program>,
|
||||
metadata: ModuleMetadata,
|
||||
) {
|
||||
const imported = new Map();
|
||||
@ -39,12 +60,16 @@ export default function rewriteLiveReferences(
|
||||
}
|
||||
|
||||
// Rewrite initialization of bindings to update exports.
|
||||
programPath.traverse(rewriteBindingInitVisitor, {
|
||||
const rewriteBindingInitVisitorState: RewriteBindingInitVisitorState = {
|
||||
metadata,
|
||||
requeueInParent,
|
||||
scope: programPath.scope,
|
||||
exported, // local name => exported name list
|
||||
});
|
||||
};
|
||||
programPath.traverse(
|
||||
rewriteBindingInitVisitor,
|
||||
rewriteBindingInitVisitorState,
|
||||
);
|
||||
|
||||
simplifyAccess(
|
||||
programPath,
|
||||
@ -53,7 +78,7 @@ export default function rewriteLiveReferences(
|
||||
);
|
||||
|
||||
// Rewrite reads/writes from imports and exports to have the correct behavior.
|
||||
programPath.traverse(rewriteReferencesVisitor, {
|
||||
const rewriteReferencesVisitorState: RewriteReferencesVisitorState = {
|
||||
seen: new WeakSet(),
|
||||
metadata,
|
||||
requeueInParent,
|
||||
@ -68,7 +93,7 @@ export default function rewriteLiveReferences(
|
||||
return identNode;
|
||||
}
|
||||
|
||||
let namespace = t.identifier(meta.name);
|
||||
let namespace: t.Expression = t.identifier(meta.name);
|
||||
if (meta.lazy) namespace = t.callExpression(namespace, []);
|
||||
|
||||
const computed = metadata.stringSpecifiers.has(importName);
|
||||
@ -79,13 +104,14 @@ export default function rewriteLiveReferences(
|
||||
computed,
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
programPath.traverse(rewriteReferencesVisitor, rewriteReferencesVisitorState);
|
||||
}
|
||||
|
||||
/**
|
||||
* A visitor to inject export update statements during binding initialization.
|
||||
*/
|
||||
const rewriteBindingInitVisitor = {
|
||||
const rewriteBindingInitVisitor: Visitor<RewriteBindingInitVisitorState> = {
|
||||
Scope(path) {
|
||||
path.skip();
|
||||
},
|
||||
@ -105,6 +131,7 @@ const rewriteBindingInitVisitor = {
|
||||
t.identifier(localName),
|
||||
),
|
||||
);
|
||||
// @ts-expect-error todo(flow->ts): avoid mutations
|
||||
statement._blockHoist = path.node._blockHoist;
|
||||
|
||||
requeueInParent(path.insertAfter(statement)[0]);
|
||||
@ -124,6 +151,7 @@ const rewriteBindingInitVisitor = {
|
||||
t.identifier(localName),
|
||||
),
|
||||
);
|
||||
// @ts-expect-error todo(flow->ts): avoid mutations
|
||||
statement._blockHoist = path.node._blockHoist;
|
||||
|
||||
requeueInParent(path.insertAfter(statement)[0]);
|
||||
@ -163,7 +191,7 @@ const buildImportThrow = localName => {
|
||||
`;
|
||||
};
|
||||
|
||||
const rewriteReferencesVisitor = {
|
||||
const rewriteReferencesVisitor: Visitor<RewriteReferencesVisitorState> = {
|
||||
ReferencedIdentifier(path) {
|
||||
const {
|
||||
seen,
|
||||
@ -200,9 +228,11 @@ const rewriteReferencesVisitor = {
|
||||
} else if (path.isJSXIdentifier() && t.isMemberExpression(ref)) {
|
||||
const { object, property } = ref;
|
||||
path.replaceWith(
|
||||
t.JSXMemberExpression(
|
||||
t.JSXIdentifier(object.name),
|
||||
t.JSXIdentifier(property.name),
|
||||
t.jsxMemberExpression(
|
||||
// @ts-expect-error todo(flow->ts): possible bug `object` might not have a name
|
||||
t.jsxIdentifier(object.name),
|
||||
// @ts-expect-error todo(flow->ts): possible bug `property` might not have a name
|
||||
t.jsxIdentifier(property.name),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
@ -303,9 +333,10 @@ const rewriteReferencesVisitor = {
|
||||
});
|
||||
|
||||
if (items.length > 0) {
|
||||
let node = t.sequenceExpression(items);
|
||||
let node: t.Node = t.sequenceExpression(items);
|
||||
if (path.parentPath.isExpressionStatement()) {
|
||||
node = t.expressionStatement(node);
|
||||
// @ts-expect-error todo(flow->ts): avoid mutations
|
||||
node._blockHoist = path.parentPath.node._blockHoist;
|
||||
}
|
||||
|
||||
@ -315,7 +346,9 @@ const rewriteReferencesVisitor = {
|
||||
}
|
||||
},
|
||||
},
|
||||
"ForOfStatement|ForInStatement"(path) {
|
||||
"ForOfStatement|ForInStatement"(
|
||||
path: NodePath<t.ForOfStatement | t.ForInStatement>,
|
||||
) {
|
||||
const { scope, node } = path;
|
||||
const { left } = node;
|
||||
const { exported, scope: programScope } = this;
|
||||
@ -2,6 +2,7 @@ import { environmentVisitor } from "@babel/helper-replace-supers";
|
||||
import traverse from "@babel/traverse";
|
||||
import * as t from "@babel/types";
|
||||
|
||||
import type { NodePath, Visitor } from "@babel/traverse";
|
||||
export default function rewriteThis(programPath: NodePath) {
|
||||
// Rewrite "this" to be "undefined".
|
||||
traverse(programPath.node, { ...rewriteThisVisitor, noScope: true });
|
||||
@ -11,10 +12,10 @@ export default function rewriteThis(programPath: NodePath) {
|
||||
* A visitor to walk the tree, rewriting all `this` references in the top-level scope to be
|
||||
* `void 0` (undefined).
|
||||
*/
|
||||
const rewriteThisVisitor = traverse.visitors.merge([
|
||||
const rewriteThisVisitor: Visitor = traverse.visitors.merge([
|
||||
environmentVisitor,
|
||||
{
|
||||
ThisExpression(path) {
|
||||
ThisExpression(path: NodePath<t.ThisExpression>) {
|
||||
path.replaceWith(t.unaryExpression("void", t.numericLiteral(0), true));
|
||||
},
|
||||
},
|
||||
Loading…
x
Reference in New Issue
Block a user