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.
This commit is contained in:
Logan Smyth 2017-10-03 13:58:47 -07:00 committed by GitHub
parent 68182bd69f
commit 5ea54f6cac

View File

@ -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<string>,
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}`);
}