Skip to content

Commit

Permalink
Use named imports for babel types (#13685)
Browse files Browse the repository at this point in the history
* migrate to named babel types imports

* perf: transform babel types import to destructuring

* fix merge errors

* apply plugin to itself
  • Loading branch information
JLHwung committed Aug 18, 2021
1 parent fc66d4d commit 614b486
Show file tree
Hide file tree
Showing 65 changed files with 1,283 additions and 787 deletions.
49 changes: 49 additions & 0 deletions babel.config.js
Expand Up @@ -202,6 +202,7 @@ module.exports = function (api) {
{
test: sources.map(normalize),
assumptions: sourceAssumptions,
plugins: [transformNamedBabelTypesImportToDestructuring],
},
{
test: unambiguousSources.map(normalize),
Expand Down Expand Up @@ -455,6 +456,54 @@ function pluginPackageJsonMacro({ types: t }) {
};
}

// transform `import { x } from "@babel/types"` to `import * as _t from "@babel/types"; const { x } = _t;
function transformNamedBabelTypesImportToDestructuring({
types: {
cloneNode,
importNamespaceSpecifier,
objectPattern,
objectProperty,
variableDeclarator,
variableDeclaration,
},
}) {
return {
name: "transform-babel-types-named-imports",
visitor: {
ImportDeclaration(path) {
const { node } = path;
if (
node.importKind === "value" &&
node.source.value === "@babel/types" &&
node.specifiers[0].type === "ImportSpecifier"
) {
const hoistedDestructuringProperties = [];
for (const { imported, local } of node.specifiers) {
hoistedDestructuringProperties.push(
objectProperty(
imported,
local,
false,
imported.name === local.name
)
);
}
const babelTypeNsImport = path.scope.generateUidIdentifier("t");
node.specifiers = [importNamespaceSpecifier(babelTypeNsImport)];
path.insertAfter([
variableDeclaration("const", [
variableDeclarator(
objectPattern(hoistedDestructuringProperties),
cloneNode(babelTypeNsImport)
),
]),
]);
}
},
},
};
}

function pluginImportMetaUrl({ types: t, template }) {
const isImportMeta = node =>
t.isMetaProperty(node) &&
Expand Down
101 changes: 61 additions & 40 deletions packages/babel-core/src/tools/build-external-helpers.ts
@@ -1,7 +1,28 @@
import * as helpers from "@babel/helpers";
import generator from "@babel/generator";
import template from "@babel/template";
import * as t from "@babel/types";
import {
arrayExpression,
assignmentExpression,
binaryExpression,
blockStatement,
callExpression,
cloneNode,
conditionalExpression,
exportNamedDeclaration,
exportSpecifier,
expressionStatement,
functionExpression,
identifier,
memberExpression,
objectExpression,
program,
stringLiteral,
unaryExpression,
variableDeclaration,
variableDeclarator,
} from "@babel/types";
import type * as t from "@babel/types";
import File from "../transformation/file/file";

// Wrapped to avoid wasting time parsing this when almost no-one uses
Expand All @@ -22,39 +43,39 @@ const buildUmdWrapper = replacements =>
`(replacements);

function buildGlobal(allowlist?: Array<string>) {
const namespace = t.identifier("babelHelpers");
const namespace = identifier("babelHelpers");

const body: t.Statement[] = [];
const container = t.functionExpression(
const container = functionExpression(
null,
[t.identifier("global")],
t.blockStatement(body),
[identifier("global")],
blockStatement(body),
);
const tree = t.program([
t.expressionStatement(
t.callExpression(container, [
const tree = program([
expressionStatement(
callExpression(container, [
// typeof global === "undefined" ? self : global
t.conditionalExpression(
t.binaryExpression(
conditionalExpression(
binaryExpression(
"===",
t.unaryExpression("typeof", t.identifier("global")),
t.stringLiteral("undefined"),
unaryExpression("typeof", identifier("global")),
stringLiteral("undefined"),
),
t.identifier("self"),
t.identifier("global"),
identifier("self"),
identifier("global"),
),
]),
),
]);

body.push(
t.variableDeclaration("var", [
t.variableDeclarator(
variableDeclaration("var", [
variableDeclarator(
namespace,
t.assignmentExpression(
assignmentExpression(
"=",
t.memberExpression(t.identifier("global"), namespace),
t.objectExpression([]),
memberExpression(identifier("global"), namespace),
objectExpression([]),
),
),
]),
Expand All @@ -70,57 +91,57 @@ function buildModule(allowlist?: Array<string>) {
const refs = buildHelpers(body, null, allowlist);

body.unshift(
t.exportNamedDeclaration(
exportNamedDeclaration(
null,
Object.keys(refs).map(name => {
return t.exportSpecifier(t.cloneNode(refs[name]), t.identifier(name));
return exportSpecifier(cloneNode(refs[name]), identifier(name));
}),
),
);

return t.program(body, [], "module");
return program(body, [], "module");
}

function buildUmd(allowlist?: Array<string>) {
const namespace = t.identifier("babelHelpers");
const namespace = identifier("babelHelpers");

const body: t.Statement[] = [];
body.push(
t.variableDeclaration("var", [
t.variableDeclarator(namespace, t.identifier("global")),
variableDeclaration("var", [
variableDeclarator(namespace, identifier("global")),
]),
);

buildHelpers(body, namespace, allowlist);

return t.program([
return program([
buildUmdWrapper({
FACTORY_PARAMETERS: t.identifier("global"),
BROWSER_ARGUMENTS: t.assignmentExpression(
FACTORY_PARAMETERS: identifier("global"),
BROWSER_ARGUMENTS: assignmentExpression(
"=",
t.memberExpression(t.identifier("root"), namespace),
t.objectExpression([]),
memberExpression(identifier("root"), namespace),
objectExpression([]),
),
COMMON_ARGUMENTS: t.identifier("exports"),
AMD_ARGUMENTS: t.arrayExpression([t.stringLiteral("exports")]),
COMMON_ARGUMENTS: identifier("exports"),
AMD_ARGUMENTS: arrayExpression([stringLiteral("exports")]),
FACTORY_BODY: body,
UMD_ROOT: t.identifier("this"),
UMD_ROOT: identifier("this"),
}),
]);
}

function buildVar(allowlist?: Array<string>) {
const namespace = t.identifier("babelHelpers");
const namespace = identifier("babelHelpers");

const body: t.Statement[] = [];
body.push(
t.variableDeclaration("var", [
t.variableDeclarator(namespace, t.objectExpression([])),
variableDeclaration("var", [
variableDeclarator(namespace, objectExpression([])),
]),
);
const tree = t.program(body);
const tree = program(body);
buildHelpers(body, namespace, allowlist);
body.push(t.expressionStatement(namespace));
body.push(expressionStatement(namespace));
return tree;
}

Expand All @@ -131,8 +152,8 @@ function buildHelpers(
) {
const getHelperReference = (name: string) => {
return namespace
? t.memberExpression(namespace, t.identifier(name))
: t.identifier(`_${name}`);
? memberExpression(namespace, identifier(name))
: identifier(`_${name}`);
};

const refs = {};
Expand Down
7 changes: 4 additions & 3 deletions packages/babel-core/src/transformation/file/file.ts
Expand Up @@ -3,7 +3,8 @@ import { NodePath, Scope } from "@babel/traverse";
import type { HubInterface } from "@babel/traverse";
import { codeFrameColumns } from "@babel/code-frame";
import traverse from "@babel/traverse";
import * as t from "@babel/types";
import { cloneNode, interpreterDirective } from "@babel/types";
import type * as t from "@babel/types";
import { getModuleName } from "@babel/helper-module-transforms";
import semver from "semver";

Expand Down Expand Up @@ -89,7 +90,7 @@ export default class File {
}
set shebang(value: string) {
if (value) {
this.path.get("interpreter").replaceWith(t.interpreterDirective(value));
this.path.get("interpreter").replaceWith(interpreterDirective(value));
} else {
this.path.get("interpreter").remove();
}
Expand Down Expand Up @@ -176,7 +177,7 @@ export default class File {

addHelper(name: string): t.Identifier {
const declar = this.declarations[name];
if (declar) return t.cloneNode(declar);
if (declar) return cloneNode(declar);

const generator = this.get("helperGenerator");
if (generator) {
Expand Down
7 changes: 4 additions & 3 deletions packages/babel-core/src/transformation/normalize-file.ts
Expand Up @@ -2,7 +2,8 @@ import fs from "fs";
import path from "path";
import buildDebug from "debug";
import type { Handler } from "gensync";
import * as t from "@babel/types";
import { file, traverseFast } from "@babel/types";
import type * as t from "@babel/types";
import type { PluginPasses } from "../config";
import convertSourceMap from "convert-source-map";
import type { SourceMapConverter as Converter } from "convert-source-map";
Expand All @@ -29,7 +30,7 @@ export default function* normalizeFile(

if (ast) {
if (ast.type === "Program") {
ast = t.file(ast, [], []);
ast = file(ast, [], []);
} else if (ast.type !== "File") {
throw new Error("AST root must be a Program or File node");
}
Expand Down Expand Up @@ -119,7 +120,7 @@ function extractCommentsFromList(regex, comments, lastComment) {

function extractComments(regex, ast) {
let lastComment = null;
t.traverseFast(ast, node => {
traverseFast(ast, node => {
[node.leadingComments, lastComment] = extractCommentsFromList(
regex,
node.leadingComments,
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-generator/src/generators/base.ts
@@ -1,5 +1,5 @@
import type Printer from "../printer";
import * as t from "@babel/types";
import type * as t from "@babel/types";
import * as charCodes from "charcodes";

export function File(this: Printer, node: t.File) {
Expand Down
8 changes: 5 additions & 3 deletions packages/babel-generator/src/generators/classes.ts
@@ -1,9 +1,11 @@
import type Printer from "../printer";
import * as t from "@babel/types";
import {
isExportDefaultDeclaration,
isExportNamedDeclaration,
} from "@babel/types";
import type * as t from "@babel/types";
import * as charCodes from "charcodes";

const { isExportDefaultDeclaration, isExportNamedDeclaration } = t;

export function ClassDeclaration(
this: Printer,
node: t.ClassDeclaration,
Expand Down
9 changes: 7 additions & 2 deletions packages/babel-generator/src/generators/expressions.ts
@@ -1,8 +1,13 @@
import type Printer from "../printer";
import * as t from "@babel/types";
import {
isCallExpression,
isLiteral,
isMemberExpression,
isNewExpression,
} from "@babel/types";
import type * as t from "@babel/types";
import * as n from "../node";

const { isCallExpression, isLiteral, isMemberExpression, isNewExpression } = t;
export function UnaryExpression(this: Printer, node: t.UnaryExpression) {
if (
node.operator === "void" ||
Expand Down
4 changes: 2 additions & 2 deletions packages/babel-generator/src/generators/flow.ts
@@ -1,8 +1,8 @@
import type Printer from "../printer";
import * as t from "@babel/types";
import { isDeclareExportDeclaration, isStatement } from "@babel/types";
import type * as t from "@babel/types";
import { ExportAllDeclaration } from "./modules";

const { isDeclareExportDeclaration, isStatement } = t;
export function AnyTypeAnnotation(this: Printer) {
this.word("any");
}
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-generator/src/generators/jsx.ts
@@ -1,5 +1,5 @@
import type Printer from "../printer";
import * as t from "@babel/types";
import type * as t from "@babel/types";

export function JSXAttribute(this: Printer, node: t.JSXAttribute) {
this.print(node.name, node);
Expand Down
4 changes: 2 additions & 2 deletions packages/babel-generator/src/generators/methods.ts
@@ -1,7 +1,7 @@
import type Printer from "../printer";
import * as t from "@babel/types";
import { isIdentifier } from "@babel/types";
import type * as t from "@babel/types";

const { isIdentifier } = t;
export function _params(this: Printer, node: any) {
this.print(node.typeParameters, node);
this.token("(");
Expand Down
7 changes: 3 additions & 4 deletions packages/babel-generator/src/generators/modules.ts
@@ -1,14 +1,13 @@
import type Printer from "../printer";
import * as t from "@babel/types";

const {
import {
isClassDeclaration,
isExportDefaultSpecifier,
isExportNamespaceSpecifier,
isImportDefaultSpecifier,
isImportNamespaceSpecifier,
isStatement,
} = t;
} from "@babel/types";
import type * as t from "@babel/types";

export function ImportSpecifier(this: Printer, node: t.ImportSpecifier) {
if (node.importKind === "type" || node.importKind === "typeof") {
Expand Down
9 changes: 7 additions & 2 deletions packages/babel-generator/src/generators/statements.ts
@@ -1,8 +1,13 @@
import type Printer from "../printer";
import * as t from "@babel/types";
import {
isFor,
isForStatement,
isIfStatement,
isStatement,
} from "@babel/types";
import type * as t from "@babel/types";
import * as charCodes from "charcodes";

const { isFor, isForStatement, isIfStatement, isStatement } = t;
export function WithStatement(this: Printer, node: t.WithStatement) {
this.word("with");
this.space();
Expand Down

0 comments on commit 614b486

Please sign in to comment.