Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix import { types } from "@babel/core" with native ESM #14663

Merged
merged 2 commits into from Jun 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 49 additions & 0 deletions babel.config.js
Expand Up @@ -220,6 +220,15 @@ module.exports = function (api) {
],
],
},
convertESM && {
test: ["./packages/babel-core/src"].map(normalize),
plugins: [
[
pluginInjectNodeReexportsHints,
{ names: ["types", "tokTypes", "traverse", "template"] },
],
],
},
convertESM && {
test: sources.map(normalize),
exclude: lazyRequireSources.map(normalize),
Expand Down Expand Up @@ -730,3 +739,43 @@ function pluginDynamicESLintVersionCheck({ template }) {
},
};
}

// Inject `0 && exports.foo = 0` hints for the specified exports,
// to help the Node.js CJS-ESM interop. This is only
// needed when compiling ESM re-exports to CJS in `lazy` mode.
function pluginInjectNodeReexportsHints({ types: t, template }, { names }) {
return {
visitor: {
Program: {
exit(path) {
const seen = [];
for (const stmt of path.get("body")) {
if (!stmt.isExpressionStatement()) continue;
const expr = stmt.get("expression");
if (
!expr.isCallExpression() ||
!expr.get("callee").matchesPattern("Object.defineProperty") ||
expr.node.arguments.length !== 3 ||
!expr.get("arguments.0").isIdentifier({ name: "exports" }) ||
!expr.get("arguments.1").isStringLiteral() ||
!names.includes(expr.node.arguments[1].value)
) {
continue;
}

expr
.get("arguments.0")
.replaceWith(template.expression.ast`(0, exports)`);
seen.push(expr.node.arguments[1].value);
}

const assign = seen.reduce(
(rhs, name) => template.expression.ast`exports.${name} = ${rhs}`,
t.numericLiteral(0)
);
path.pushContainer("body", template.statement.ast`0 && (${assign})`);
},
},
},
};
}
4 changes: 3 additions & 1 deletion packages/babel-core/src/index.ts
Expand Up @@ -8,9 +8,11 @@ export { resolvePlugin, resolvePreset } from "./config/files";

export { getEnv } from "./config/helpers/environment";

// NOTE: Lazy re-exports aren't detected by the Node.js CJS-ESM interop.
// These are handled by pluginInjectNodeReexportsHints in our babel.config.js
// so that they can work well.
export * as types from "@babel/types";
export { tokTypes } from "@babel/parser";

export { default as traverse } from "@babel/traverse";
export { default as template } from "@babel/template";

Expand Down
2 changes: 1 addition & 1 deletion packages/babel-core/test/api.js
@@ -1,4 +1,4 @@
import babel from "../lib/index.js";
import * as babel from "../lib/index.js";
import { TraceMap, originalPositionFor } from "@jridgewell/trace-mapping";
import path from "path";
import generator from "@babel/generator";
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-core/test/config-chain.js
Expand Up @@ -2,7 +2,7 @@ import fs from "fs";
import os from "os";
import path from "path";
import { fileURLToPath } from "url";
import babel from "../lib/index.js";
import * as babel from "../lib/index.js";
import rimraf from "rimraf";

import _getTargets from "@babel/helper-compilation-targets";
Expand Down
6 changes: 2 additions & 4 deletions packages/babel-core/test/fixtures/babel-compile-async.mjs
Expand Up @@ -2,10 +2,8 @@

// Usage:
// babel-compile-async.js [filename]
import babel from "../../lib/index.js";
import { transformAsync } from "../../lib/index.js";

(async () => {
process.stdout.write(
JSON.stringify(await babel.transformAsync(""))
);
process.stdout.write(JSON.stringify(await transformAsync("")));
})();
6 changes: 2 additions & 4 deletions packages/babel-core/test/fixtures/babel-compile-sync.mjs
Expand Up @@ -2,8 +2,6 @@

// Usage:
// babel-compile-async.js [filename]
import babel from "../../lib/index.js";
import { transformSync } from "../../lib/index.js";

process.stdout.write(
JSON.stringify(babel.transformSync(""))
);
process.stdout.write(JSON.stringify(transformSync("")));
Expand Up @@ -2,12 +2,12 @@

// Usage:
// babel-load-options-async.js [filename]
import babel from "../../lib/index.js";
import { loadOptionsAsync } from "../../lib/index.js";

