babel-core
Version:
Turn ES6 code into readable vanilla ES5 with source maps
371 lines (286 loc) • 11.2 kB
JavaScript
"use strict";
var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; };
var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; };
var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
var messages = _interopRequireWildcard(require("../../messages"));
var traverse = _interopRequire(require("../../traversal"));
var extend = _interopRequire(require("lodash/object/extend"));
var object = _interopRequire(require("../../helpers/object"));
var util = _interopRequireWildcard(require("../../util"));
var t = _interopRequireWildcard(require("../../types"));
var remapVisitor = {
enter: function enter(node, parent, scope, formatter) {
var remap = formatter.internalRemap[node.name];
if (this.isReferencedIdentifier() && remap) {
if (!scope.hasBinding(node.name) || scope.bindingIdentifierEquals(node.name, formatter.localImports[node.name])) {
return remap;
}
}
if (t.isUpdateExpression(node)) {
var exported = formatter.getExport(node.argument, scope);
if (exported) {
this.skip();
// expand to long file assignment expression
var assign = t.assignmentExpression(node.operator[0] + "=", node.argument, t.literal(1));
// remap this assignment expression
var remapped = formatter.remapExportAssignment(assign, exported);
// we don't need to change the result
if (t.isExpressionStatement(parent) || node.prefix) {
return remapped;
}
var nodes = [];
nodes.push(remapped);
var operator;
if (node.operator === "--") {
operator = "+";
} else {
// "++"
operator = "-";
}
nodes.push(t.binaryExpression(operator, node.argument, t.literal(1)));
return t.sequenceExpression(nodes);
}
}
if (t.isAssignmentExpression(node)) {
var exported = formatter.getExport(node.left, scope);
if (exported) {
this.skip();
return formatter.remapExportAssignment(node, exported);
}
}
}
};
var importsVisitor = {
ImportDeclaration: {
enter: function enter(node, parent, scope, formatter) {
formatter.hasLocalImports = true;
extend(formatter.localImports, this.getBindingIdentifiers());
formatter.bumpImportOccurences(node);
}
}
};
var exportsVisitor = traverse.explode({
ExportDeclaration: {
enter: function enter(node, parent, scope, formatter) {
formatter.hasLocalImports = true;
var declar = this.get("declaration");
if (declar.isStatement()) {
var bindings = declar.getBindingIdentifiers();
for (var name in bindings) {
var binding = bindings[name];
formatter._addExport(name, binding);
}
}
if (this.isExportNamedDeclaration() && node.specifiers) {
for (var i = 0; i < node.specifiers.length; i++) {
var specifier = node.specifiers[i];
var local = specifier.local;
if (!local) continue;
formatter._addExport(local.name, specifier.exported);
}
}
if (!t.isExportDefaultDeclaration(node)) {
var onlyDefault = node.specifiers && node.specifiers.length === 1 && t.isSpecifierDefault(node.specifiers[0]);
if (!onlyDefault) {
formatter.hasNonDefaultExports = true;
}
}
if (node.source) {
formatter.bumpImportOccurences(node);
}
}
}
});
var DefaultFormatter = (function () {
function DefaultFormatter(file) {
_classCallCheck(this, DefaultFormatter);
this.internalRemap = {};
this.defaultIds = object();
this.scope = file.scope;
this.file = file;
this.ids = object();
this.hasNonDefaultExports = false;
this.hasLocalExports = false;
this.hasLocalImports = false;
this.localImportOccurences = object();
this.localExports = object();
this.localImports = object();
this.getLocalExports();
this.getLocalImports();
}
DefaultFormatter.prototype.transform = function transform() {
this.remapAssignments();
};
DefaultFormatter.prototype.doDefaultExportInterop = function doDefaultExportInterop(node) {
return (t.isExportDefaultDeclaration(node) || t.isSpecifierDefault(node)) && !this.noInteropRequireExport && !this.hasNonDefaultExports;
};
DefaultFormatter.prototype.bumpImportOccurences = function bumpImportOccurences(node) {
var source = node.source.value;
var occurs = this.localImportOccurences;
var _occurs = occurs;
var _source = source;
if (!_occurs[_source]) _occurs[_source] = 0;
if (node.specifiers) {
occurs[source] += node.specifiers.length;
}
};
DefaultFormatter.prototype.getLocalExports = function getLocalExports() {
this.file.path.traverse(exportsVisitor, this);
};
DefaultFormatter.prototype.getLocalImports = function getLocalImports() {
this.file.path.traverse(importsVisitor, this);
};
DefaultFormatter.prototype.remapAssignments = function remapAssignments() {
if (this.hasLocalImports) {
this.file.path.traverse(remapVisitor, this);
}
};
DefaultFormatter.prototype.remapExportAssignment = function remapExportAssignment(node, exported) {
var assign = node;
for (var i = 0; i < exported.length; i++) {
assign = t.assignmentExpression("=", t.memberExpression(t.identifier("exports"), exported[i]), assign);
}
return assign;
};
DefaultFormatter.prototype._addExport = function _addExport(name, exported) {
var _localExports, _name;
var info = (_localExports = this.localExports, _name = name, !_localExports[_name] && (_localExports[_name] = {
binding: this.scope.getBindingIdentifier(name),
exported: []
}), _localExports[_name]);
info.exported.push(exported);
};
DefaultFormatter.prototype.getExport = function getExport(node, scope) {
if (!t.isIdentifier(node)) return;
var local = this.localExports[node.name];
if (local && local.binding === scope.getBindingIdentifier(node.name)) {
return local.exported;
}
};
DefaultFormatter.prototype.getModuleName = function getModuleName() {
var opts = this.file.opts;
if (opts.moduleId) return opts.moduleId;
var filenameRelative = opts.filenameRelative;
var moduleName = "";
if (opts.moduleRoot) {
moduleName = opts.moduleRoot + "/";
}
if (!opts.filenameRelative) {
return moduleName + opts.filename.replace(/^\//, "");
}
if (opts.sourceRoot) {
// remove sourceRoot from filename
var sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "/?");
filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
}
if (!opts.keepModuleIdExtensions) {
// remove extension
filenameRelative = filenameRelative.replace(/\.(\w*?)$/, "");
}
moduleName += filenameRelative;
// normalize path separators
moduleName = moduleName.replace(/\\/g, "/");
return moduleName;
};
DefaultFormatter.prototype._pushStatement = function _pushStatement(ref, nodes) {
if (t.isClass(ref) || t.isFunction(ref)) {
if (ref.id) {
nodes.push(t.toStatement(ref));
ref = ref.id;
}
}
return ref;
};
DefaultFormatter.prototype._hoistExport = function _hoistExport(declar, assign, priority) {
if (t.isFunctionDeclaration(declar)) {
assign._blockHoist = priority || 2;
}
return assign;
};
DefaultFormatter.prototype.getExternalReference = function getExternalReference(node, nodes) {
var ids = this.ids;
var id = node.source.value;
if (ids[id]) {
return ids[id];
} else {
return this.ids[id] = this._getExternalReference(node, nodes);
}
};
DefaultFormatter.prototype.checkExportIdentifier = function checkExportIdentifier(node) {
if (t.isIdentifier(node, { name: "__esModule" })) {
throw this.file.errorWithNode(node, messages.get("modulesIllegalExportName", node.name));
}
};
DefaultFormatter.prototype.exportAllDeclaration = function exportAllDeclaration(node, nodes) {
var ref = this.getExternalReference(node, nodes);
nodes.push(this.buildExportsWildcard(ref, node));
};
DefaultFormatter.prototype.isLoose = function isLoose() {
return this.file.isLoose("es6.modules");
};
DefaultFormatter.prototype.exportSpecifier = function exportSpecifier(specifier, node, nodes) {
if (node.source) {
var ref = this.getExternalReference(node, nodes);
if (specifier.local.name === "default" && !this.noInteropRequireExport) {
// importing a default so we need to normalize it
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
} else {
ref = t.memberExpression(ref, specifier.local);
if (!this.isLoose()) {
nodes.push(this.buildExportsFromAssignment(specifier.exported, ref, node));
return;
}
}
// export { foo } from "test";
nodes.push(this.buildExportsAssignment(specifier.exported, ref, node));
} else {
// export { foo };
nodes.push(this.buildExportsAssignment(specifier.exported, specifier.local, node));
}
};
DefaultFormatter.prototype.buildExportsWildcard = function buildExportsWildcard(objectIdentifier) {
return t.expressionStatement(t.callExpression(this.file.addHelper("defaults"), [t.identifier("exports"), t.callExpression(this.file.addHelper("interop-require-wildcard"), [objectIdentifier])]));
};
DefaultFormatter.prototype.buildExportsFromAssignment = function buildExportsFromAssignment(id, init) {
this.checkExportIdentifier(id);
return util.template("exports-from-assign", {
INIT: init,
ID: t.literal(id.name)
}, true);
};
DefaultFormatter.prototype.buildExportsAssignment = function buildExportsAssignment(id, init) {
this.checkExportIdentifier(id);
return util.template("exports-assign", {
VALUE: init,
KEY: id
}, true);
};
DefaultFormatter.prototype.exportDeclaration = function exportDeclaration(node, nodes) {
var declar = node.declaration;
var id = declar.id;
if (t.isExportDefaultDeclaration(node)) {
id = t.identifier("default");
}
var assign;
if (t.isVariableDeclaration(declar)) {
for (var i = 0; i < declar.declarations.length; i++) {
var decl = declar.declarations[i];
decl.init = this.buildExportsAssignment(decl.id, decl.init, node).expression;
var newDeclar = t.variableDeclaration(declar.kind, [decl]);
if (i === 0) t.inherits(newDeclar, declar);
nodes.push(newDeclar);
}
} else {
var ref = declar;
if (t.isFunctionDeclaration(declar) || t.isClassDeclaration(declar)) {
ref = declar.id;
nodes.push(declar);
}
assign = this.buildExportsAssignment(id, ref, node);
nodes.push(assign);
this._hoistExport(declar, assign);
}
};
return DefaultFormatter;
})();
module.exports = DefaultFormatter;