avoid duplicate requires when importing modules
This commit is contained in:
@@ -10,108 +10,71 @@ var _ = require("lodash");
|
||||
|
||||
function DefaultFormatter(file) {
|
||||
this.file = file;
|
||||
this.ids = object();
|
||||
|
||||
this.localExports = this.getLocalExports();
|
||||
this.localImports = this.getLocalImports();
|
||||
this.hasLocalExports = false;
|
||||
this.hasLocalImports = false;
|
||||
|
||||
this.localImportOccurences = object();
|
||||
this.localExports = object();
|
||||
this.localImports = object();
|
||||
|
||||
this.getLocalExports();
|
||||
this.getLocalImports();
|
||||
|
||||
this.remapAssignments();
|
||||
|
||||
//this.checkCollisions();
|
||||
}
|
||||
|
||||
DefaultFormatter.prototype.bumpImportOccurences = function (node) {
|
||||
var source = node.source.value;
|
||||
this.localImportOccurences[source] = this.localImportOccurences[source] || 0;
|
||||
this.localImportOccurences[source] += node.specifiers.length;
|
||||
};
|
||||
|
||||
var exportsVisitor = {
|
||||
enter: function (node, parent, scope, context, localExports) {
|
||||
enter: function (node, parent, scope, context, formatter) {
|
||||
var declar = node && node.declaration;
|
||||
if (t.isExportDeclaration(node) && declar && t.isStatement(declar)) {
|
||||
_.extend(localExports, t.getIds(declar, true));
|
||||
if (t.isExportDeclaration(node)) {
|
||||
formatter.hasLocalImports = true;
|
||||
if (declar && t.isStatement(declar)) {
|
||||
_.extend(formatter.localExports, t.getIds(declar, true));
|
||||
}
|
||||
|
||||
if (node.source) {
|
||||
formatter.bumpImportOccurences(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.getLocalExports = function () {
|
||||
var localExports = object();
|
||||
traverse(this.file.ast, exportsVisitor, this.file.scope, localExports);
|
||||
return localExports;
|
||||
traverse(this.file.ast, exportsVisitor, this.file.scope, this);
|
||||
};
|
||||
|
||||
var importsVisitor = {
|
||||
enter: function (node, parent, scope, context, localImports) {
|
||||
enter: function (node, parent, scope, context, formatter) {
|
||||
if (t.isImportDeclaration(node)) {
|
||||
_.extend(localImports, t.getIds(node, true));
|
||||
formatter.hasLocalImports = true;
|
||||
_.extend(formatter.localImports, t.getIds(node, true));
|
||||
formatter.bumpImportOccurences(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.getLocalImports = function () {
|
||||
var localImports = object();
|
||||
traverse(this.file.ast, importsVisitor, this.file.scope, localImports);
|
||||
return localImports;
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.isLocalReference = function (node) {
|
||||
var localImports = this.localImports;
|
||||
return t.isIdentifier(node) && localImports[node.name] && localImports[node.name] !== node;
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.checkLocalReference = function (node) {
|
||||
var file = this.file;
|
||||
if (this.isLocalReference(node)) {
|
||||
throw file.errorWithNode(node, "Illegal assignment of module import");
|
||||
}
|
||||
};
|
||||
|
||||
var collissionsVisitor = {
|
||||
enter: function (node, parent, scope, context, state) {
|
||||
var self = state.self;
|
||||
if (t.isAssignmentExpression(node)) {
|
||||
|
||||
var left = node.left;
|
||||
if (t.isMemberExpression(left)) {
|
||||
while (left.object) left = left.object;
|
||||
}
|
||||
|
||||
self.checkLocalReference(left);
|
||||
} else if (t.isDeclaration(node)) {
|
||||
_.each(t.getIds(node, true), self.checkLocalReference);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.checkCollisions = function () {
|
||||
// todo: all check export collissions
|
||||
var state = { self: this };
|
||||
traverse(this.file.ast, collissionsVisitor, null, state);
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.remapExportAssignment = function (node) {
|
||||
return t.assignmentExpression(
|
||||
"=",
|
||||
node.left,
|
||||
t.assignmentExpression(
|
||||
node.operator,
|
||||
t.memberExpression(t.identifier("exports"), node.left),
|
||||
node.right
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.isLocalReference = function (node, scope) {
|
||||
var localExports = this.localExports;
|
||||
var name = node.name;
|
||||
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.get(name, true);
|
||||
traverse(this.file.ast, importsVisitor, this.file.scope, this);
|
||||
};
|
||||
|
||||
var remapVisitor = {
|
||||
enter: function (node, parent, scope, context, state) {
|
||||
var self = state.self;
|
||||
if (t.isUpdateExpression(node) && self.isLocalReference(node.argument, scope)) {
|
||||
enter: function (node, parent, scope, context, formatter) {
|
||||
if (t.isUpdateExpression(node) && formatter.isLocalReference(node.argument, scope)) {
|
||||
context.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 = self.remapExportAssignment(assign);
|
||||
var remapped = formatter.remapExportAssignment(assign);
|
||||
|
||||
// we don't need to change the result
|
||||
if (t.isExpressionStatement(parent) || node.prefix) {
|
||||
@@ -132,16 +95,47 @@ var remapVisitor = {
|
||||
return t.sequenceExpression(nodes);
|
||||
}
|
||||
|
||||
if (t.isAssignmentExpression(node) && self.isLocalReference(node.left, scope)) {
|
||||
if (t.isAssignmentExpression(node) && formatter.isLocalReference(node.left, scope)) {
|
||||
context.skip();
|
||||
return self.remapExportAssignment(node);
|
||||
return formatter.remapExportAssignment(node);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.remapAssignments = function () {
|
||||
var state = { self: this };
|
||||
traverse(this.file.ast, remapVisitor, this.file.scope, state);
|
||||
if (this.hasLocalImports) {
|
||||
traverse(this.file.ast, remapVisitor, this.file.scope, this);
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.isLocalReference = function (node) {
|
||||
var localImports = this.localImports;
|
||||
return t.isIdentifier(node) && localImports[node.name] && localImports[node.name] !== node;
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.checkLocalReference = function (node) {
|
||||
var file = this.file;
|
||||
if (this.isLocalReference(node)) {
|
||||
throw file.errorWithNode(node, "Illegal assignment of module import");
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.remapExportAssignment = function (node) {
|
||||
return t.assignmentExpression(
|
||||
"=",
|
||||
node.left,
|
||||
t.assignmentExpression(
|
||||
node.operator,
|
||||
t.memberExpression(t.identifier("exports"), node.left),
|
||||
node.right
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.isLocalReference = function (node, scope) {
|
||||
var localExports = this.localExports;
|
||||
var name = node.name;
|
||||
return t.isIdentifier(node) && localExports[name] && localExports[name] === scope.get(name, true);
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.getModuleName = function () {
|
||||
@@ -195,21 +189,34 @@ DefaultFormatter.prototype._hoistExport = function (declar, assign, priority) {
|
||||
return assign;
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype._exportSpecifier = function (getRef, specifier, node, nodes) {
|
||||
DefaultFormatter.prototype.push = function (node, nodes) {
|
||||
var ids = this.ids;
|
||||
var id = node.source.value;
|
||||
|
||||
if (ids[id]) {
|
||||
return ids[id];
|
||||
} else {
|
||||
return this.ids[id] = this._push(node, nodes);
|
||||
}
|
||||
};
|
||||
|
||||
DefaultFormatter.prototype.exportSpecifier = function (specifier, node, nodes) {
|
||||
var inherits = false;
|
||||
if (node.specifiers.length === 1) inherits = node;
|
||||
|
||||
if (node.source) {
|
||||
var ref = this.push(node, nodes);
|
||||
|
||||
if (t.isExportBatchSpecifier(specifier)) {
|
||||
// export * from "foo";
|
||||
nodes.push(this._exportsWildcard(getRef(), node));
|
||||
nodes.push(this._exportsWildcard(ref, node));
|
||||
} else {
|
||||
var ref;
|
||||
if (t.isSpecifierDefault(specifier) && !this.noInteropRequire) {
|
||||
// importing a default so we need to normalise it
|
||||
ref = t.callExpression(this.file.addHelper("interop-require"), [getRef()]);
|
||||
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
|
||||
} else {
|
||||
ref = t.memberExpression(getRef(), t.getSpecifierId(specifier));
|
||||
ref = t.memberExpression(ref, t.getSpecifierId(specifier));
|
||||
}
|
||||
|
||||
// export { foo } from "test";
|
||||
|
||||
@@ -10,7 +10,6 @@ var _ = require("lodash");
|
||||
|
||||
function AMDFormatter() {
|
||||
CommonFormatter.apply(this, arguments);
|
||||
this.ids = {};
|
||||
}
|
||||
|
||||
util.inherits(AMDFormatter, DefaultFormatter);
|
||||
@@ -69,23 +68,16 @@ AMDFormatter.prototype.getModuleName = function () {
|
||||
};
|
||||
|
||||
AMDFormatter.prototype._push = function (node) {
|
||||
var id = node.source.value;
|
||||
var ids = this.ids;
|
||||
|
||||
if (ids[id]) {
|
||||
return ids[id];
|
||||
} else {
|
||||
return this.ids[id] = this.file.generateUidIdentifier(id);
|
||||
}
|
||||
return this.file.generateUidIdentifier(node.source.value);
|
||||
};
|
||||
|
||||
AMDFormatter.prototype.importDeclaration = function (node) {
|
||||
this._push(node);
|
||||
this.push(node);
|
||||
};
|
||||
|
||||
AMDFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
|
||||
var key = t.getSpecifierName(specifier);
|
||||
var ref = this._push(node);
|
||||
var ref = this.push(node);
|
||||
|
||||
if (_.contains(this.file.dynamicImported, node)) {
|
||||
// Prevent unnecessary renaming of dynamic imports.
|
||||
@@ -113,10 +105,3 @@ AMDFormatter.prototype.exportDeclaration = function (node) {
|
||||
|
||||
CommonFormatter.prototype.exportDeclaration.apply(this, arguments);
|
||||
};
|
||||
|
||||
AMDFormatter.prototype.exportSpecifier = function (specifier, node, nodes) {
|
||||
var self = this;
|
||||
return this._exportSpecifier(function () {
|
||||
return self._push(node);
|
||||
}, specifier, node, nodes);
|
||||
};
|
||||
|
||||
@@ -10,7 +10,10 @@ var _ = require("lodash");
|
||||
|
||||
var visitor = {
|
||||
enter: function (node, parent, scope, context, state) {
|
||||
if (t.isExportDeclaration(node) && !node.default) state.hasNonDefaultExports = true;
|
||||
if (t.isExportDeclaration(node) && !node.default) {
|
||||
state.hasNonDefaultExports = true;
|
||||
context.stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -29,11 +32,10 @@ util.inherits(CommonJSFormatter, DefaultFormatter);
|
||||
CommonJSFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
|
||||
var variableName = t.getSpecifierName(specifier);
|
||||
|
||||
var ref = this.push(node, nodes);
|
||||
|
||||
// import foo from "foo";
|
||||
if (t.isSpecifierDefault(specifier)) {
|
||||
var ref = util.template("require", {
|
||||
MODULE_NAME: node.source
|
||||
});
|
||||
if (!_.contains(this.file.dynamicImported, node)) {
|
||||
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
|
||||
}
|
||||
@@ -45,17 +47,18 @@ CommonJSFormatter.prototype.importSpecifier = function (specifier, node, nodes)
|
||||
t.variableDeclarator(
|
||||
variableName,
|
||||
t.callExpression(this.file.addHelper("interop-require-wildcard"), [
|
||||
t.callExpression(t.identifier("require"), [node.source])
|
||||
ref
|
||||
])
|
||||
)
|
||||
]));
|
||||
} else {
|
||||
// import foo from "foo";
|
||||
nodes.push(util.template("require-assign-key", {
|
||||
VARIABLE_NAME: variableName,
|
||||
MODULE_NAME: node.source,
|
||||
KEY: t.getSpecifierId(specifier)
|
||||
}));
|
||||
// import { foo } from "foo";
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(
|
||||
variableName,
|
||||
t.memberExpression(ref, t.getSpecifierId(specifier))
|
||||
)
|
||||
]));
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -95,8 +98,17 @@ CommonJSFormatter.prototype.exportDeclaration = function (node, nodes) {
|
||||
DefaultFormatter.prototype.exportDeclaration.apply(this, arguments);
|
||||
};
|
||||
|
||||
CommonJSFormatter.prototype.exportSpecifier = function (specifier, node, nodes) {
|
||||
this._exportSpecifier(function () {
|
||||
return t.callExpression(t.identifier("require"), [node.source]);
|
||||
}, specifier, node, nodes);
|
||||
CommonJSFormatter.prototype._push = function (node, nodes) {
|
||||
var source = node.source.value;
|
||||
var call = t.callExpression(t.identifier("require"), [node.source]);
|
||||
|
||||
if (this.localImportOccurences[source] > 1) {
|
||||
var uid = this.file.generateUidIdentifier(source);
|
||||
nodes.push(t.variableDeclaration("var", [
|
||||
t.variableDeclarator(uid, call)
|
||||
]));
|
||||
return uid;
|
||||
} else {
|
||||
return call;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -16,12 +16,14 @@ var _defaults = function (obj, defaults) {
|
||||
return obj;
|
||||
};
|
||||
|
||||
_defaults(exports, _interopRequireWildcard(require("foo")));
|
||||
var _foo = require("foo");
|
||||
|
||||
exports.foo = require("foo").foo;
|
||||
exports.foo = require("foo").foo;
|
||||
exports.bar = require("foo").bar;
|
||||
exports.bar = require("foo").foo;
|
||||
exports["default"] = require("foo").foo;
|
||||
exports["default"] = require("foo").foo;
|
||||
exports.bar = require("foo").bar;
|
||||
_defaults(exports, _interopRequireWildcard(_foo));
|
||||
|
||||
exports.foo = _foo.foo;
|
||||
exports.foo = _foo.foo;
|
||||
exports.bar = _foo.bar;
|
||||
exports.bar = _foo.foo;
|
||||
exports["default"] = _foo.foo;
|
||||
exports["default"] = _foo.foo;
|
||||
exports.bar = _foo.bar;
|
||||
|
||||
@@ -10,4 +10,4 @@ var isOdd = exports.isOdd = (function (isEven) {
|
||||
return function (n) {
|
||||
return !isEven(n);
|
||||
};
|
||||
})(isEven);
|
||||
})(isEven);
|
||||
@@ -4,6 +4,8 @@ var _interopRequire = function (obj) {
|
||||
return obj && obj.__esModule ? obj["default"] : obj;
|
||||
};
|
||||
|
||||
var foo = _interopRequire(require("foo"));
|
||||
var _foo = require("foo");
|
||||
|
||||
var foo2 = _interopRequire(require("foo"));
|
||||
var foo = _interopRequire(_foo);
|
||||
|
||||
var foo2 = _interopRequire(_foo);
|
||||
@@ -4,6 +4,8 @@ var _interopRequire = function (obj) {
|
||||
return obj && obj.__esModule ? obj["default"] : obj;
|
||||
};
|
||||
|
||||
var foo = _interopRequire(require("foo"));
|
||||
var _foo = require("foo");
|
||||
|
||||
var xyz = require("foo").baz;
|
||||
var foo = _interopRequire(_foo);
|
||||
|
||||
var xyz = _foo.baz;
|
||||
@@ -1,8 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
var bar = require("foo").bar;
|
||||
var bar2 = require("foo").bar2;
|
||||
var baz = require("foo").baz;
|
||||
var baz2 = require("foo").bar;
|
||||
var baz3 = require("foo").bar;
|
||||
var xyz = require("foo").xyz;
|
||||
var _foo = require("foo");
|
||||
|
||||
var bar = _foo.bar;
|
||||
var bar2 = _foo.bar2;
|
||||
var baz = _foo.baz;
|
||||
var baz2 = _foo.bar;
|
||||
var baz3 = _foo.bar;
|
||||
var xyz = _foo.xyz;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import "foo";
|
||||
import "foo-bar";
|
||||
import "./directory/foo-bar";
|
||||
import foo from "foo";
|
||||
import * as foo2 from "foo";
|
||||
import {bar} from "foo";
|
||||
import {foo as bar2} from "foo";
|
||||
import foo from "foo2";
|
||||
import * as foo2 from "foo3";
|
||||
import {bar} from "foo4";
|
||||
import {foo as bar2} from "foo5";
|
||||
|
||||
export {test};
|
||||
export var test = 5;
|
||||
|
||||
@@ -16,11 +16,11 @@ require("foo-bar");
|
||||
|
||||
require("./directory/foo-bar");
|
||||
|
||||
var foo = _interopRequire(require("foo"));
|
||||
var foo = _interopRequire(require("foo2"));
|
||||
|
||||
var foo2 = _interopRequireWildcard(require("foo"));
|
||||
var foo2 = _interopRequireWildcard(require("foo3"));
|
||||
|
||||
var bar = require("foo").bar;
|
||||
var bar2 = require("foo").foo;
|
||||
var bar = require("foo4").bar;
|
||||
var bar2 = require("foo5").foo;
|
||||
exports.test = test;
|
||||
var test = exports.test = 5;
|
||||
var test = exports.test = 5;
|
||||
@@ -20,8 +20,10 @@ var giveWord = _regeneratorRuntime.mark(function giveWord() {
|
||||
});
|
||||
|
||||
exports.giveWord = giveWord;
|
||||
var foo = _to5Helpers.interopRequire(require("someModule"));
|
||||
var _someModule = require("someModule");
|
||||
|
||||
var bar = _to5Helpers.interopRequireWildcard(require("someModule"));
|
||||
var foo = _to5Helpers.interopRequire(_someModule);
|
||||
|
||||
var myWord = exports.myWord = _core.Symbol("abc");
|
||||
var bar = _to5Helpers.interopRequireWildcard(_someModule);
|
||||
|
||||
var myWord = exports.myWord = _core.Symbol("abc");
|
||||
Reference in New Issue
Block a user