commonjs-walker
Advanced tools
Comparing version 2.0.0 to 3.0.0
309
index.js
@@ -11,2 +11,3 @@ 'use strict'; | ||
var util = require('util'); | ||
var resolve = require('resolve'); | ||
@@ -22,3 +23,12 @@ function walker (entry, options, callback) { | ||
walker.OPTIONS = { | ||
BROWSER: { | ||
detectCyclic: true, | ||
strictRequire: true, | ||
allowAbsolutePath: false, | ||
extensions: ['.js', '.json'] | ||
} | ||
}; | ||
function makeDefault (object, key, value) { | ||
@@ -42,7 +52,6 @@ object[key] = key in object | ||
makeDefault(options, 'allowAbsolutePath', true); | ||
makeDefault(options, 'extensions', EXTS_NODE); | ||
makeDefault(options, 'extFallbacks', EXTS_NODE); | ||
if (!this._checkExts()) { | ||
throw new Error('Invalid value of options.extFallbacks'); | ||
throw new Error('Invalid value of `options.extensions`'); | ||
} | ||
@@ -55,4 +64,5 @@ | ||
// Checks if the `options.extensions` is valid | ||
Walker.prototype._checkExts = function() { | ||
var exts = this.options.extFallbacks; | ||
var exts = this.options.extensions; | ||
@@ -72,9 +82,8 @@ if (!util.isArray(exts)) { | ||
var entry = this.entry; | ||
var called; | ||
function cb (err, tree) { | ||
function cb (err) { | ||
if (called) { | ||
return; | ||
} | ||
called = true; | ||
@@ -85,5 +94,4 @@ | ||
} | ||
// Returns the node of the entry point | ||
self.callback(null, self._getNode(entry), self.nodes); | ||
self.callback(null, self.nodes); | ||
} | ||
@@ -93,31 +101,17 @@ | ||
var q = async.queue(function (task, done) { | ||
// `path` will always be an absolute path. | ||
var path = task.path; | ||
function sub_node (err) { | ||
// Each node must be created before `._parseFileDependencies()` | ||
self._parseFileDependencies(path, function (err) { | ||
if (err) { | ||
cb(err); | ||
return cb(err); | ||
} | ||
done(); | ||
} | ||
if (/\.json$/i.test(path)) { | ||
return self._parseJsonFile(path, sub_node); | ||
} | ||
// Each node must be created before `._parseFile()` | ||
self._parseFile(path, function (err, data) { | ||
if (err) { | ||
cb(err); | ||
return done(); | ||
} | ||
self._dealDependencies(data, sub_node); | ||
}); | ||
}); | ||
q.drain = cb; | ||
// Creates entry node | ||
// `node` should be created before the task is running. | ||
this._createNode(entry); | ||
q.drain = cb; | ||
// Adds initial task | ||
@@ -127,3 +121,2 @@ q.push({ | ||
}); | ||
this.queue = q; | ||
@@ -133,2 +126,9 @@ }; | ||
// Actually, we do nothing | ||
Walker.prototype._parseNodeFile = function(path, callback) { | ||
this._parseJsonFile(path, callback); | ||
}; | ||
// @param {Path} path Absolute path | ||
Walker.prototype._parseJsonFile = function(path, callback) { | ||
@@ -141,5 +141,6 @@ var self = this; | ||
var node = this._getNode(path); | ||
var node = self._getNode(path); | ||
node.code = content; | ||
node.isJson = true; | ||
node.dependencies = {}; | ||
callback(null); | ||
}); | ||
@@ -149,85 +150,30 @@ }; | ||
Walker.prototype._parseFile = function(path, callback) { | ||
Walker.prototype._parseFileDependencies = function(path, callback) { | ||
var node = this._getNode(path); | ||
var options = this.options; | ||
var self = this; | ||
parser.parse(path, { | ||
noStrictRequire: this.options.noStrictRequire | ||
strictRequire: this.options.strictRequire | ||
}, callback); | ||
}; | ||
Walker.prototype._ensureExt = function(path, ext) { | ||
var regex = new RegExp('\\.' + ext + '$', 'i'); | ||
if (!regex.test(path)) { | ||
path += '.' + ext; | ||
} | ||
return path; | ||
}; | ||
Walker.prototype._dealDependencies = function(data, callback) { | ||
var dependencies = data.dependencies; | ||
var path = data.path; | ||
var node = this._getNode(path); | ||
node.unresolvedDependencies = dependencies; | ||
node.dependencies = []; | ||
node.code = data.code; | ||
var self = this; | ||
var options = this.options; | ||
async.each(dependencies, function (dep, done) { | ||
var origin = dep; | ||
if (dep.indexOf('/') === 0 && !options.allowAbsolutePath) { | ||
return done({ | ||
code: 'NOT_ALLOW_ABSOLUTE_PATH', | ||
message: 'Requiring an absolute path is not allowed', | ||
data: { | ||
dependency: dep, | ||
path: path | ||
} | ||
}); | ||
// @param {Object} data | ||
// - code | ||
// - path | ||
// - dependencies | ||
}, function (err, data) { | ||
if (err) { | ||
return callback(err); | ||
} | ||
node.code = data.code; | ||
node.dependencies = {}; | ||
// Absolutize | ||
if (self._isRelativePath(dep)) { | ||
dep = node_path.join(node_path.dirname(path), dep); | ||
} | ||
var resolved = self._resolveDependency(dep); | ||
if (!resolved) { | ||
return done({ | ||
code: 'MODULE_NOT_FOUND', | ||
message: 'Cannot find module \'' + origin + '\'', | ||
data: { | ||
path: dep, | ||
origin: origin | ||
} | ||
}); | ||
} | ||
var sub_node = self._getNode(resolved); | ||
if (sub_node) { | ||
// We only check the node if it meets the conditions below: | ||
// 1. already exists: all new nodes are innocent. | ||
// 2. but assigned as a dependency of anothor node | ||
// If one of the ancestor dependents of `node` is `current`, it forms a circle. | ||
var circular_trace; | ||
if ( | ||
options.detectCyclic | ||
// node -> sub_node | ||
&& (circular_trace = circular.trace(sub_node, node)) | ||
) { | ||
var dependencies = data.dependencies; | ||
async.each(dependencies, function (dep, done) { | ||
if (dep.indexOf('/') === 0 && !options.allowAbsolutePath) { | ||
return done({ | ||
code: 'CYCLIC_DEPENDENCY', | ||
message: 'Cyclic dependency found: \n' + self._printCyclic(circular_trace), | ||
code: 'NOT_ALLOW_ABSOLUTE_PATH', | ||
message: 'Requiring an absolute path "' + dep + '" is not allowed in "' + path + '"', | ||
data: { | ||
trace: circular_trace, | ||
path: resolved | ||
dependency: dep, | ||
path: path | ||
} | ||
@@ -237,73 +183,78 @@ }); | ||
self._addDependent(node, sub_node); | ||
if (!self._isRelativePath(dep)) { | ||
return self._dealDependency(dep, dep, node, done); | ||
} | ||
// If sub node is already exists, skip parsing. | ||
return done(null); | ||
} | ||
resolve(dep, { | ||
basedir: node_path.dirname(path), | ||
extensions: options.extensions | ||
}, function (err, real) { | ||
if (err) { | ||
return done({ | ||
code: 'MODULE_NOT_FOUND', | ||
message: err.message, | ||
stack: err.stack, | ||
data: { | ||
path: dep | ||
} | ||
}); | ||
} | ||
sub_node = self._createNode(resolved); | ||
self._addDependent(node, sub_node); | ||
self._dealDependency(dep, real, node, callback); | ||
}); | ||
}, callback); | ||
}); | ||
}; | ||
if (sub_node.isForeign) { | ||
// We do NOT parse foreign modules | ||
return done(null); | ||
} | ||
self.queue.push({ | ||
path: resolved | ||
}); | ||
done(null); | ||
}, callback); | ||
}; | ||
Walker.prototype._resolveDependency = function(dep) { | ||
// Foreign module with a top id | ||
if (!this._isAbsolutePath(dep)) { | ||
return dep; | ||
Walker.prototype._dealDependency = function(dep, real, node, callback) { | ||
node.dependencies[dep] = real; | ||
var sub_node = this._getNode(real); | ||
if (!sub_node) { | ||
sub_node = this._createNode(real); | ||
if (!sub_node.foreign) { | ||
// only if the node is newly created. | ||
this.queue.push({ | ||
path: real | ||
}); | ||
} | ||
// this._addDependent(node, sub_node); | ||
return callback(null); | ||
} | ||
var resolved = null; | ||
try { | ||
resolved = require.resolve(dep); | ||
} catch(e) {} | ||
// We only check the node if it meets the conditions below: | ||
// 1. already exists: all new nodes are innocent. | ||
// 2. but assigned as a dependency of anothor node | ||
// If one of the ancestor dependents of `node` is `current`, it forms a circle. | ||
var circular_trace; | ||
if ( | ||
this.options.detectCyclic | ||
resolved = this._cleanResolvedDependency(resolved); | ||
return resolved; | ||
}; | ||
// `require.resolve` will always fallback to | ||
// `.js`, then `.json`, and finally `.node`. | ||
// But we not always do that, so we need to clean the resolved path. | ||
Walker.prototype._cleanResolvedDependency = function(resolved) { | ||
var match = resolved.match(/\.[a-z]+$/i); | ||
// if no extension, the module must exist. | ||
if (!match) { | ||
return resolved; | ||
// node -> sub_node | ||
&& (circular_trace = circular.trace(sub_node, node, this.nodes)) | ||
) { | ||
return callback({ | ||
code: 'CYCLIC_DEPENDENCY', | ||
message: 'Cyclic dependency found: \n' + this._printCyclic(circular_trace), | ||
data: { | ||
trace: circular_trace, | ||
path: real | ||
} | ||
}); | ||
} | ||
var ext = match[0].toLowerCase(); | ||
if (~this.options.extFallbacks.indexOf(ext)) { | ||
return resolved; | ||
} | ||
// if `options.extFallbacks` does not contain `ext`, | ||
// we consider it not found. | ||
return null; | ||
// this._addDependent(node, sub_node); | ||
callback(null); | ||
}; | ||
Walker.prototype._addDependent = function(dependent, dependency) { | ||
if (!~dependency.dependents.indexOf(dependent)) { | ||
dependency.dependents.push(dependent); | ||
} | ||
// Walker.prototype._addDependent = function(dependent, dependency) { | ||
// // adds dependent | ||
// if (!~dependency.dependents.indexOf(dependent)) { | ||
// dependency.dependents.push(dependent); | ||
// } | ||
// }; | ||
dependent.dependencies.push(dependency); | ||
}; | ||
// Creates the node by id if not exists. | ||
@@ -319,16 +270,7 @@ // No fault tolerance for the sake of private method | ||
node = this.nodes[id] = { | ||
id: id, | ||
dependents: [] | ||
// version will be set later | ||
dependents: [], | ||
entry: id === this.entry, | ||
foreign: this._isForeign(id) | ||
}; | ||
if (id === this.entry) { | ||
node.isEntryPoint = true; | ||
} | ||
if (!this._isAbsolutePath(id)) { | ||
node.isForeign = true; | ||
} | ||
} | ||
return node; | ||
@@ -338,2 +280,7 @@ }; | ||
Walker.prototype._isForeign = function(path) { | ||
return !this._isAbsolutePath(path); | ||
}; | ||
Walker.prototype._isAbsolutePath = function(path) { | ||
@@ -344,7 +291,4 @@ return node_path.resolve(path) === path.replace(/[\/\\]+$/, ''); | ||
Walker.prototype._isRelativePath = function(dep) { | ||
// 'abc' -> true | ||
// './abc' -> false | ||
// '../abc' -> false | ||
return dep.indexOf('./') === 0 || dep.indexOf('../') === 0; | ||
Walker.prototype._isRelativePath = function(path) { | ||
return path.indexOf('./') === 0 || path.indexOf('../') === 0; | ||
}; | ||
@@ -365,3 +309,2 @@ | ||
}); | ||
list.pop(); | ||
@@ -371,7 +314,5 @@ | ||
++ index; | ||
return index === 1 || index === trace.length | ||
? '[1]' | ||
: index; | ||
}); | ||
@@ -378,0 +319,0 @@ |
@@ -19,3 +19,3 @@ 'use strict'; | ||
// - `Array` if has a circle | ||
circular.trace = function (from, to) { | ||
circular.trace = function (from, to, nodes) { | ||
var trace = [to]; | ||
@@ -27,7 +27,7 @@ | ||
return circular.lookBack(from, to, trace); | ||
return circular.lookBack(from, to, trace, nodes); | ||
}; | ||
circular.lookBack = function (from, to, trace) { | ||
circular.lookBack = function (from, to, trace, nodes) { | ||
trace.push(from); | ||
@@ -39,5 +39,9 @@ | ||
var dependencies = from.dependencies; | ||
var deps_array = dependencies | ||
? Object.keys(dependencies) | ||
: []; | ||
// if meets the end, just pop. | ||
if (!from.dependencies || from.dependencies.length === 0) { | ||
if (deps_array.length === 0) { | ||
trace.pop(); | ||
@@ -47,4 +51,6 @@ return null; | ||
var found = from.dependencies.some(function (new_from) { | ||
return circular.lookBack(new_from, to, trace); | ||
var found = deps_array.some(function (dep) { | ||
var dep_path = dependencies[dep]; | ||
var new_from = nodes[dep_path]; | ||
return circular.lookBack(new_from, to, trace, nodes); | ||
}); | ||
@@ -59,2 +65,2 @@ | ||
return trace; | ||
}; | ||
}; |
@@ -20,3 +20,3 @@ 'use strict'; | ||
return callback({ | ||
code: 'EPARSEJS', | ||
code: 'ERROR_PARSE_JS', | ||
message: 'Error parsing "' + path + '": ' + err.stack, | ||
@@ -31,3 +31,2 @@ data: { | ||
var dependencies = []; | ||
try { | ||
@@ -37,3 +36,3 @@ parser._parseDependencies(ast, dependencies, options); | ||
return callback({ | ||
code: 'EREQUIRE', | ||
code: 'WRONG_USAGE_REQUIRE', | ||
message: 'Error parsing dependencies: ' + e.message, | ||
@@ -56,3 +55,3 @@ data: { | ||
callback(null, { | ||
code: content, | ||
code: content, | ||
path: path, | ||
@@ -70,3 +69,3 @@ dependencies: dependencies | ||
return callback({ | ||
code: 'EREADFILE', | ||
code: 'ERROR_READ_FILE', | ||
message: 'Error reading module "' + path + '": ' + err.stack, | ||
@@ -121,3 +120,3 @@ data: { | ||
if (args.length === 0) { | ||
parser._throw(strict, loc_text + 'Method `require` accepts only one parameter.'); | ||
parser._throw(strict, loc_text + 'Method `require` accepts one and only one parameter.'); | ||
return; | ||
@@ -124,0 +123,0 @@ } |
{ | ||
"name": "commonjs-walker", | ||
"version": "2.0.0", | ||
"version": "3.0.0", | ||
"description": "Analyzer and tree walker for commonjs.", | ||
@@ -30,4 +30,5 @@ "main": "index.js", | ||
"async": "^0.8.0", | ||
"esprima": "^1.2.0" | ||
"esprima": "^1.2.0", | ||
"resolve": "^0.7.1" | ||
} | ||
} |
121
README.md
@@ -14,8 +14,9 @@ # commonjs-walker [![NPM version](https://badge.fury.io/js/commonjs-walker.png)](http://badge.fury.io/js/commonjs-walker) [![Build Status](https://travis-ci.org/kaelzhang/node-commonjs-walker.png?branch=master)](https://travis-ci.org/kaelzhang/node-commonjs-walker) | ||
- `require()` a directory. | ||
- if a module is not find, commonjs-walker will attempt to load the required filename with the added extension of `.js`, `.json`, and then `.node`, according to [File Modules](http://nodejs.org/api/modules.html#modules_file_modules) | ||
- If a module is not found, commonjs-walker will attempt to load the required filename with the added extension of `.js`, `.json`, and then `.node`, according to [File Modules](http://nodejs.org/api/modules.html#modules_file_modules) | ||
- You can define what extensions should commonjs-walker fallback to by [options.extensions](#optionsextensions), which will be very usefull for browser-side commonjs modules. | ||
## walker(entry, [options,] callback) | ||
## walker(entry, [options], callback) | ||
```js | ||
walker('/path/to/entry.js', options, function(err, tree, nodes){ | ||
walker('/path/to/entry.js', options, function(err, nodes){ | ||
// ... | ||
@@ -25,2 +26,8 @@ }); | ||
Walks down from a entry point, such as `package.main` of commonjs or any JavaScript file based on CommonJS, and tries to create a `walker.Module` instance of the top level. | ||
- entry `Path` the absolute path of the entry point. | ||
- nodes `Object` the hashmap of `<path>: <walker.Module>` | ||
If the file structure of your project is (actually it is a very extreme scenario): | ||
@@ -32,3 +39,3 @@ | ||
|-- a | ||
| |-- index.json | ||
|-- index.json | ||
``` | ||
@@ -52,54 +59,29 @@ | ||
```js | ||
walker('/path/to/index.js', function(err, tree, nodes){ | ||
console.log(tree); | ||
walker('/path/to/index.js', function(err, nodes){ | ||
console.log(nodes); | ||
}) | ||
}); | ||
``` | ||
Then, the `tree` object will be something like: | ||
Then, the `nodes` object will be something like: | ||
```js | ||
{ | ||
id: '/path/to/index.js', | ||
dependents: [], | ||
isEntryPoint: true, | ||
unresolvedDependencies: ['./a', './b'], | ||
dependencies: [ | ||
{ | ||
// use `require.resolve` to the the real path. | ||
id: '/path/to/a/index.json', | ||
dependents: [ | ||
tree // points to `index.js` | ||
], | ||
dependencies: [], | ||
unresolvedDependencies: [], | ||
code: <Buffer>, | ||
isJson: true | ||
}, | ||
{ | ||
id: 'b', | ||
isForeign: true, | ||
dependents: [tree] | ||
} | ||
], | ||
code: <Buffer> | ||
'/path/to/index.js': { | ||
entry: true, | ||
dependencies: { | ||
'./a': '/path/to/a/index.json', | ||
'b': 'b' | ||
}, | ||
code: <Buffer> | ||
}, | ||
'/path/to/a/index.json': { | ||
dependencies: {}, | ||
code: <Buffer> | ||
}, | ||
'b': { | ||
foreign: true | ||
} | ||
} | ||
``` | ||
The `nodes` object is the `path->node` hashmap. | ||
```js | ||
{ | ||
'/path/to/index.js': tree, | ||
'/path/to/a.js': tree.dependencies[0] | ||
} | ||
``` | ||
Walks down from a entry point, such as `package.main` of commonjs, and tries to create a `walker.Module` instance of the top level. | ||
- entry `Path` the absolute path of the entry point. | ||
- tree `walker.Module` tree of `walker.Module` | ||
- nodes `Object` the hashmap of `<path>: <walker.Module>` | ||
#### options | ||
@@ -112,15 +94,16 @@ | ||
detectCyclic | `Boolean` | true | whether should check cyclic dependencies | ||
strictRequire | `Boolean` | true | whether should check the usage of method `require()` | ||
strictRequire | `Boolean` | true | whether should check the usage of method `require()`. If true, the argument of `require()` must be an literal string. | ||
allowAbsolutePath | `Boolean` | true | whether should allow to require an absolute path. | ||
extFallbacks | `Array` | `['.js', '.json', '.node']` | see `options.extFallbacks` section | ||
extensions | `Array` | `['.js', '.json', '.node']` | see `options.extensions` section | ||
<!-- parseForeignModule | `Boolean` | true | will try to resolve foreign modules by `require.resolve()`. Set this option to false to handle foreign modules yourself. --> | ||
#### options.extFallbacks | ||
#### options.extensions | ||
type `Array` | ||
When we `require()` a `path`, if `path` is not found, nodejs will attempt to load the required filename with the added extension of `.js`, `.json`, and then `.node`. [ref](http://nodejs.org/api/modules.html#modules_file_modules) | ||
When we `require()` a `path`, if `path` is not found, nodejs will attempt to load the required filename with the added extension of `.js`, `.json`, and then `.node`. [Reference via](http://nodejs.org/api/modules.html#modules_file_modules) | ||
But for browser-side environment, most usually, we do not support extension `.node` which is why `options.extFallbacks`. | ||
But for browser-side environment, most usually, we do not support extension `.node` which is what `options.extensions` is for. | ||
Especially, only tree values are allowed below: | ||
Especially, only tree values below are allowed: | ||
@@ -131,2 +114,15 @@ - `['.js']` | ||
## walker.OPTIONS.BROWSER | ||
An usual preset of options for browsers, as | ||
```js | ||
{ | ||
detectCyclic: true, | ||
strictRequire: true, | ||
allowAbsolutePath: false, | ||
extensions: ['.js', '.json'] | ||
} | ||
``` | ||
## Struct: walker.Module | ||
@@ -140,8 +136,7 @@ | ||
-------- | ---- | ----------- | ||
id | `String` | the id of the module | ||
isEntryPoint | `Boolean` | whether the current module is the entry point | ||
dependents | `Array.<walker.module>` | the dependent modules. If there's no dependents, it will be `[]` | ||
isForeign | `Boolean` | whether the current module is from a foreign package. | ||
entry | `Boolean` | whether the current module is the entry point | ||
foreign | `Boolean` | whether the current module is from a foreign package. | ||
<!-- dependents | `Array.<String>` | the dependent modules. If there's no dependents, it will be `[]` --> | ||
#### `isJSON` or normal | ||
#### If `foreign` is `false` | ||
@@ -151,10 +146,4 @@ Property | Type | Description | ||
code | `Buffer` | the file content of the current module. | ||
dependencies | `Object.<id: path>` | `id` is the argument of `require(id)`. `path` is the resolved absolute path by `id`. If the module has no dependencies, it will be `{}` | ||
#### For both `isForeign` and `isJSON` are `false` | ||
Property | Type | Description | ||
-------- | ---- | ----------- | ||
dependencies | `Array.<walker.Module>` | the dependencies of the current module. If the module has no dependencies, it will be `[]` | ||
unresolvedDependencies | `Array.<String>` | the array contains the items `require()`d by the module. | ||
## Class: walker.Error | ||
@@ -167,3 +156,2 @@ | ||
## Error codes | ||
@@ -177,2 +165,1 @@ | ||
@@ -10,3 +10,7 @@ 'use strict'; | ||
var a = {}; | ||
var result = circular.trace(a, a); | ||
var nodes = { | ||
'/a': a | ||
}; | ||
var result = circular.trace(a, a, nodes); | ||
expect(result).to.equal(null); | ||
@@ -18,4 +22,8 @@ }); | ||
var b = {} | ||
var nodes = { | ||
'/a': a, | ||
'/b': b | ||
}; | ||
var result = circular.trace(a, b); | ||
var result = circular.trace(a, b, nodes); | ||
expect(result).to.equal(null); | ||
@@ -27,14 +35,15 @@ }); | ||
var b = { | ||
dependents: [ | ||
{ | ||
dependents: [ | ||
{} | ||
] | ||
}, | ||
{} | ||
] | ||
dependencies: { | ||
'./c': '/c' | ||
} | ||
}; | ||
var nodes = { | ||
'/a': a, | ||
'/b': b, | ||
'/c': { | ||
dependencies: {} | ||
} | ||
}; | ||
var result = circular.trace(a, b); | ||
var result = circular.trace(a, b, nodes); | ||
expect(result).to.equal(null); | ||
@@ -49,21 +58,28 @@ }); | ||
name: 'b', | ||
dependencies: [ | ||
{ | ||
name: 'c', | ||
dependencies: [ | ||
{ | ||
name: 'd' | ||
}, | ||
dependencies: { | ||
'./c': '/c', | ||
'./e': '/e' | ||
} | ||
}; | ||
var c = { | ||
name: 'c', | ||
dependencies: { | ||
'./d': '/d', | ||
'./a': '/a' | ||
} | ||
}; | ||
a | ||
] | ||
}, | ||
{ | ||
name: 'e' | ||
} | ||
] | ||
var nodes = { | ||
'/a': a, | ||
'/b': b, | ||
'/c': c, | ||
'/d': { | ||
name: 'd' | ||
}, | ||
'/e': { | ||
name: 'e' | ||
} | ||
}; | ||
var result = circular.trace(b, a).map(function (item) { | ||
var result = circular.trace(b, a, nodes).map(function (item) { | ||
return item.name; | ||
@@ -70,0 +86,0 @@ }); |
@@ -14,6 +14,6 @@ 'use strict'; | ||
file: 'simplest.js', | ||
expect: function (err, tree) { | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).to.equal(null); | ||
expect(tree.code.toString()).to.equal("require('abc');"); | ||
expect(tree.dependencies[0].isForeign).to.equal(true); | ||
expect(entry.code.toString()).to.equal("require('abc');"); | ||
expect(nodes['abc'].foreign).to.equal(true); | ||
} | ||
@@ -24,7 +24,6 @@ }, | ||
file: 'one-dep/index.js', | ||
expect: function (err, tree) { | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).to.equal(null); | ||
var dep = tree.dependencies[0]; | ||
expect(dep.id).to.equal( node_path.join(root, 'one-dep', 'a.js') ); | ||
var dep = entry.dependencies['./a']; | ||
expect(dep).to.equal( node_path.join(root, 'one-dep', 'a.js') ); | ||
} | ||
@@ -35,3 +34,3 @@ }, | ||
file: 'circular/index.js', | ||
expect: function (err, tree) { | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).not.to.equal(null); | ||
@@ -47,6 +46,145 @@ expect(err.code).to.equal('CYCLIC_DEPENDENCY'); | ||
file: 'circular/index.js', | ||
expect: function (err, tree) { | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).to.equal(null); | ||
} | ||
} | ||
}, | ||
{ | ||
desc: 'module not found', | ||
options: { | ||
}, | ||
file: 'not-found/one.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err.code).to.equal('MODULE_NOT_FOUND'); | ||
} | ||
}, | ||
{ | ||
desc: 'module not found: fallback, still not found', | ||
options: {}, | ||
file: 'not-found/two.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err.code).to.equal('MODULE_NOT_FOUND'); | ||
} | ||
}, | ||
{ | ||
desc: 'module not found: limited by exts', | ||
options: { | ||
extensions: ['.js', '.json'] | ||
}, | ||
file: 'not-found/three.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err.code).to.equal('MODULE_NOT_FOUND'); | ||
} | ||
}, | ||
{ | ||
desc: 'if not limited, could be found', | ||
options: { | ||
}, | ||
file: 'not-found/three.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).to.equal(null); | ||
expect(!!entry).to.equal(true); | ||
} | ||
}, | ||
{ | ||
desc: 'error require', | ||
file: 'error-require/a.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).to.not.equal(null); | ||
expect(err.code).to.equal('WRONG_USAGE_REQUIRE'); | ||
} | ||
}, | ||
{ | ||
desc: 'modules: no-fallback', | ||
file: 'fallback/no-fallback.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).to.equal(null); | ||
var dep = './cases/no-fallback'; | ||
var real = node_path.join( node_path.dirname(path), dep ); | ||
expect(entry.dependencies[dep]).to.equal(real); | ||
} | ||
}, | ||
{ | ||
desc: 'modules: no-fallback not found', | ||
file: 'fallback/no-fallback-not-found.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err.code).to.equal('MODULE_NOT_FOUND'); | ||
} | ||
}, | ||
{ | ||
desc: 'modules: fallback', | ||
file: 'fallback/fallback.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).to.equal(null); | ||
var dep = './cases/fallback'; | ||
var real = node_path.join( node_path.dirname(path), dep ) + '.js'; | ||
expect(entry.dependencies[dep]).to.equal(real); | ||
} | ||
}, | ||
{ | ||
desc: 'modules: exact, no fallback', | ||
file: 'fallback/fallback-exact.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).to.equal(null); | ||
var dep = './cases/fallback.js'; | ||
var real = node_path.join( node_path.dirname(path), dep ); | ||
expect(entry.dependencies[dep]).to.equal(real); | ||
} | ||
}, | ||
{ | ||
desc: 'modules: falback to json', | ||
file: 'fallback/fallback-json.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).to.equal(null); | ||
var dep = './cases/fallback-json'; | ||
var real = node_path.join( node_path.dirname(path), dep ) + '.json'; | ||
expect(entry.dependencies[dep]).to.equal(real); | ||
} | ||
}, | ||
{ | ||
desc: 'modules: falback to node', | ||
options: { | ||
}, | ||
file: 'fallback/fallback-node.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).to.equal(null); | ||
var dep = './cases/fallback-node'; | ||
var real = node_path.join( node_path.dirname(path), dep ) + '.node'; | ||
expect(entry.dependencies[dep]).to.equal(real); | ||
} | ||
}, | ||
{ | ||
desc: 'modules: falback to node, without `".node"` extension', | ||
options: { | ||
extensions: ['.js', '.json'] | ||
}, | ||
file: 'fallback/fallback-node.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err.code).to.equal('MODULE_NOT_FOUND'); | ||
} | ||
}, | ||
{ | ||
desc: 'directories: dir without ending slash', | ||
options: { | ||
}, | ||
file: 'fallback/dir.js', | ||
expect: function (err, path, nodes, entry) { console.log(err) | ||
expect(err).to.equal(null); | ||
var dep = './cases/dir'; | ||
var real = node_path.join( node_path.dirname(path), dep ) + '/index.js'; | ||
expect(entry.dependencies[dep]).to.equal(real); | ||
} | ||
}, | ||
{ | ||
desc: 'directories: dir with ending slash', | ||
options: { | ||
}, | ||
file: 'fallback/dir-slash.js', | ||
expect: function (err, path, nodes, entry) { | ||
expect(err).to.equal(null); | ||
var dep = './cases/dir/'; | ||
var real = node_path.join( node_path.dirname(path), dep ) + 'index.js'; | ||
expect(entry.dependencies[dep]).to.equal(real); | ||
} | ||
}, | ||
]; | ||
@@ -57,18 +195,41 @@ | ||
cases.forEach(function (c) { | ||
it(c.desc, function(done){ | ||
var file = node_path.join(root, c.file); | ||
walker(file, c.options || {}, function (err, tree) { | ||
done(); | ||
c.expect(err, tree); | ||
var i = c.only | ||
? it.only | ||
: it; | ||
function run (noOptions) { | ||
var desc = c.desc; | ||
var options = c.options || {}; | ||
if (noOptions) { | ||
if (Object.keys(options).length !== 0) { | ||
return; | ||
} | ||
desc += ': no argument `options`'; | ||
} | ||
i(desc, function(done){ | ||
var file = node_path.join(root, c.file); | ||
var callback = function (err, nodes) { | ||
done(); | ||
var entry; | ||
if (!err && nodes) { | ||
entry = nodes[file] | ||
} | ||
c.expect(err, file, nodes, entry); | ||
}; | ||
if (noOptions) { | ||
walker(file, callback); | ||
} else { | ||
walker(file, options, callback); | ||
} | ||
}); | ||
}); | ||
}); | ||
} | ||
it('let `options` be optional', function(done){ | ||
var file = node_path.join(root, cases[0].file); | ||
walker(file,function(err, tree){ | ||
done(); | ||
cases[0].expect(err,tree); | ||
}); | ||
run(); | ||
run(true); | ||
}); | ||
}); |
@@ -16,4 +16,4 @@ 'use strict'; | ||
deps: ['../abc', 'abc', './abc'] | ||
}, { | ||
}, | ||
{ | ||
desc: 'no arguments, strict', | ||
@@ -25,4 +25,4 @@ file: 'no-arg.js', | ||
error: true | ||
}, { | ||
}, | ||
{ | ||
desc: 'no arguments, no strict', | ||
@@ -35,3 +35,4 @@ file: 'no-arg.js', | ||
}, { | ||
}, | ||
{ | ||
desc: 'more than one arguments, strict', | ||
@@ -44,3 +45,4 @@ file: 'more-than-one-arg.js', | ||
}, { | ||
}, | ||
{ | ||
desc: 'more than one arguments, no strict', | ||
@@ -47,0 +49,0 @@ file: 'more-than-one-arg.js', |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Misc. License Issues
License(Experimental) A package's licensing information has fine-grained problems.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
27830
41
774
2
3
1
156
+ Addedresolve@^0.7.1
+ Addedresolve@0.7.4(transitive)