From 5ea54f6cacdf71f585ef39a974c4e44c29922e6b Mon Sep 17 00:00:00 2001 From: Logan Smyth Date: Tue, 3 Oct 2017 13:58:47 -0700 Subject: [PATCH] Fix "module" external helpers output (#6377) * Move namespace init. * Move call to helper generation. * Generate named module exports properly. * Ensure that helper names are valid identifiers. --- .../src/tools/build-external-helpers.js | 94 +++++++------------ 1 file changed, 34 insertions(+), 60 deletions(-) diff --git a/packages/babel-core/src/tools/build-external-helpers.js b/packages/babel-core/src/tools/build-external-helpers.js index 081b8ebbf0..7b9d94ac43 100644 --- a/packages/babel-core/src/tools/build-external-helpers.js +++ b/packages/babel-core/src/tools/build-external-helpers.js @@ -3,8 +3,6 @@ import generator from "babel-generator"; import template from "babel-template"; import * as t from "babel-types"; -const keywordHelpers = ["typeof", "extends", "instanceof"]; - const buildUmdWrapper = template(` (function (root, factory) { if (typeof define === "function" && define.amd) { @@ -19,7 +17,9 @@ const buildUmdWrapper = template(` }); `); -function buildGlobal(namespace, builder) { +function buildGlobal(whitelist) { + const namespace = t.identifier("babelHelpers"); + const body = []; const container = t.functionExpression( null, @@ -56,55 +56,30 @@ function buildGlobal(namespace, builder) { ]), ); - builder(body); + buildHelpers(body, namespace, whitelist); return tree; } -function buildModule(namespace, builder) { +function buildModule(whitelist) { const body = []; - builder(body); + const refs = buildHelpers(body, null, whitelist); - const module = body.map(helperNode => { - const possibleAssignment = t.isExpressionStatement(helperNode) - ? helperNode.expression - : helperNode; + body.unshift( + t.exportNamedDeclaration( + null, + Object.keys(refs).map(name => { + return t.exportSpecifier(t.clone(refs[name]), t.identifier(name)); + }), + ), + ); - const isExportedHelper = - t.isAssignmentExpression(possibleAssignment) && - t.isMemberExpression(possibleAssignment.left) && - possibleAssignment.left.object.name === namespace.name; - - if (!isExportedHelper) { - return helperNode; - } - - const exportedHelper = possibleAssignment; - - const identifier = exportedHelper.left.property.name; - const isKeywordHelper = keywordHelpers.indexOf(identifier) !== -1; - - if (isKeywordHelper) { - return t.exportNamedDeclaration(null, [ - t.exportSpecifier( - t.identifier(`_${identifier}`), - t.identifier(identifier), - ), - ]); - } - - return t.exportNamedDeclaration( - t.variableDeclaration("var", [ - t.variableDeclarator(t.identifier(identifier), exportedHelper.right), - ]), - [], - ); - }); - - return t.program(module); + return t.program(body, [], "module"); } -function buildUmd(namespace, builder) { +function buildUmd(whitelist) { + const namespace = t.identifier("babelHelpers"); + const body = []; body.push( t.variableDeclaration("var", [ @@ -112,7 +87,7 @@ function buildUmd(namespace, builder) { ]), ); - builder(body); + buildHelpers(body, namespace, whitelist); return t.program([ buildUmdWrapper({ @@ -130,7 +105,9 @@ function buildUmd(namespace, builder) { ]); } -function buildVar(namespace, builder) { +function buildVar(whitelist) { + const namespace = t.identifier("babelHelpers"); + const body = []; body.push( t.variableDeclaration("var", [ @@ -138,37 +115,34 @@ function buildVar(namespace, builder) { ]), ); const tree = t.program(body); - builder(body); + buildHelpers(body, namespace, whitelist); body.push(t.expressionStatement(namespace)); return tree; } function buildHelpers(body, namespace, whitelist) { - const getHelperReference = name => - t.memberExpression(namespace, t.identifier(name)); + const getHelperReference = name => { + return namespace + ? t.memberExpression(namespace, t.identifier(name)) + : t.identifier(`_${name}`); + }; + const refs = {}; helpers.list.forEach(function(name) { if (whitelist && whitelist.indexOf(name) < 0) return; - const { nodes } = helpers.get( - name, - getHelperReference, - getHelperReference(name), - ); + const ref = (refs[name] = getHelperReference(name)); + + const { nodes } = helpers.get(name, getHelperReference, ref); body.push(...nodes); }); + return refs; } export default function( whitelist?: Array, outputType: "global" | "module" | "umd" | "var" = "global", ) { - const namespace = t.identifier("babelHelpers"); - - const builder = function(body) { - return buildHelpers(body, namespace, whitelist); - }; - let tree; const build = { @@ -179,7 +153,7 @@ export default function( }[outputType]; if (build) { - tree = build(namespace, builder); + tree = build(whitelist); } else { throw new Error(`Unsupported output type ${outputType}`); }