const [, , filename, cwd] = process.argv;

(async () => {
process.stdout.write(
JSON.stringify(await babel.loadOptionsAsync({ filename, cwd }))
JSON.stringify(await loadOptionsAsync({ filename, cwd }))
);
})();
5 changes: 2 additions & 3 deletions packages/babel-helper-check-duplicate-nodes/test/index.js
@@ -1,6 +1,5 @@
import _checkDuplicateNodes from "../lib/index.js";
import babel from "@babel/core";
const { parseSync, traverse, types: t } = babel;
import { parseSync, traverse, types as t } from "@babel/core";
const checkDuplicateNodes = _checkDuplicateNodes.default;

describe("checkDuplicateNodes", () => {
Expand Down Expand Up @@ -53,7 +52,7 @@ describe("checkDuplicateNodes", () => {
});
it("should throw when more than one arguments are passed", () => {
expect(() => {
checkDuplicateNodes(babel, {});
checkDuplicateNodes({}, {});
}).toThrow("checkDuplicateNodes accepts only one argument: ast");
});
});
@@ -1,6 +1,5 @@
import { shouldTransform } from "../lib/util.js";
import babel from "@babel/core";
const { parseSync, traverse } = babel;
import { parseSync, traverse } from "@babel/core";

function getPath(input, parserOpts = {}) {
let targetPath;
Expand Down
@@ -1,6 +1,5 @@
import { shouldTransform } from "../lib/util.js";
import babel from "@babel/core";
const { parseSync, traverse } = babel;
import { parseSync, traverse } from "@babel/core";

function getPath(input, parserOpts = {}) {
let targetPath;
Expand Down
@@ -1,4 +1,4 @@
import babel from "@babel/core";
import { transformSync } from "@babel/core";
import proposalDestructuringPrivate from "../lib/index.js";

describe("plugin ordering", () => {
Expand All @@ -12,7 +12,7 @@ describe("plugin ordering", () => {
`;
expect(
() =>
babel.transformSync(source, {
transformSync(source, {
filename: "example.js",
highlightCode: false,
configFile: false,
Expand Down
@@ -1,8 +1,5 @@
import babel from "@babel/core";
import { parseSync, traverse, types as t } from "@babel/core";
import { traversePattern, privateKeyPathIterator } from "../lib/util.js";
const { isObjectProperty, isPrivateName } = babel.types;

const { parseSync, traverse } = babel;

function wrapSourceInClassEnvironment(input) {
const usedPrivateNames = new Set();
Expand Down Expand Up @@ -44,9 +41,9 @@ describe("traversePattern", () => {
);
const keys = [
...traversePattern(patternPath.node, function* (node) {
if (isObjectProperty(node)) {
if (t.isObjectProperty(node)) {
const propertyKey = node.key;
if (isPrivateName(propertyKey)) {
if (t.isPrivateName(propertyKey)) {
yield propertyKey.id.name;
}
}
Expand Down
@@ -1,6 +1,5 @@
import { willPathCastToBoolean } from "../lib/util.js";
import babel from "@babel/core";
const { parseSync, traverse } = babel;
import { parseSync, traverse } from "@babel/core";

function getPath(input, parserOpts) {
let targetPath;
Expand Down
6 changes: 3 additions & 3 deletions packages/babel-plugin-transform-runtime/scripts/build-dist.js
Expand Up @@ -2,7 +2,7 @@ import path from "path";
import fs from "fs";
import { createRequire } from "module";
import helpers from "@babel/helpers";
import babel from "@babel/core";
import { transformFromAstSync, File } from "@babel/core";
import template from "@babel/template";
import t from "@babel/types";
import { fileURLToPath } from "url";
Expand Down Expand Up @@ -217,7 +217,7 @@ function buildHelper(

if (!esm) {
bindings = [];
helpers.ensure(helperName, babel.File);
helpers.ensure(helperName, File);
for (const dep of helpers.getDependencies(helperName)) {
const id = (dependencies[dep] = t.identifier(t.toIdentifier(dep)));
tree.body.push(template.statement.ast`
Expand All @@ -235,7 +235,7 @@ function buildHelper(
);
tree.body.push(...helper.nodes);

return babel.transformFromAstSync(tree, null, {
return transformFromAstSync(tree, null, {
filename: helperFilename,
presets: [["@babel/preset-env", { modules: false }]],
plugins: [
Expand Down