Socket
Socket
Sign inDemoInstall

enhanced-resolve

Package Overview
Dependencies
Maintainers
1
Versions
130
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

enhanced-resolve - npm Package Compare versions

Comparing version 0.3.1 to 0.4.0

lib/cachedFsResolve.js

210

lib/resolve.js

@@ -6,37 +6,32 @@ /*

var path = require("path");
var fs = require("fs");
var createThrottledFunction = require("./createThrottledFunction");
var statCache = {}, readFileCache = {};
var statAsync = createThrottledFunction(fs.stat, 2000, Object.create(statCache));
var statSync = createThrottledFunction(function(pathname, callback) {
try { callback(null, fs.statSync(pathname)); } catch(e) { callback(e) }
}, 4000, statCache);
var readFileAsync = createThrottledFunction(fs.readFile, 2000, Object.create(readFileCache));
var readFileSync = createThrottledFunction(function(pathname, enc, callback) {
try { callback(null, fs.readFileSync(pathname, enc)); } catch(e) { callback(e) }
}, 4000, readFileCache);
var parse = require("./parse");
var stringify = require("./stringify");
var matchRegExpObject = require("./matchRegExpObject");
// http://nodejs.org/docs/v0.4.8/api/all.html#all_Together...
module.exports = function resolveFactory(config) {
function resolve(context, identifier, options, type, sync, callback) {
var statAsync = config.statAsync;
var statSync = config.statSync;
var readFileAsync = config.readFileAsync;
var readFileSync = config.readFileSync;
var parsePackage = config.parsePackage;
function resolve(context, resource, options, type, sync, callback) {
function finalResult(err, absoluteFilename) {
if(err) {
callback(new Error("Module \"" + identifier + "\" not found in context \"" +
callback(new Error("Module \"" + stringify({resource: resource}) + "\" not found in context \"" +
context + "\"\n " + err));
return;
}
callback(null, absoluteFilename);
resource.path = absoluteFilename;
callback(null, resource);
}
var identArray = split(identifier);
var contextArray = split(context);
while(options.alias[identArray[0]]) {
var old = identArray[0];
identArray[0] = options.alias[identArray[0]];
identArray = split(path.join.apply(path, identArray));
if(identArray[0] === old)
break;
}
if(identArray[0] === "." || identArray[0] === ".." || identArray[0] === "" || identArray[0].match(/^[A-Z]:$/i)) {
var pathname = identArray[0][0] === "." ? join(contextArray, identArray) : join(identArray, []);
applyAlias(resource, options.alias);
if(resource.module) {
loadInModuleDirectories(context, resource.path, options, type, sync, finalResult);
} else {
var pathname = resource.path[0] === "." ? join(split(context), split(resource.path)) : resource.path;
if(type === "context") {

@@ -49,6 +44,6 @@ (sync?statSync:statAsync)(pathname, function(err, stat) {

if(!stat.isDirectory()) {
finalResult(new Error("Context \"" + identifier + "\" in not a directory"));
finalResult(new Error("Context \"" + pathname + "\" in not a directory"));
return;
}
callback(null, pathname);
finalResult(null, pathname);
});

@@ -58,31 +53,61 @@ } else {

}
} else {
loadNodeModules(contextArray, identArray, options, type, sync, finalResult);
}
}
function applyAlias(resource, alias) {
while(resource.path && resource.module) {
var moduleName = resource.path, remaining = "";
var idx = moduleName.indexOf("/");
if(idx >= 0) {
remaining = moduleName.slice(idx);
moduleName = moduleName.slice(0, idx);
}
if(!alias[moduleName]) return;
resource.path = alias[moduleName] + remaining;
resource.module = parse.isModule(resource.path);
}
}
function doResolve(context, identifier, options, type, sync, callback) {
var identifiers = identifier.replace(/^!|!$/g, "").replace(/!!/g, "!").split(/!/g);
var resource = identifiers.pop();
if(identifier.indexOf("!") === -1) {
var request;
try {
request = parse(identifier);
} catch(e) { return callback(e); }
var resource = request.resource;
if(request.loaders === null && resource === null) {
// We want to resolve an empty identifier
return onResolvedBoth();
} else if(request.loaders !== null && request.loaders.length === 0 && resource === null) {
// We want to resolve "!" or "!!" or ...
return onResolvedBoth();
} else if(request.loaders === null && resource.path === null) {
// We want to resolve something like "?query"
return onResolvedBoth();
} else if(request.loaders === null && resource.path !== null) {
// We want to resolve something like "simple" or "./file"
request.loaders = [];
// We need the resource first to check if loaders apply.
// We have to do it serial.
resolve(context, resource, options, type, sync, function(err, resource) {
resolve(context, resource, options, type, sync, function(err) {
if(err) return callback(err);
for(var i = 0; i < options.loaders.length; i++) {
var line = options.loaders[i];
var test = line.test;
if(typeof test == "string") test = new RegExp(test);
if(test.test(resource)) {
Array.prototype.push.apply(identifiers, line.loader.split(/!/g));
if(matchRegExpObject(line, resource.path)) {
var loaders = parse(line.loader + "!").loaders;
Array.prototype.push.apply(request.loaders, loaders);
break;
}
}
if(identifiers.length == 0) return onResolvedBoth([], resource);
if(request.loaders.length == 0) return onResolvedBoth();
resolveLoaders(context, identifiers, options, sync, function(err, loaders) {
resolveLoaders(context, request.loaders, options, sync, function(err) {
if(err) return callback(err);
onResolvedBoth(loaders, resource);
onResolvedBoth();
});
});
} else if(resource === null || resource.path === null) {
resolveLoaders(context, request.loaders, options, sync, function(err) {
if(err) return callback(err);
if(count++) return onResolvedBoth();
});
} else {

@@ -92,24 +117,20 @@ // Loaders are specified. Do it parallel.

var count = 0;
var loaders, resource;
resolve(context, resource, options, type, sync, function(err, res) {
if(err) {
resolve(context, resource, options, type, sync, function(err) {
if(err && !fastExit) {
fastExit = true;
return callback(err);
}
resource = res;
if(count++) return onResolvedBoth(loaders, resource);
if(count++) return onResolvedBoth();
});
resolveLoaders(context, identifiers, options, sync, function(err, theLoaders) {
if(err) {
resolveLoaders(context, request.loaders, options, sync, function(err) {
if(err && !fastExit) {
fastExit = true;
return callback(err);
}
loaders = theLoaders;
if(count++) return onResolvedBoth(loaders, resource);
if(count++) return onResolvedBoth();
});
}
function onResolvedBoth(loaders, resource) {
loaders.push(resource);
var intermediateResult = loaders.join("!");
function onResolvedBoth() {
var intermediateResult = stringify(request);
var postprocessors = options.postprocess[type].slice(0);

@@ -129,6 +150,10 @@ postprocessors.push(function(result) {

function resolveLoaders(context, identifiers, options, sync, callback) {
function resolveLoaders(context, loaders, options, sync, callback) {
var count = loaders.length;
if(count == 0) return callback();
var errors = [];
var count = identifiers.length;
function endOne() {
function endOne(err) {
if(err) {
errors.push(err);
}
count--;

@@ -140,15 +165,7 @@ if(count === 0) {

}
callback(null, identifiers);
callback(null, loaders);
}
}
if(count == 0) return endOne(count++);
identifiers.forEach(function(ident, index) {
resolve(context, ident, options, "loader", sync, function(err, filename) {
if(err) {
errors.push(err);
} else {
identifiers[index] = filename;
}
endOne()
});
loaders.forEach(function(loader) {
resolve(context, loader, options, "loader", sync, endOne);
});

@@ -179,4 +196,4 @@ }

options.paths = [];
if(!options.modulesDirectorys)
options.modulesDirectorys = ["node_modules"];
if(!options.modulesDirectories)
options.modulesDirectories = ["node_modules"];
if(!options.alias)

@@ -213,3 +230,3 @@ options.alias = {};

*/
module.exports = function(context, identifier, options, callback) {
var resolveFunction = function resolveFunction(context, identifier, options, callback) {
if(!callback) {

@@ -222,3 +239,3 @@ callback = options;

}
module.exports.sync = function(context, identifier, options) {
resolveFunction.sync = function(context, identifier, options) {
if(!options) options = {};

@@ -230,5 +247,5 @@ options = setupDefaultOptions(options);

}
module.exports.setupDefaultOptions = setupDefaultOptions;
resolveFunction.setupDefaultOptions = setupDefaultOptions;
module.exports.context = function(context, identifier, options, callback) {
resolveFunction.context = function(context, identifier, options, callback) {
if(!callback) {

@@ -241,3 +258,3 @@ callback = options;

}
module.exports.context.sync = function(context, identifier, options) {
resolveFunction.context.sync = function(context, identifier, options) {
if(!options) options = {};

@@ -253,3 +270,3 @@ options = setupDefaultOptions(options);

*/
module.exports.loaders = function(context, identifier, options, callback) {
resolveFunction.loaders = function(context, identifier, options, callback) {
if(!callback) {

@@ -260,6 +277,20 @@ callback = options;

options = setupDefaultOptions(options);
var identifiers = identifier.replace(/^!|!$/g, "").replace(/!!/g, "!").split(/!/g);
if(identifiers.length == 1 && identifiers[0] == "") return callback(null, []);
return resolveLoaders(context, identifiers, options, false, callback);
try {
var loaders = parse(identifier + "!").loaders;
} catch(e) { return callback(e); }
return resolveLoaders(context, loaders, options, false, function(err, loaders) {
if(err) return callback(err);
return callback(null, loaders.map(stringify.part));
});
}
resolveFunction.loaders.sync = function(context, identifier, options) {
if(!options) options = {};
options = setupDefaultOptions(options);
var callback = createSyncCallback();
var loaders = parse(identifier + "!").loaders;
resolveLoaders(context, loaders, options, false, callback);
return callback.get().map(stringify.part);
}
resolveFunction.parse = parse;
resolveFunction.stringify = stringify;

@@ -321,3 +352,3 @@

try {
content = JSON.parse(content);
content = parsePackage(content);
} catch (jsonError) {

@@ -380,7 +411,8 @@ return callback(jsonError);

function loadNodeModules(context, identifier, options, type, sync, callback) {
function loadInModuleDirectories(context, identifier, options, type, sync, callback) {
var firstError = null;
var moduleName = identifier.shift();
var fileInModule = split(identifier);
var moduleName = fileInModule.shift();
var postfixes = type === "loader" ? options.loaderPostfixes : options.postfixes;
var paths = nodeModulesPaths(context, options);
var paths = modulesDirectoriesPaths(context, options);
(sync?iterateSync:iterateAsync)(options.paths, function(path, idx, next) {

@@ -408,3 +440,3 @@ usePath(path, next);

dirs.forEach(function(dir, idx) {
var pathname = join(split(dir), identifier);
var pathname = join(split(dir), fileInModule);
if(type === "context") {

@@ -445,6 +477,6 @@ (sync?statSync:statAsync)(pathname, function(err, stat) {

function nodeModulesPaths(context, options) {
var parts = context;
function modulesDirectoriesPaths(context, options) {
var parts = split(context);
var root = 0;
options.modulesDirectorys.forEach(function(dir) {
options.modulesDirectories.forEach(function(dir) {
var index = parts.indexOf(dir)-1;

@@ -456,6 +488,6 @@ if(index >= 0 && index < root)

for(var i = parts.length; i > root; i--) {
if(options.modulesDirectorys.indexOf(parts[i-1]) >= 0)
if(options.modulesDirectories.indexOf(parts[i-1]) >= 0)
continue;
var part = parts.slice(0, i);
options.modulesDirectorys.forEach(function(dir) {
options.modulesDirectories.forEach(function(dir) {
dirs.push(join(part, [dir]));

@@ -486,2 +518,6 @@ });

}
}
return resolveFunction;
}
{
"name": "enhanced-resolve",
"version": "0.3.1",
"version": "0.4.0",
"author": "Tobias Koppers @sokra",

@@ -21,3 +21,3 @@ "description": "Offers a async require.resolve function. It's highly configurable.",

},
"main": "lib/resolve.js",
"main": "lib/cachedFsResolve.js",
"homepage": "http://github.com/webpack/enhanced-resolve",

@@ -24,0 +24,0 @@ "scripts": {

@@ -9,11 +9,123 @@ # enhanced-resolve

## Request Format
relative: `./file`, `.././../folder/./file`
absolute: `/home/file`, `C:\folder\file`
module: `module`, `module/with/sub/file`
query: `resourceFile?query` (with resourceFile one of above, and query be any string)
loaders: `loader!resource`, `loader1!loader2!resource` (with loader and resource each one of above)
Example: `raw!./customLoader?evil,strict!C:\fail\loader?fail=big!../file.js?charset=utf-8`
## Methods
``` javascript
var resolve = require("enhanced-resolve");
resolve(string context, string identifier, object options, function callback(err, result))
resolve.sync(string context, string identifier, object options)
resolve.context(string context, string identifier, object options, function callback(err, result))
resolve.context.sync(string context, string identifier, object options)
// Resolve a normal request
resolve(context: String, identifier: String, options: Object, callback: (err: Error, result: String) => void) => void
resolve.sync(context: String, identifier: String, options: Object) => String
// Resolve a context request, which means the result should be a folder
resolve.context(context: String, identifier: String, options: Object, callback: (err: Error, result: String) => void) => void
resolve.context.sync(context: String, identifier: String, options: Object) => String
// Only resolve loaders, a array of resolved loaders is the result
resolve.loaders(context: String, identifier: String, options: Object, callback: (err: Error, result: String[]) => void) => void
resolve.loaders.sync(context: String, identifier: String, options: Object) => String[]
// parse a request
resolve.parse(identifier: String) => {loaders: Part[], resource: Part}
// stringify a parsed request
resolve.stringify(parsed: {loaders: Part[], resource: Part}) => String
// the type used for parse and stringify
type Part { path: String, query: String, module: Boolean }
// checks if a request part is a module
resolve.parse.isModule(identifierPart: String)
```
*It is used in [webpack](/webpack/webpack)*
## Options
``` javascript
{
paths: ["/my/absolute/dirname"],
// default: []
// search paths for modules
modulesDirectories: ["xyz_modules", "node_modules"],
// default: (defaults are NOT included if you define your own)
// ["node_modules"];
// directories to be searched for modules
alias: {
"old-module": "new-module",
"another-module": "new-module/more/stuff"
},
// replace a module
extensions: ["", ".www.js", ".js"],
// defaults: (defaults are NOT included if you define your own)
// ["", ".js"]
// postfixes for files to try
packageMains: ["abc", "main"]
// defaults: ["main"]
// lookup fields in package.json
loaderExtensions: [".loader.js", ".www-loader.js", "", ".js"],
// defaults: (defaults are NOT included if you define your own)
// [".node-loader.js", ".loader.js", "", ".js"]
// postfixes for loaders to try
loaderPostfixes: ["-loader", "-xyz", ""],
// defaults: (defaults are NOT included if you define your own)
// ["-node-loader", "-loader", ""]
// postfixes for loader modules to try
loaderPackageMains: ["myloader", "main"]
// defaults: ["loader", "main"]
// lookup fields for loaders in package.json
loaders: [{
// test, include and exclude can be undefined, RegExp, string or array of these
test: /\.generator\.js/,
include: "\\.js",
exclude: [
/\.no\.generator\.js/,
"\\.nono\\.generator\\.js"
}
loader: "val"
}],
// default: []
// automatically use loaders if resolved filename match RegExp
// and no loader is specified.
postprocess: {
normal: [function(filename, callback) {
// webpack will not find files including ".exclude."
if(/\.exclude\.[^\\\/]*$/.test(filename))
return callback(new Error("File is excluded"));
callback(null, filename);
}],
// defaults: []
// postprocess resolved filenames by all specified async functions
// a postprocessor must call the callback
// You can pass a filename instead of a function
// The filename is required and the exports are expected to be a function.
context: [],
// same as postprocess.normal but for contextes
}
}
```
*It is used i. e. in [webpack](https://github.com/webpack/webpack) and [Scripted](https://github.com/scripted-editor/scripted)*

@@ -1,2 +0,2 @@

var resolve = require("../lib/resolve");
var resolve = require("../");
var should = require("should");

@@ -3,0 +3,0 @@ var path = require("path");

@@ -7,9 +7,16 @@ /*

var path = require("path");
var resolve = require("../lib/resolve");
var resolve = require("../");
var options = {
loaders: [
{test: ".load1$", loader: "m2/b"},
{test: ".load2$", loader: "m1/a!m2/b"}
]
}
var fixtures = path.join(__dirname, "fixtures");
function testResolve(name, context, moduleName, result) {
describe(name, function() {
it("should resolve correctly", function(done) {
resolve(context, moduleName, {}, function(err, filename) {
it("should resolve async correctly", function(done) {
resolve(context, moduleName, options, function(err, filename) {
if(err) done(err);

@@ -21,2 +28,7 @@ should.exist(filename);

});
it("should resolve sync correctly", function() {
var filename = resolve.sync(context, moduleName, options);
should.exist(filename);
filename.should.equal(result);
});
});

@@ -26,3 +38,3 @@ }

describe(name, function() {
it("should resolve correctly", function(done) {
it("should resolve async correctly", function(done) {
resolve.context(context, moduleName, {}, function(err, filename) {

@@ -35,5 +47,13 @@ if(err) done(err);

});
it("should resolve sync correctly", function() {
var filename = resolve.context.sync(context, moduleName, {});
should.exist(filename)
filename.should.equal(result);
});
});
}
describe("resolve", function() {
testResolve("absolute path",
fixtures, path.join(fixtures, "main1.js"), path.join(fixtures, "main1.js"));
testResolve("file with .js",

@@ -58,2 +78,12 @@ fixtures, "./main1.js", path.join(fixtures, "main1.js"));

testResolve("file with query",
fixtures, "./main1.js?query", path.join(fixtures, "main1.js") + "?query");
testResolve("file in module with query",
fixtures, "m1/a?query", path.join(fixtures, "node_modules", "m1", "a.js") + "?query");
testResolve("absolute path with loader",
fixtures,
path.join(fixtures, "node_modules", "m1", "a.js") + "!!" + path.join(fixtures, "main1.js"),
path.join(fixtures, "node_modules", "m1", "a.js") + "!" + path.join(fixtures, "main1.js"));
testResolve("loader",

@@ -68,3 +98,26 @@ fixtures, "m1/a!./main1.js", path.join(fixtures, "node_modules", "m1", "a.js") + "!" + path.join(fixtures, "main1.js"));

path.join(fixtures, "main1.js"));
testResolve("multiple loaders with queries",
fixtures, "m1/a?q1!m1/b?q2!m2/b?q3!./main1.js?q4", path.join(fixtures, "node_modules", "m1", "a.js") + "?q1!" +
path.join(fixtures, "node_modules", "m1", "b.js") + "?q2!" +
path.join(fixtures, "node_modules", "m2-loader", "b.js") + "?q3!" +
path.join(fixtures, "main1.js") + "?q4");
testResolve("automatic one loader",
fixtures, "./file.load1",
path.join(fixtures, "node_modules", "m2-loader", "b.js") + "!" +
path.join(fixtures, "file.load1"));
testResolve("automatic two loader",
fixtures, "./file.load2",
path.join(fixtures, "node_modules", "m1", "a.js") + "!" +
path.join(fixtures, "node_modules", "m2-loader", "b.js") + "!" +
path.join(fixtures, "file.load2"));
testResolve("overwrite automatic loader",
fixtures, "m1/a!./file.load1",
path.join(fixtures, "node_modules", "m1", "a.js") + "!" +
path.join(fixtures, "file.load1"));
testResolve("disable automatic loader",
fixtures, "!./file.load1",
path.join(fixtures, "file.load1"));
testResolveContext("context for fixtures",

@@ -80,2 +133,7 @@ fixtures, "./", fixtures);

path.join(fixtures, ".."));
testResolveContext("context for fixtures with query",
fixtures, "./?query", fixtures + "?query");
testResolveContext("context with loader and query",
fixtures, "m1/a?q1!./?q2", path.join(fixtures, "node_modules", "m1", "a.js") + "?q1!" + fixtures + "?q2");
});

@@ -1,2 +0,2 @@

var resolve = require("../lib/resolve");
var resolve = require("../");
var should = require("should");

@@ -7,6 +7,6 @@ var path = require("path");

var pathsToIt = [
[__dirname, "../lib/resolve", "direct"],
[__dirname, "../lib/cachedFsResolve", "direct"],
[__dirname, "../", "as directory"],
[path.join(__dirname, "..", ".."), "./enhanced-resolve", "as module"],
[path.join(__dirname, "..", ".."), "./enhanced-resolve/lib/resolve", "in module"]
[path.join(__dirname, "..", ".."), "./enhanced-resolve/lib/cachedFsResolve", "in module"]
];

@@ -19,3 +19,3 @@ pathsToIt.forEach(function(pathToIt) {

filename.should.be.a("string");
filename.should.be.eql(path.join(__dirname, "..", "lib", "resolve.js"));
filename.should.be.eql(path.join(__dirname, "..", "lib", "cachedFsResolve.js"));
done();

@@ -28,3 +28,3 @@ });

filename.should.be.a("string");
filename.should.be.eql(path.join(__dirname, "..", "lib", "resolve.js"));
filename.should.be.eql(path.join(__dirname, "..", "lib", "cachedFsResolve.js"));
});

@@ -31,0 +31,0 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc