diff --git a/packages/babel-core/src/transformation/file/file.js b/packages/babel-core/src/transformation/file/file.js index 795a33b6bf..79ef660161 100644 --- a/packages/babel-core/src/transformation/file/file.js +++ b/packages/babel-core/src/transformation/file/file.js @@ -1,6 +1,6 @@ // @flow -import getHelper from "@babel/helpers"; +import * as helpers from "@babel/helpers"; import { NodePath, Hub, Scope } from "@babel/traverse"; import { codeFrameColumns } from "@babel/code-frame"; import traverse from "@babel/traverse"; @@ -132,11 +132,16 @@ export default class File { name, )); - const { nodes, globals } = getHelper( + const dependencies = {}; + for (const dep of helpers.getDependencies(name)) { + dependencies[dep] = this.addHelper(dep); + } + + const { nodes, globals } = helpers.get( name, - name => this.addHelper(name), + dep => dependencies[dep], uid, - () => Object.keys(this.scope.getAllBindings()), + Object.keys(this.scope.getAllBindings()), ); globals.forEach(name => { diff --git a/packages/babel-helpers/src/index.js b/packages/babel-helpers/src/index.js index 44cd492c07..c44a794f3d 100644 --- a/packages/babel-helpers/src/index.js +++ b/packages/babel-helpers/src/index.js @@ -134,8 +134,8 @@ function getHelperMetadata(file) { /** * Given a helper AST and information about how it will be used, update the AST to match the usage. */ -function permuteHelperAST(file, metadata, id, getLocalBindings, getDependency) { - if (getLocalBindings && !id) { +function permuteHelperAST(file, metadata, id, localBindings, getDependency) { + if (localBindings && !id) { throw new Error("Unexpected local bindings for module-based helpers."); } @@ -154,11 +154,11 @@ function permuteHelperAST(file, metadata, id, getLocalBindings, getDependency) { const dependenciesRefs = {}; dependencies.forEach((name, id) => { dependenciesRefs[id.name] = - typeof getDependency === "function" ? getDependency(name) : id; + (typeof getDependency === "function" && getDependency(name)) || id; }); const toRename = {}; - const bindings = new Set((getLocalBindings && getLocalBindings()) || []); + const bindings = new Set(localBindings || []); localBindingNames.forEach(name => { let newName = name; while (bindings.has(newName)) newName = "_" + newName; @@ -237,17 +237,17 @@ function loadHelper(name) { const metadata = getHelperMetadata(fn()); - // Preload dependencies - metadata.dependencies.forEach(loadHelper); + helperData[name] = { + build(getDependency, id, localBindings) { + const file = fn(); + permuteHelperAST(file, metadata, id, localBindings, getDependency); - helperData[name] = function(getDependency, id, getLocalBindings) { - const file = fn(); - permuteHelperAST(file, metadata, id, getLocalBindings, getDependency); - - return { - nodes: file.program.body, - globals: metadata.globals, - }; + return { + nodes: file.program.body, + globals: metadata.globals, + }; + }, + dependencies: metadata.dependencies, }; } @@ -256,12 +256,15 @@ function loadHelper(name) { export function get( name, - getDependency?: string => t.Expression, + getDependency?: string => ?t.Expression, id?, - getLocalBindings?: () => string[], + localBindings?: string[], ) { - const helper = loadHelper(name); - return helper(getDependency, id, getLocalBindings); + return loadHelper(name).build(getDependency, id, localBindings); +} + +export function getDependencies(name: string): $ReadOnlyArray { + return Array.from(loadHelper(name).dependencies.values()); } export const list = Object.keys(helpers) diff --git a/packages/babel-runtime/scripts/build-dist.js b/packages/babel-runtime/scripts/build-dist.js index 54f309907d..8f424f51d6 100644 --- a/packages/babel-runtime/scripts/build-dist.js +++ b/packages/babel-runtime/scripts/build-dist.js @@ -99,6 +99,15 @@ function buildRuntimeRewritePlugin(relativePath, helperName, dependencies) { }; } +function buildRequireCall(id, dep) { + return t.variableDeclaration("var", [ + t.variableDeclarator( + id, + t.callExpression(t.identifier("require"), [t.stringLiteral(dep)]) + ) + ]); +} + function buildHelper(helperName, modules, useBuiltIns) { const id = modules === "commonjs" @@ -106,12 +115,31 @@ function buildHelper(helperName, modules, useBuiltIns) { : null; const sourceType = modules === "commonjs" ? "script" : "module"; - const helper = helpers.get(helperName, null, id); - const tree = t.program(helper.nodes, [], sourceType); + const tree = t.program([], [], sourceType); + const dependencies = {}; + let bindings = null; + + if (modules === "commonjs") { + bindings = []; + for (const dep of helpers.getDependencies(helperName)) { + const id = dependencies[dep] = t.identifier(t.toIdentifier(dep)); + tree.body.push(buildRequireCall(id, dep)); + bindings.push(id.name); + } + } + + const helper = helpers.get( + helperName, + dep => dependencies[dep], + id, + bindings + ); + tree.body.push.apply(tree.body, helper.nodes); + const transformOpts = makeTransformOpts(modules, useBuiltIns); const relative = useBuiltIns ? "../.." : ".."; - + return babel.transformFromAst(tree, null, { presets: transformOpts.presets, plugins: transformOpts.plugins.concat([