Sebastian McKenzie ae7d5367f1 6.0.0
I'm extremely stupid and didn't commit as I go. To anyone reading this
I'm extremely sorry. A lot of these changes are very broad and I plan on
releasing Babel 6.0.0 today live on stage at Ember Camp London so I'm
afraid I couldn't wait. If you're ever in London I'll buy you a beer
(or assorted beverage!) to make up for it, also I'll kiss your feet and
give you a back massage, maybe.
2015-10-29 17:51:24 +00:00

110 lines
2.7 KiB
JavaScript

import template from "babel-template";
let buildDefine = template(`
define(MODULE_NAME, [SOURCES], function (PARAMS) {
BODY;
});
`);
export default function ({ types: t }) {
function isValidRequireCall(path) {
if (!path.isCallExpression()) return false;
if (!path.get("callee").isIdentifier({ name: "require" })) return false;
if (path.scope.getBinding("require")) return false;
let args = path.get("arguments");
if (args.length !== 1) return false;
let arg = args[0];
if (!arg.isStringLiteral()) return false;
return true;
}
let amdVisitor = {
ReferencedIdentifier({ node, scope }) {
if (node.name === "exports" && !scope.getBinding("exports")) {
this.hasExports = true;
}
if (node.name === "module" && !scope.getBinding("module")) {
this.hasModule = true;
}
},
CallExpression(path) {
if (!isValidRequireCall(path)) return;
this.bareSources.push(path.node.arguments[0]);
path.remove();
},
VariableDeclarator(path) {
let id = path.get("id");
if (!id.isIdentifier()) return;
let init = path.get("init");
if (!isValidRequireCall(init)) return;
let source = init.node.arguments[0];
this.sourceNames[source.value] = true;
this.sources.push([id.node, source]);
path.remove();
}
};
return {
inherits: require("babel-plugin-transform-es2015-modules-commonjs"),
pre() {
// source strings
this.sources = [];
this.sourceNames = Object.create(null);
// bare sources
this.bareSources = [];
this.hasExports = false;
this.hasModule = false;
},
visitor: {
Program: {
exit(path) {
if (this.ran) return;
this.ran = true;
path.traverse(amdVisitor, this);
let params = this.sources.map(source => source[0]);
let sources = this.sources.map(source => source[1]);
sources = sources.concat(this.bareSources.filter((str) => {
return !this.sourceNames[str.value];
}));
let moduleName = this.getModuleName();
if (moduleName) moduleName = t.stringLiteral(moduleName);
if (this.hasExports) {
sources.unshift(t.stringLiteral("exports"));
params.unshift(t.identifier("exports"));
}
if (this.hasModule) {
sources.unshift(t.stringLiteral("module"));
params.unshift(t.identifier("module"));
}
path.node.body = [buildDefine({
MODULE_NAME: moduleName,
SOURCES: sources,
PARAMS: params,
BODY: path.node.body
})];
}
}
}
};
}