Skip to content

Commit

Permalink
Generate helper metadata at build time (#16501)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed May 22, 2024
1 parent 125ba9a commit 553e433
Show file tree
Hide file tree
Showing 147 changed files with 2,693 additions and 991 deletions.
13 changes: 12 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,16 @@ function pluginPolyfillsOldNode({ template, types: t }) {
// https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V16.md#v8-93
replacement: template`hasOwnProperty.call`,
},
{
name: "Object.entries",
necessary({ parent, node }) {
// To avoid infinite replacement loops
return !t.isLogicalExpression(parent, { operator: "||", left: node });
},
supported: path =>
path.parentPath.isCallExpression({ callee: path.node }),
replacement: template`Object.entries || (o => Object.keys(o).map(k => [k, o[k]]))`,
},
{
name: "fs.rmSync",
necessary({ node, parent }) {
Expand Down Expand Up @@ -543,7 +553,8 @@ function pluginPolyfillsOldNode({ template, types: t }) {
if (!polyfill.necessary(path)) return;
if (!polyfill.supported(path)) {
throw path.buildCodeFrameError(
`This '${polyfill.name}' usage is not supported by the inline polyfill.`
`This '${polyfill.name}' usage is not supported by the inline polyfill.\n` +
path.parentPath.toString()
);
}

Expand Down
21 changes: 18 additions & 3 deletions packages/babel-core/src/tools/build-external-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
variableDeclarator,
} from "@babel/types";
import type * as t from "@babel/types";
import File from "../transformation/file/file.ts";
import type { Replacements } from "@babel/template";

// Wrapped to avoid wasting time parsing this when almost no-one uses
Expand Down Expand Up @@ -174,8 +173,24 @@ function buildHelpers(

const ref = (refs[name] = getHelperReference(name));

helpers.ensure(name, File);
const { nodes } = helpers.get(name, getHelperReference, ref);
const { nodes } = helpers.get(
name,
getHelperReference,
namespace ? null : `_${name}`,
[],
namespace
? (ast, exportName, mapExportBindingAssignments) => {
mapExportBindingAssignments(node =>
assignmentExpression("=", ref, node),
);
ast.body.push(
expressionStatement(
assignmentExpression("=", ref, identifier(exportName)),
),
);
}
: null,
);

body.push(...nodes);
});
Expand Down
4 changes: 2 additions & 2 deletions packages/babel-core/src/transformation/file/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export default class File {
}

// make sure that the helper exists
helpers.ensure(name, File);
helpers.minVersion(name);

const uid = (this.declarations[name] =
this.scope.generateUidIdentifier(name));
Expand All @@ -176,7 +176,7 @@ export default class File {
const { nodes, globals } = helpers.get(
name,
dep => dependencies[dep],
uid,
uid.name,
Object.keys(this.scope.getAllBindings()),
);

Expand Down
100 changes: 82 additions & 18 deletions packages/babel-core/test/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -840,24 +840,6 @@ describe("api", function () {
});

describe("buildExternalHelpers", function () {
describe("smoke tests", function () {
it("builds external helpers in global output type", function () {
babel.buildExternalHelpers(null, "global");
});

it("builds external helpers in module output type", function () {
babel.buildExternalHelpers(null, "module");
});

it("builds external helpers in umd output type", function () {
babel.buildExternalHelpers(null, "umd");
});

it("builds external helpers in var output type", function () {
babel.buildExternalHelpers(null, "var");
});
});

it("all", function () {
const script = babel.buildExternalHelpers();
expect(script).toEqual(expect.stringContaining("classCallCheck"));
Expand All @@ -880,6 +862,88 @@ describe("api", function () {
const script = babel.buildExternalHelpers(["typeof"]);
expect(script).toEqual(expect.stringContaining("typeof"));
});

describe("output types", function () {
it("global", function () {
const script = babel.buildExternalHelpers(["get"], "global");
expect(script).toMatchInlineSnapshot(`
"(function (global) {
var babelHelpers = global.babelHelpers = {};
function _get() {
return babelHelpers.get = _get = \\"undefined\\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) {
var p = babelHelpers.superPropBase(e, t);
if (p) {
var n = Object.getOwnPropertyDescriptor(p, t);
return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value;
}
}, _get.apply(null, arguments);
}
babelHelpers.get = _get;
})(typeof global === \\"undefined\\" ? self : global);"
`);
});

it("umd", function () {
const script = babel.buildExternalHelpers(["get"], "umd");
expect(script).toMatchInlineSnapshot(`
"(function (root, factory) {
if (typeof define === \\"function\\" && define.amd) {
define([\\"exports\\"], factory);
} else if (typeof exports === \\"object\\") {
factory(exports);
} else {
factory(root.babelHelpers = {});
}
})(this, function (global) {
var babelHelpers = global;
function _get() {
return babelHelpers.get = _get = \\"undefined\\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) {
var p = babelHelpers.superPropBase(e, t);
if (p) {
var n = Object.getOwnPropertyDescriptor(p, t);
return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value;
}
}, _get.apply(null, arguments);
}
babelHelpers.get = _get;
});"
`);
});

it("var", function () {
const script = babel.buildExternalHelpers(["get"], "var");
expect(script).toMatchInlineSnapshot(`
"var babelHelpers = {};
function _get() {
return babelHelpers.get = _get = \\"undefined\\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) {
var p = babelHelpers.superPropBase(e, t);
if (p) {
var n = Object.getOwnPropertyDescriptor(p, t);
return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value;
}
}, _get.apply(null, arguments);
}
babelHelpers.get = _get;
babelHelpers;"
`);
});

it("module", function () {
const script = babel.buildExternalHelpers(["get"], "module");
expect(script).toMatchInlineSnapshot(`
"export { _get as get };
function _get() {
return _get = \\"undefined\\" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) {
var p = _superPropBase(e, t);
if (p) {
var n = Object.getOwnPropertyDescriptor(p, t);
return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value;
}
}, _get.apply(null, arguments);
}"
`);
});
});
});

describe("handle parsing errors", function () {
Expand Down
2 changes: 0 additions & 2 deletions packages/babel-helpers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@
"main": "./lib/index.js",
"dependencies": {
"@babel/template": "workspace:^",
"@babel/traverse": "workspace:^",
"@babel/types": "workspace:^"
},
"devDependencies": {
"@babel/core": "workspace:^",
"@babel/generator": "workspace:^",
"@babel/helper-plugin-test-runner": "workspace:^",
"@babel/parser": "workspace:^",
Expand Down
Loading

0 comments on commit 553e433

Please sign in to comment.