blob: f07de350c1a286cdb91c81b21a28167c83654b76 [file] [log] [blame]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var async = require("async");
var diff = require("diff");
var fs = require("fs");
var glob = require("glob");
var lodash = require("lodash");
var os = require("os");
var path = require("path");
var ts = require("typescript");
var pad = require("pad");
var bundle_item_1 = require("./bundle-item");
var DependencyWalker = /** @class */ (function () {
function DependencyWalker(log) {
this.log = log;
this.requireRegexp = /\brequire\b/;
this.walk = require("acorn-walk");
}
DependencyWalker.prototype.hasRequire = function (s) {
return this.requireRegexp.test(s);
};
DependencyWalker.prototype.collectTypescriptDependencies = function (queue) {
var _this = this;
var dependencyCount = 0;
var ambientModuleNames = this.collectAmbientModules(queue);
queue.forEach(function (queued) {
queued.item.dependencies = _this.findUnresolvedTsRequires(queued.emitOutput);
var resolvedModules = queued.emitOutput.sourceFile.resolvedModules;
if (resolvedModules && !queued.emitOutput.isDeclarationFile) {
if (lodash.isMap(resolvedModules)) { // Typescript 2.2+
resolvedModules.forEach(function (resolvedModule, moduleName) {
_this.addBundleItem(queued, resolvedModule, moduleName, ambientModuleNames);
});
}
else { // Typescript 1.6.2 - 2.1.6
Object.keys(resolvedModules).forEach(function (moduleName) {
var resolvedModule = resolvedModules[moduleName];
_this.addBundleItem(queued, resolvedModule, moduleName, ambientModuleNames);
});
}
}
dependencyCount += queued.item.dependencies.length;
});
this.validateCase(queue);
return dependencyCount;
};
DependencyWalker.prototype.collectJavascriptDependencies = function (bundleItem, onDependenciesCollected) {
var _this = this;
var moduleNames = [];
var expressions = [];
var isRequire = function (node) {
return node.type === "CallExpression" &&
node.callee.type === "Identifier" &&
node.callee.name === "require";
};
var visitNode = function (node, state, c) {
if (!_this.hasRequire(bundleItem.source.slice(node.start, node.end))) {
return;
}
_this.walk.base[node.type](node, state, c);
if (isRequire(node) && node.arguments.length > 0) {
if (node.arguments[0].type === "Literal") {
if (!lodash.isString(node.arguments[0].value)) {
_this.log.error("Unexpected literal value: %s%sRequired by: %s", node.arguments[0].value, os.EOL, bundleItem.filename);
}
moduleNames.push(node.arguments[0].value);
}
else {
expressions.push(node.arguments[0]);
}
}
};
if (bundleItem.ast) {
this.walk.recursive(bundleItem.ast, null, {
Expression: visitNode,
Statement: visitNode
});
}
this.addDynamicDependencies(expressions, bundleItem, function (dynamicDependencies) {
onDependenciesCollected(moduleNames.concat(dynamicDependencies));
});
};
DependencyWalker.prototype.collectAmbientModules = function (queue) {
var ambientModuleNames = [];
queue.forEach(function (queued) {
if (queued.emitOutput.ambientModuleNames) {
ambientModuleNames.push.apply(ambientModuleNames, queued.emitOutput.ambientModuleNames);
}
});
return ambientModuleNames;
};
DependencyWalker.prototype.addBundleItem = function (queued, resolvedModule, moduleName, ambientModuleNames) {
if (ambientModuleNames.indexOf(moduleName) === -1) {
queued.item.dependencies.push(new bundle_item_1.BundleItem(moduleName, resolvedModule && resolvedModule.resolvedFileName));
}
};
DependencyWalker.prototype.findUnresolvedTsRequires = function (emitOutput) {
var dependencies = [];
if (emitOutput.isDeclarationFile) {
return dependencies;
}
var visitNode = function (node) {
if (node.kind === ts.SyntaxKind.CallExpression) {
var ce = node;
var expression = ce.expression ?
ce.expression :
undefined;
var argument = ce.arguments && ce.arguments.length ?
ce.arguments[0] :
undefined;
if (expression && expression.text === "require" &&
argument && typeof argument.text === "string") {
dependencies.push(new bundle_item_1.BundleItem(argument.text));
}
}
ts.forEachChild(node, visitNode);
};
visitNode(emitOutput.sourceFile);
return dependencies;
};
DependencyWalker.prototype.addDynamicDependencies = function (expressions, bundleItem, onDynamicDependenciesAdded) {
var _this = this;
var dynamicDependencies = [];
if (expressions.length === 0) {
process.nextTick(function () {
onDynamicDependenciesAdded(dynamicDependencies);
});
return;
}
async.each(expressions, function (expression, onExpressionResolved) {
var dynamicModuleName = _this.parseDynamicRequire(expression);
var directory = path.dirname(bundleItem.filename);
var pattern;
if (dynamicModuleName && dynamicModuleName !== "*") {
if (new bundle_item_1.BundleItem(dynamicModuleName).isNpmModule()) {
dynamicDependencies.push(dynamicModuleName);
onExpressionResolved();
}
else {
pattern = path.join(directory, dynamicModuleName);
glob(pattern, function (globError, matches) {
if (globError) {
throw globError;
}
async.each(matches, function (match, onMatchResolved) {
fs.stat(match, function (statError, stats) {
if (statError) {
throw statError;
}
if (stats.isFile()) {
_this.log.debug("Dynamic require: \nexpression: [%s]" +
"\nfilename: %s\nrequired by %s\nglob: %s", JSON.stringify(expression, undefined, 3), match, bundleItem.filename, pattern);
dynamicDependencies.push("./" + path.relative(directory, match));
}
onMatchResolved();
});
}, onExpressionResolved);
});
}
}
else {
onExpressionResolved();
}
}, function () {
onDynamicDependenciesAdded(dynamicDependencies);
});
};
DependencyWalker.prototype.parseDynamicRequire = function (expression) {
var visitNode = function (node) {
switch (node.type) {
case "BinaryExpression":
if (node.operator === "+") {
return visitNode(node.left) + visitNode(node.right);
}
break;
case "ExpressionStatement":
return visitNode(node.expression);
case "Literal":
return node.value + "";
case "Identifier":
return "*";
default:
return "";
}
};
return visitNode(expression);
};
DependencyWalker.prototype.validateCase = function (queue) {
var files = queue.map(function (q) {
return q.file.originalPath;
});
var fileslower = queue.map(function (q) {
return q.file.originalPath.toLowerCase();
});
queue.forEach(function (queued) {
if (queued.item.dependencies) {
queued.item.dependencies.forEach(function (dependency) {
if (dependency.filename && files.indexOf(dependency.filename) === -1) {
var lowerIndex = fileslower.indexOf(dependency.filename.toLowerCase());
if (lowerIndex !== -1) {
var result = diff.diffChars(files[lowerIndex], dependency.filename);
var arrows_1 = "";
result.forEach(function (part) {
if (part.added) {
arrows_1 += "^";
}
else if (!part.removed) {
arrows_1 += pad("", part.count);
}
});
throw new Error("Uppercase/lowercase mismatch importing " +
dependency.moduleName + " from " + queued.file.originalPath +
":" + os.EOL + os.EOL +
"filename: " + files[lowerIndex] + os.EOL +
"module name: " + dependency.filename + os.EOL +
" " + arrows_1 + os.EOL);
}
}
});
}
});
};
return DependencyWalker;
}());
exports.DependencyWalker = DependencyWalker;
//# sourceMappingURL=dependency-walker.js.map