[Pkg-javascript-commits] [node-resolve] 01/10: New upstream version 1.4.0

Julien Puydt julien.puydt at laposte.net
Fri Sep 15 15:19:42 UTC 2017


This is an automated email from the git hooks/post-receive script.

jpuydt-guest pushed a commit to branch master
in repository node-resolve.

commit 68dce8d4a97fd679c5214be9dc2e16658a7b7cf3
Author: Julien Puydt <julien.puydt at laposte.net>
Date:   Wed Aug 16 19:35:39 2017 +0200

    New upstream version 1.4.0
---
 .eslintignore                                     |   1 +
 .eslintrc                                         |  30 ++
 .gitignore                                        |   7 +
 .npmrc                                            |   1 +
 .travis.yml                                       | 185 +++++++++++-
 appveyor.yml                                      |  44 +++
 example/async.js                                  |   4 +-
 index.js                                          |  11 +-
 lib/async.js                                      | 203 +++++++------
 lib/caller.js                                     |   2 +-
 lib/core.js                                       |  26 +-
 lib/core.json                                     |  85 +++---
 lib/node-modules-paths.js                         |  55 ++--
 lib/sync.js                                       |  64 ++--
 package.json                                      |  19 +-
 readme.markdown                                   |  18 +-
 test/core.js                                      |  29 +-
 test/dotdot.js                                    |  28 +-
 test/dotdot/index.js                              |   2 +-
 test/faulty_basedir.js                            |   8 +-
 test/filter.js                                    |   9 +-
 test/filter_sync.js                               |  11 +-
 test/mock.js                                      | 175 +++++------
 test/mock_sync.js                                 |  67 +++--
 test/module_dir.js                                |  36 +--
 test/module_dir/xmodules/aaa/index.js             |   2 +-
 test/module_dir/ymodules/aaa/index.js             |   2 +-
 test/module_dir/zmodules/bbb/main.js              |   2 +-
 test/node-modules-paths.js                        |  93 ++++++
 test/node_path.js                                 |  37 +--
 test/node_path/x/aaa/index.js                     |   2 +-
 test/node_path/x/ccc/index.js                     |   2 +-
 test/node_path/y/bbb/index.js                     |   2 +-
 test/node_path/y/ccc/index.js                     |   2 +-
 test/pathfilter.js                                |  61 ++--
 test/precedence.js                                |  10 +-
 test/precedence/aaa.js                            |   2 +-
 test/precedence/aaa/index.js                      |   2 +-
 test/precedence/aaa/main.js                       |   2 +-
 test/precedence/bbb.js                            |   2 +-
 test/resolver.js                                  | 338 +++++++++++++---------
 test/resolver/baz/package.json                    |   2 +-
 test/resolver/dot_main/index.js                   |   1 +
 test/resolver/dot_main/package.json               |   3 +
 test/resolver/dot_slash_main/index.js             |   1 +
 test/resolver/dot_slash_main/package.json         |   3 +
 test/resolver/incorrect_main/package.json         |   2 +-
 test/resolver/same_names/foo.js                   |   1 +
 test/resolver/same_names/foo/index.js             |   1 +
 test/resolver/symlinked/.gitignore                |   1 +
 test/resolver/symlinked/_/.gitignore              |   1 +
 test/resolver/symlinked/_/node_modules/foo.js     |   0
 test/resolver/symlinked/_/symlink_target/.gitkeep |   0
 test/resolver/without_basedir/main.js             |   9 +-
 test/resolver_sync.js                             | 255 ++++++++++------
 test/subdirs.js                                   |   2 +-
 test/symlinks.js                                  |  54 ++++
 57 files changed, 1350 insertions(+), 667 deletions(-)

diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..3c3629e
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1 @@
+node_modules
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..9db19a4
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,30 @@
+{
+    "extends": "@ljharb",
+    "root": true,
+    "rules": {
+        "array-bracket-newline": 0,
+        "array-element-newline": 0,
+        "indent": [2, 4],
+        "strict": 0,
+        "complexity": 0,
+        "consistent-return": 0,
+        "curly": 0,
+        "dot-notation": [2, { "allowKeywords": true }],
+        "func-name-matching": 0,
+        "func-style": 0,
+        "global-require": 0,
+        "id-length": [2, { "min": 1, "max": 30 }],
+        "max-nested-callbacks": 0,
+        "max-params": 0,
+        "max-statements-per-line": [2, { "max": 2 }],
+        "max-statements": 0,
+        "no-magic-numbers": 0,
+        "no-console": 0,
+        "no-shadow": 0,
+        "no-unused-vars": [2, { "vars": "all", "args": "none" }],
+        "no-use-before-define": 0,
+        "object-curly-newline": 0,
+        "operator-linebreak": [2, "before"],
+        "sort-keys": 0,
+    }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f833451
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+# gitignore
+node_modules
+
+# Only apps should have lockfiles
+npm-shrinkwrap.json
+package-lock.json
+yarn.lock
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..43c97e7
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+package-lock=false
diff --git a/.travis.yml b/.travis.yml
index 895dbd3..25709b3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,4 +1,185 @@
 language: node_js
+os:
+ - linux
 node_js:
-  - 0.6
-  - 0.8
+  - "8.2"
+  - "7.10"
+  - "6.11"
+  - "5.12"
+  - "4.8"
+  - "iojs-v3.3"
+  - "iojs-v2.5"
+  - "iojs-v1.8"
+  - "0.12"
+  - "0.10"
+  - "0.8"
+  - "0.6"
+before_install:
+  - 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ]; then npm install -g npm at 1.3 ; elif [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then case "$(npm --version)" in 1.*) npm install -g npm at 1.4.28 ;; 2.*) npm install -g npm at 2 ;; esac ; fi'
+  - 'if [ "${TRAVIS_NODE_VERSION}" != "0.6" ] && [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then if [ "${TRAVIS_NODE_VERSION%${TRAVIS_NODE_VERSION#[0-9]}}" = "0" ] || [ "${TRAVIS_NODE_VERSION:0:4}" = "iojs" ]; then npm install -g npm at 4.5 ; else npm install -g npm; fi; fi'
+install:
+  - 'if [ "${TRAVIS_NODE_VERSION}" = "0.6" ]; then (nvm install 0.8 && npm install -g npm at 1.3 && npm install -g npm at 1.4.28 && npm install -g npm at 2 && npm install); else npm install; fi;'
+script:
+  - 'if [ -n "${PRETEST-}" ]; then npm run pretest ; fi'
+  - 'if [ -n "${POSTTEST-}" ]; then npm run posttest ; fi'
+  - 'if [ -n "${COVERAGE-}" ]; then npm run coverage ; fi'
+  - 'if [ -n "${TEST-}" ]; then npm run tests-only ; fi'
+sudo: false
+env:
+  - TEST=true
+matrix:
+  fast_finish: true
+  include:
+    - node_js: "node"
+      env: PRETEST=true
+    - node_js: "8.1"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "8.0"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "7.9"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "7.8"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "7.7"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "7.6"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "7.5"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "7.4"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "7.3"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "7.2"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "7.1"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "7.0"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "6.10"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "6.9"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "6.8"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "6.7"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "6.6"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "6.5"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "6.4"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "6.3"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "6.2"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "6.1"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "6.0"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.11"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.10"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.9"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.8"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.7"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.6"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.5"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.4"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.3"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.2"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.1"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "5.0"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "4.7"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "4.6"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "4.5"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "4.4"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "4.3"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "4.2"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "4.1"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "4.0"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v3.2"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v3.1"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v3.0"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v2.4"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v2.3"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v2.2"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v2.1"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v2.0"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v1.7"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v1.6"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v1.5"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v1.4"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v1.3"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v1.2"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v1.1"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "iojs-v1.0"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "0.11"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "0.9"
+      env: TEST=true ALLOW_FAILURE=true
+    - node_js: "0.4"
+      env: TEST=true ALLOW_FAILURE=true
+    ##- node_js: "7"
+      #env: TEST=true
+      #os: osx
+    #- node_js: "6"
+      #env: TEST=true
+      #os: osx
+    #- node_js: "5"
+      #env: TEST=true
+      #os: osx
+    #- node_js: "4"
+      #env: TEST=true
+      #os: osx
+    #- node_js: "iojs"
+      #env: TEST=true
+      #os: osx
+    #- node_js: "0.12"
+      #env: TEST=true
+      #os: osx
+    #- node_js: "0.10"
+      #env: TEST=true
+      #os: osx
+    #- node_js: "0.8"
+      #env: TEST=true
+      #os: osx
+  allow_failures:
+    - os: osx
+    - env: TEST=true ALLOW_FAILURE=true
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..f54a1b6
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,44 @@
+version: 1.0.{build}
+skip_branch_with_pr: true
+build: off
+
+environment:
+  matrix:
+    - nodejs_version: "7"
+    - nodejs_version: "6"
+    - nodejs_version: "5"
+    - nodejs_version: "4"
+    - nodejs_version: "3"
+    - nodejs_version: "2"
+    - nodejs_version: "1"
+    - nodejs_version: "0.12"
+    - nodejs_version: "0.10"
+    - nodejs_version: "0.8"
+    - nodejs_version: "0.6"
+matrix:
+  # fast_finish: true
+  allow_failures:
+    - nodejs_version: "0.6"
+
+platform:
+  - x86
+  - x64
+
+# Install scripts. (runs after repo cloning)
+install:
+ # Get the latest stable version of Node.js or io.js
+ - ps: Install-Product node $env:nodejs_version $env:platform
+ - IF %nodejs_version% EQU 0.6 npm -g install npm at 1.3
+ - IF %nodejs_version% EQU 0.8 npm -g install npm at 2
+ - set PATH=%APPDATA%\npm;%PATH%
+ #- IF %nodejs_version% NEQ 0.6 AND %nodejs_version% NEQ 0.8 npm -g install npm
+ # install modules
+ - npm install
+
+# Post-install test scripts.
+test_script:
+ # Output useful info for debugging.
+ - node --version
+ - npm --version
+ # run tests
+ - npm run tests-only
diff --git a/example/async.js b/example/async.js
index 6624ff7..20e65dc 100644
--- a/example/async.js
+++ b/example/async.js
@@ -1,5 +1,5 @@
 var resolve = require('../');
 resolve('tap', { basedir: __dirname }, function (err, res) {
-    if (err) console.error(err)
-    else console.log(res)
+    if (err) console.error(err);
+    else console.log(res);
 });
diff --git a/index.js b/index.js
index 51f194b..eb6ba89 100644
--- a/index.js
+++ b/index.js
@@ -1,5 +1,8 @@
 var core = require('./lib/core');
-exports = module.exports = require('./lib/async');
-exports.core = core;
-exports.isCore = function (x) { return core[x] };
-exports.sync = require('./lib/sync');
+var async = require('./lib/async');
+async.core = core;
+async.isCore = function isCore(x) { return core[x]; };
+async.sync = require('./lib/sync');
+
+exports = async;
+module.exports = async;
diff --git a/lib/async.js b/lib/async.js
index 0f0eeca..ef1bde7 100644
--- a/lib/async.js
+++ b/lib/async.js
@@ -3,78 +3,90 @@ var fs = require('fs');
 var path = require('path');
 var caller = require('./caller.js');
 var nodeModulesPaths = require('./node-modules-paths.js');
-var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\//;
 
-module.exports = function resolve (x, opts, cb) {
+module.exports = function resolve(x, options, callback) {
+    var cb = callback;
+    var opts = options || {};
     if (typeof opts === 'function') {
         cb = opts;
         opts = {};
     }
-    if (!opts) opts = {};
     if (typeof x !== 'string') {
+        var err = new TypeError('Path must be a string.');
         return process.nextTick(function () {
-            cb(new Error('path must be a string'));
+            cb(err);
         });
     }
-    
+
     var isFile = opts.isFile || function (file, cb) {
         fs.stat(file, function (err, stat) {
-            if (err && err.code === 'ENOENT') cb(null, false)
-            else if (err) cb(err)
-            else cb(null, stat.isFile() || stat.isFIFO())
+            if (!err) {
+                return cb(null, stat.isFile() || stat.isFIFO());
+            }
+            if (err.code === 'ENOENT' || err.code === 'ENOTDIR') return cb(null, false);
+            return cb(err);
         });
     };
     var readFile = opts.readFile || fs.readFile;
-    
-    var extensions = opts.extensions || [ '.js' ];
+
+    var extensions = opts.extensions || ['.js'];
     var y = opts.basedir || path.dirname(caller());
-    
+
     opts.paths = opts.paths || [];
-    
-    if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[\\\/])/.test(x)) {
+
+    if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/.test(x)) {
         var res = path.resolve(y, x);
-        if (x === '..') res += '/';
+        if (x === '..' || x.slice(-1) === '/') res += '/';
         if (/\/$/.test(x) && res === y) {
             loadAsDirectory(res, opts.package, onfile);
-        }
-        else loadAsFile(res, opts.package, onfile);
-    }
-    else loadNodeModules(x, y, function (err, n, pkg) {
-        if (err) cb(err)
-        else if (n) cb(null, n, pkg)
+        } else loadAsFile(res, opts.package, onfile);
+    } else loadNodeModules(x, y, function (err, n, pkg) {
+        if (err) cb(err);
+        else if (n) cb(null, n, pkg);
         else if (core[x]) return cb(null, x);
-        else cb(new Error("Cannot find module '" + x + "' from '" + y + "'"))
+        else {
+            var moduleError = new Error("Cannot find module '" + x + "' from '" + y + "'");
+            moduleError.code = 'MODULE_NOT_FOUND';
+            cb(moduleError);
+        }
     });
-    
-    function onfile (err, m, pkg) {
-        if (err) cb(err)
-        else if (m) cb(null, m, pkg)
+
+    function onfile(err, m, pkg) {
+        if (err) cb(err);
+        else if (m) cb(null, m, pkg);
         else loadAsDirectory(res, function (err, d, pkg) {
-            if (err) cb(err)
-            else if (d) cb(null, d, pkg)
-            else cb(new Error("Cannot find module '" + x + "' from '" + y + "'"))
-        })
+            if (err) cb(err);
+            else if (d) cb(null, d, pkg);
+            else {
+                var moduleError = new Error("Cannot find module '" + x + "' from '" + y + "'");
+                moduleError.code = 'MODULE_NOT_FOUND';
+                cb(moduleError);
+            }
+        });
     }
-    
-    function loadAsFile (x, pkg, cb) {
-        if (typeof pkg === 'function') {
-            cb = pkg;
-            pkg = undefined;
+
+    function loadAsFile(x, thePackage, callback) {
+        var loadAsFilePackage = thePackage;
+        var cb = callback;
+        if (typeof loadAsFilePackage === 'function') {
+            cb = loadAsFilePackage;
+            loadAsFilePackage = undefined;
         }
-        
+
         var exts = [''].concat(extensions);
-        load(exts, x, pkg)
-		
-		function load (exts, x, pkg) {
-            if (exts.length === 0) return cb(null, undefined, pkg);
+        load(exts, x, loadAsFilePackage);
+
+        function load(exts, x, loadPackage) {
+            if (exts.length === 0) return cb(null, undefined, loadPackage);
             var file = x + exts[0];
-            
-            if (pkg) onpkg(null, pkg)
+
+            var pkg = loadPackage;
+            if (pkg) onpkg(null, pkg);
             else loadpkg(path.dirname(file), onpkg);
-            
-            function onpkg (err, pkg_, dir) {
+
+            function onpkg(err, pkg_, dir) {
                 pkg = pkg_;
-                if (err) return cb(err)
+                if (err) return cb(err);
                 if (dir && pkg && opts.pathFilter) {
                     var rfile = path.relative(dir, file);
                     var rel = rfile.slice(0, rfile.length - exts[0].length);
@@ -87,33 +99,30 @@ module.exports = function resolve (x, opts, cb) {
                 }
                 isFile(file, onex);
             }
-            function onex (err, ex) {
-                if (err) cb(err)
-                else if (!ex) load(exts.slice(1), x, pkg)
-                else cb(null, file, pkg)
+            function onex(err, ex) {
+                if (err) return cb(err);
+                if (ex) return cb(null, file, pkg);
+                load(exts.slice(1), x, pkg);
             }
         }
     }
-    
-    function loadpkg (dir, cb) {
+
+    function loadpkg(dir, cb) {
         if (dir === '' || dir === '/') return cb(null);
-        if (process.platform === 'win32' && /^\w:[\\\/]*$/.test(dir)) {
+        if (process.platform === 'win32' && (/^\w:[/\\]*$/).test(dir)) {
             return cb(null);
         }
-        if (/[\\\/]node_modules[\\\/]*$/.test(dir)) return cb(null);
-        
+        if (/[/\\]node_modules[/\\]*$/.test(dir)) return cb(null);
+
         var pkgfile = path.join(dir, 'package.json');
         isFile(pkgfile, function (err, ex) {
             // on err, ex is false
-            if (!ex) return loadpkg(
-                path.dirname(dir), cb
-            );
-            
+            if (!ex) return loadpkg(path.dirname(dir), cb);
+
             readFile(pkgfile, function (err, body) {
                 if (err) cb(err);
-                try { var pkg = JSON.parse(body) }
-                catch (err) {}
-                
+                try { var pkg = JSON.parse(body); } catch (jsonErr) {}
+
                 if (pkg && opts.packageFilter) {
                     pkg = opts.packageFilter(pkg, pkgfile);
                 }
@@ -121,72 +130,74 @@ module.exports = function resolve (x, opts, cb) {
             });
         });
     }
-    
-    function loadAsDirectory (x, fpkg, cb) {
+
+    function loadAsDirectory(x, loadAsDirectoryPackage, callback) {
+        var cb = callback;
+        var fpkg = loadAsDirectoryPackage;
         if (typeof fpkg === 'function') {
             cb = fpkg;
             fpkg = opts.package;
         }
-        
-        var pkgfile = path.join(x, '/package.json');
+
+        var pkgfile = path.join(x, 'package.json');
         isFile(pkgfile, function (err, ex) {
             if (err) return cb(err);
-            if (!ex) return loadAsFile(path.join(x, '/index'), fpkg, cb);
-            
+            if (!ex) return loadAsFile(path.join(x, 'index'), fpkg, cb);
+
             readFile(pkgfile, function (err, body) {
                 if (err) return cb(err);
                 try {
                     var pkg = JSON.parse(body);
-                }
-                catch (err) {}
-                
+                } catch (jsonErr) {}
+
                 if (opts.packageFilter) {
                     pkg = opts.packageFilter(pkg, pkgfile);
                 }
-                
+
                 if (pkg.main) {
-                    if (pkg.main === '.' || pkg.main === './'){
-                        pkg.main = 'index'
+                    if (pkg.main === '.' || pkg.main === './') {
+                        pkg.main = 'index';
                     }
                     loadAsFile(path.resolve(x, pkg.main), pkg, function (err, m, pkg) {
                         if (err) return cb(err);
                         if (m) return cb(null, m, pkg);
-                        if (!pkg) return loadAsFile(path.join(x, '/index'), pkg, cb);
+                        if (!pkg) return loadAsFile(path.join(x, 'index'), pkg, cb);
 
                         var dir = path.resolve(x, pkg.main);
                         loadAsDirectory(dir, pkg, function (err, n, pkg) {
                             if (err) return cb(err);
                             if (n) return cb(null, n, pkg);
-                            loadAsFile(path.join(x, '/index'), pkg, cb);
+                            loadAsFile(path.join(x, 'index'), pkg, cb);
                         });
                     });
                     return;
                 }
-                
+
                 loadAsFile(path.join(x, '/index'), pkg, cb);
             });
         });
     }
-    
-    function loadNodeModules (x, start, cb) {
-        (function process (dirs) {
-            if (dirs.length === 0) return cb(null, undefined);
-            var dir = dirs[0];
-            
-            var file = path.join(dir, '/', x);
-            loadAsFile(file, undefined, onfile);
-            
-            function onfile (err, m, pkg) {
-                if (err) return cb(err);
-                if (m) return cb(null, m, pkg);
-                loadAsDirectory(path.join(dir, '/', x), undefined, ondir);
-            }
-            
-            function ondir (err, n, pkg) {
-                if (err) return cb(err);
-                if (n) return cb(null, n, pkg);
-                process(dirs.slice(1));
-            }
-        })(nodeModulesPaths(start, opts));
+
+    function processDirs(cb, dirs) {
+        if (dirs.length === 0) return cb(null, undefined);
+        var dir = dirs[0];
+
+        var file = path.join(dir, x);
+        loadAsFile(file, undefined, onfile);
+
+        function onfile(err, m, pkg) {
+            if (err) return cb(err);
+            if (m) return cb(null, m, pkg);
+            loadAsDirectory(path.join(dir, x), undefined, ondir);
+        }
+
+        function ondir(err, n, pkg) {
+            if (err) return cb(err);
+            if (n) return cb(null, n, pkg);
+            processDirs(cb, dirs.slice(1));
+        }
+    }
+    function loadNodeModules(x, start, cb) {
+        processDirs(cb, nodeModulesPaths(start, opts));
     }
 };
diff --git a/lib/caller.js b/lib/caller.js
index 5536549..b14a280 100644
--- a/lib/caller.js
+++ b/lib/caller.js
@@ -1,7 +1,7 @@
 module.exports = function () {
     // see https://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
     var origPrepareStackTrace = Error.prepareStackTrace;
-    Error.prepareStackTrace = function (_, stack) { return stack };
+    Error.prepareStackTrace = function (_, stack) { return stack; };
     var stack = (new Error()).stack;
     Error.prepareStackTrace = origPrepareStackTrace;
     return stack[2].getFileName();
diff --git a/lib/core.js b/lib/core.js
index ea4a6c8..ad9efd1 100644
--- a/lib/core.js
+++ b/lib/core.js
@@ -1,4 +1,22 @@
-module.exports = require('./core.json').reduce(function (acc, x) {
-    acc[x] = true;
-    return acc;
-}, {});
+var current = (process.versions && process.versions.node && process.versions.node.split('.')) || [];
+
+function versionIncluded(version) {
+    if (version === '*') return true;
+    var versionParts = version.split('.');
+    for (var i = 0; i < 3; ++i) {
+        if ((current[i] || 0) >= (versionParts[i] || 0)) return true;
+    }
+    return false;
+}
+
+var data = require('./core.json');
+
+var core = {};
+for (var version in data) { // eslint-disable-line no-restricted-syntax
+    if (Object.prototype.hasOwnProperty.call(data, version) && versionIncluded(version)) {
+        for (var i = 0; i < data[version].length; ++i) {
+            core[data[version][i]] = true;
+        }
+    }
+}
+module.exports = core;
diff --git a/lib/core.json b/lib/core.json
index 28560f7..843844e 100644
--- a/lib/core.json
+++ b/lib/core.json
@@ -1,38 +1,47 @@
-[
-    "assert",
-    "buffer_ieee754",
-    "buffer",
-    "child_process",
-    "cluster",
-    "console",
-    "constants",
-    "crypto",
-    "_debugger",
-    "dgram",
-    "dns",
-    "domain",
-    "events",
-    "freelist",
-    "fs",
-    "http",
-    "https",
-    "_linklist",
-    "module",
-    "net",
-    "os",
-    "path",
-    "punycode",
-    "querystring",
-    "readline",
-    "repl",
-    "stream",
-    "string_decoder",
-    "sys",
-    "timers",
-    "tls",
-    "tty",
-    "url",
-    "util",
-    "vm",
-    "zlib"
-]
+{
+    "*": [
+        "assert",
+        "buffer_ieee754",
+        "buffer",
+        "child_process",
+        "cluster",
+        "console",
+        "constants",
+        "crypto",
+        "_debugger",
+        "dgram",
+        "dns",
+        "domain",
+        "events",
+        "freelist",
+        "fs",
+        "http",
+        "https",
+        "_linklist",
+        "module",
+        "net",
+        "os",
+        "path",
+        "punycode",
+        "querystring",
+        "readline",
+        "repl",
+        "stream",
+        "string_decoder",
+        "sys",
+        "timers",
+        "tls",
+        "tty",
+        "url",
+        "util",
+        "vm",
+        "zlib"
+    ],
+    "0.11": [
+        "_http_server"
+    ],
+    "1.0": [
+        "process",
+        "v8"
+    ]
+}
diff --git a/lib/node-modules-paths.js b/lib/node-modules-paths.js
index ce0a0d9..a4bde6a 100644
--- a/lib/node-modules-paths.js
+++ b/lib/node-modules-paths.js
@@ -1,38 +1,45 @@
 var path = require('path');
+var fs = require('fs');
+var parse = path.parse || require('path-parse');
 
-module.exports = function (start, opts) {
-    var modules = opts.moduleDirectory
+module.exports = function nodeModulesPaths(start, opts) {
+    var modules = opts && opts.moduleDirectory
         ? [].concat(opts.moduleDirectory)
-        : ['node_modules']
-    ;
+        : ['node_modules'];
 
     // ensure that `start` is an absolute path at this point,
     // resolving against the process' current working directory
-    start = path.resolve(start);
+    var absoluteStart = path.resolve(start);
+
+    if (opts && opts.preserveSymlinks === false) {
+        try {
+            absoluteStart = fs.realpathSync(absoluteStart);
+        } catch (err) {
+            if (err.code !== 'ENOENT') {
+                throw err;
+            }
+        }
+    }
 
     var prefix = '/';
-    if (/^([A-Za-z]:)/.test(start)) {
+    if (/^([A-Za-z]:)/.test(absoluteStart)) {
         prefix = '';
-    } else if (/^\\\\/.test(start)) {
+    } else if (/^\\\\/.test(absoluteStart)) {
         prefix = '\\\\';
     }
 
-    var splitRe = process.platform === 'win32' ? /[\/\\]/ : /\/+/;
-
-    var parts = start.split(splitRe);
+    var paths = [absoluteStart];
+    var parsed = parse(absoluteStart);
+    while (parsed.dir !== paths[paths.length - 1]) {
+        paths.push(parsed.dir);
+        parsed = parse(parsed.dir);
+    }
 
-    var dirs = [];
-    for (var i = parts.length - 1; i >= 0; i--) {
-        if (modules.indexOf(parts[i]) !== -1) continue;
-        dirs = dirs.concat(modules.map(function(module_dir) {
-            return prefix + path.join(
-                path.join.apply(path, parts.slice(0, i + 1)),
-                module_dir
-            );
+    var dirs = paths.reduce(function (dirs, aPath) {
+        return dirs.concat(modules.map(function (moduleDir) {
+            return path.join(prefix, aPath, moduleDir);
         }));
-    }
-    if (process.platform === 'win32'){
-        dirs[dirs.length-1] = dirs[dirs.length-1].replace(":", ":\\");
-    }
-    return dirs.concat(opts.paths);
-}
+    }, []);
+
+    return opts && opts.paths ? dirs.concat(opts.paths) : dirs;
+};
diff --git a/lib/sync.js b/lib/sync.js
index ef91edd..bc9e287 100644
--- a/lib/sync.js
+++ b/lib/sync.js
@@ -4,39 +4,48 @@ var path = require('path');
 var caller = require('./caller.js');
 var nodeModulesPaths = require('./node-modules-paths.js');
 
-module.exports = function (x, opts) {
-    if (!opts) opts = {};
+module.exports = function (x, options) {
+    if (typeof x !== 'string') {
+        throw new TypeError('Path must be a string.');
+    }
+    var opts = options || {};
     var isFile = opts.isFile || function (file) {
-        try { var stat = fs.statSync(file) }
-        catch (err) { if (err && err.code === 'ENOENT') return false }
+        try {
+            var stat = fs.statSync(file);
+        } catch (e) {
+            if (e && (e.code === 'ENOENT' || e.code === 'ENOTDIR')) return false;
+            throw e;
+        }
         return stat.isFile() || stat.isFIFO();
     };
     var readFileSync = opts.readFileSync || fs.readFileSync;
-    
-    var extensions = opts.extensions || [ '.js' ];
+
+    var extensions = opts.extensions || ['.js'];
     var y = opts.basedir || path.dirname(caller());
 
     opts.paths = opts.paths || [];
 
-    if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[\\\/])/.test(x)) {
+    if (/^(?:\.\.?(?:\/|$)|\/|([A-Za-z]:)?[/\\])/.test(x)) {
         var res = path.resolve(y, x);
-        if (x === '..') res += '/';
+        if (x === '..' || x.slice(-1) === '/') res += '/';
         var m = loadAsFileSync(res) || loadAsDirectorySync(res);
         if (m) return m;
     } else {
         var n = loadNodeModulesSync(x, y);
         if (n) return n;
     }
-    
+
     if (core[x]) return x;
-    
-    throw new Error("Cannot find module '" + x + "' from '" + y + "'");
-    
-    function loadAsFileSync (x) {
+
+    var err = new Error("Cannot find module '" + x + "' from '" + y + "'");
+    err.code = 'MODULE_NOT_FOUND';
+    throw err;
+
+    function loadAsFileSync(x) {
         if (isFile(x)) {
             return x;
         }
-        
+
         for (var i = 0; i < extensions.length; i++) {
             var file = x + extensions[i];
             if (isFile(file)) {
@@ -44,37 +53,40 @@ module.exports = function (x, opts) {
             }
         }
     }
-    
-    function loadAsDirectorySync (x) {
+
+    function loadAsDirectorySync(x) {
         var pkgfile = path.join(x, '/package.json');
         if (isFile(pkgfile)) {
-            var body = readFileSync(pkgfile, 'utf8');
             try {
+                var body = readFileSync(pkgfile, 'UTF8');
                 var pkg = JSON.parse(body);
+
                 if (opts.packageFilter) {
                     pkg = opts.packageFilter(pkg, x);
                 }
-                
+
                 if (pkg.main) {
+                    if (pkg.main === '.' || pkg.main === './') {
+                        pkg.main = 'index';
+                    }
                     var m = loadAsFileSync(path.resolve(x, pkg.main));
                     if (m) return m;
                     var n = loadAsDirectorySync(path.resolve(x, pkg.main));
                     if (n) return n;
                 }
-            }
-            catch (err) {}
+            } catch (e) {}
         }
-        
-        return loadAsFileSync(path.join( x, '/index'));
+
+        return loadAsFileSync(path.join(x, '/index'));
     }
-    
-    function loadNodeModulesSync (x, start) {
+
+    function loadNodeModulesSync(x, start) {
         var dirs = nodeModulesPaths(start, opts);
         for (var i = 0; i < dirs.length; i++) {
             var dir = dirs[i];
-            var m = loadAsFileSync(path.join( dir, '/', x));
+            var m = loadAsFileSync(path.join(dir, '/', x));
             if (m) return m;
-            var n = loadAsDirectorySync(path.join( dir, '/', x ));
+            var n = loadAsDirectorySync(path.join(dir, '/', x));
             if (n) return n;
         }
     }
diff --git a/package.json b/package.json
index 507fe8b..1f8d597 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "resolve",
   "description": "resolve like require.resolve() on behalf of files asynchronously and synchronously",
-  "version": "1.1.7",
+  "version": "1.4.0",
   "repository": {
     "type": "git",
     "url": "git://github.com/substack/node-resolve.git"
@@ -14,16 +14,27 @@
     "module"
   ],
   "scripts": {
-    "test": "tape test/*.js"
+    "prepublish": "safe-publish-latest",
+    "lint": "eslint .",
+    "tests-only": "tape test/*.js",
+    "pretest": "npm run lint",
+    "test": "npm run --silent tests-only"
   },
   "devDependencies": {
-    "tape": "^3.5.0",
-    "tap": "0.4.13"
+    "@ljharb/eslint-config": "^12.2.0",
+    "eslint": "^4.3.0",
+    "object-keys": "^1.0.11",
+    "safe-publish-latest": "^1.1.1",
+    "tap": "0.4.13",
+    "tape": "^4.7.0"
   },
   "license": "MIT",
   "author": {
     "name": "James Halliday",
     "email": "mail at substack.net",
     "url": "http://substack.net"
+  },
+  "dependencies": {
+    "path-parse": "^1.0.5"
   }
 }
diff --git a/readme.markdown b/readme.markdown
index 4fab9b0..1bb67d4 100644
--- a/readme.markdown
+++ b/readme.markdown
@@ -1,7 +1,7 @@
 # resolve
 
 implements the [node `require.resolve()`
-algorithm](http://nodejs.org/docs/v0.4.8/api/all.html#all_Together...)
+algorithm](https://nodejs.org/api/modules.html#modules_all_together)
 such that you can `require.resolve()` on behalf of a file asynchronously and
 synchronously
 
@@ -73,6 +73,11 @@ node_modules recursive walk (probably don't use this)
 
 * opts.moduleDirectory - directory (or directories) in which to recursively look for modules. default: `"node_modules"`
 
+* opts.preserveSymlinks - if true, doesn't resolve `basedir` to real path before resolving.
+This is the way Node resolves dependencies when executed with the [--preserve-symlinks](https://nodejs.org/api/all.html#cli_preserve_symlinks) flag.
+**Note:** this property is currently `true` by default but it will be changed to
+`false` in the next major version because *Node's resolution algorithm does not preserve symlinks by default*.
+
 default `opts` values:
 
 ``` javascript
@@ -88,7 +93,8 @@ default `opts` values:
             else cb(null, stat.isFile())
         });
     },
-    moduleDirectory: 'node_modules'
+    moduleDirectory: 'node_modules',
+    preserveSymlinks: true
 }
 ```
 
@@ -115,6 +121,11 @@ node_modules recursive walk (probably don't use this)
 
 * opts.moduleDirectory - directory (or directories) in which to recursively look for modules. default: `"node_modules"`
 
+* opts.preserveSymlinks - if true, doesn't resolve `basedir` to real path before resolving.
+This is the way Node resolves dependencies when executed with the [--preserve-symlinks](https://nodejs.org/api/all.html#cli_preserve_symlinks) flag.
+**Note:** this property is currently `true` by default but it will be changed to
+`false` in the next major version because *Node's resolution algorithm does not preserve symlinks by default*.
+
 default `opts` values:
 
 ``` javascript
@@ -127,7 +138,8 @@ default `opts` values:
         try { return fs.statSync(file).isFile() }
         catch (e) { return false }
     },
-    moduleDirectory: 'node_modules'
+    moduleDirectory: 'node_modules',
+    preserveSymlinks: true
 }
 ````
 
diff --git a/test/core.js b/test/core.js
index 4a56682..1182e0c 100644
--- a/test/core.js
+++ b/test/core.js
@@ -2,11 +2,28 @@ var test = require('tape');
 var resolve = require('../');
 
 test('core modules', function (t) {
-    t.ok(resolve.isCore('fs'));
-    t.ok(resolve.isCore('net'));
-    t.ok(resolve.isCore('http'));
-    
-    t.ok(!resolve.isCore('seq'));
-    t.ok(!resolve.isCore('../'));
+    t.test('isCore()', function (st) {
+        st.ok(resolve.isCore('fs'));
+        st.ok(resolve.isCore('net'));
+        st.ok(resolve.isCore('http'));
+
+        st.ok(!resolve.isCore('seq'));
+        st.ok(!resolve.isCore('../'));
+        st.end();
+    });
+
+    t.test('core list', function (st) {
+        st.plan(resolve.core.length);
+
+        for (var i = 0; i < resolve.core.length; ++i) {
+            st.doesNotThrow(
+                function () { require(resolve.core[i]); }, // eslint-disable-line no-loop-func
+                'requiring ' + resolve.core[i] + ' does not throw'
+            );
+        }
+
+        st.end();
+    });
+
     t.end();
 });
diff --git a/test/dotdot.js b/test/dotdot.js
index b876772..3080665 100644
--- a/test/dotdot.js
+++ b/test/dotdot.js
@@ -4,26 +4,26 @@ var resolve = require('../');
 
 test('dotdot', function (t) {
     t.plan(4);
-    var dir = __dirname + '/dotdot/abc';
-    
-    resolve('..', { basedir : dir }, function (err, res, pkg) {
+    var dir = path.join(__dirname, '/dotdot/abc');
+
+    resolve('..', { basedir: dir }, function (err, res, pkg) {
         t.ifError(err);
-        t.equal(res, __dirname + '/dotdot/index.js');
+        t.equal(res, path.join(__dirname, 'dotdot/index.js'));
     });
-    
-    resolve('.', { basedir : dir }, function (err, res, pkg) {
+
+    resolve('.', { basedir: dir }, function (err, res, pkg) {
         t.ifError(err);
-        t.equal(res, dir + '/index.js');
+        t.equal(res, path.join(dir, 'index.js'));
     });
 });
 
 test('dotdot sync', function (t) {
     t.plan(2);
-    var dir = __dirname + '/dotdot/abc';
-    
-    var a = resolve.sync('..', { basedir : dir });
-    t.equal(a, __dirname + '/dotdot/index.js');
-    
-    var b = resolve.sync('.', { basedir : dir });
-    t.equal(b, dir + '/index.js');
+    var dir = path.join(__dirname, '/dotdot/abc');
+
+    var a = resolve.sync('..', { basedir: dir });
+    t.equal(a, path.join(__dirname, 'dotdot/index.js'));
+
+    var b = resolve.sync('.', { basedir: dir });
+    t.equal(b, path.join(dir, 'index.js'));
 });
diff --git a/test/dotdot/index.js b/test/dotdot/index.js
index afec736..643f9fc 100644
--- a/test/dotdot/index.js
+++ b/test/dotdot/index.js
@@ -1 +1 @@
-module.exports = 'whatever'
+module.exports = 'whatever';
diff --git a/test/faulty_basedir.js b/test/faulty_basedir.js
index 2440818..e20d937 100644
--- a/test/faulty_basedir.js
+++ b/test/faulty_basedir.js
@@ -1,16 +1,12 @@
-var path = require('path');
 var test = require('tape');
 var resolve = require('../');
 
-// not sure what's up with this test anymore
-if (process.platform !== 'win32') return;
-
-test('faulty basedir must produce error in windows', function (t) {
+test('faulty basedir must produce error in windows', { skip: process.platform !== 'win32' }, function (t) {
     t.plan(1);
 
     var resolverDir = 'C:\\a\\b\\c\\d';
 
-    resolve('tape/lib/test.js', { basedir : resolverDir }, function (err, res, pkg) {
+    resolve('tape/lib/test.js', { basedir: resolverDir }, function (err, res, pkg) {
         t.equal(true, !!err);
     });
 
diff --git a/test/filter.js b/test/filter.js
index 07c38f3..51a753f 100644
--- a/test/filter.js
+++ b/test/filter.js
@@ -1,18 +1,19 @@
+var path = require('path');
 var test = require('tape');
 var resolve = require('../');
 
 test('filter', function (t) {
     t.plan(2);
-    var dir = __dirname + '/resolver';
+    var dir = path.join(__dirname, 'resolver');
     resolve('./baz', {
-        basedir : dir,
-        packageFilter : function (pkg) {
+        basedir: dir,
+        packageFilter: function (pkg) {
             pkg.main = 'doom';
             return pkg;
         }
     }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/baz/doom.js');
+        t.equal(res, path.join(dir, 'baz/doom.js'));
         t.equal(pkg.main, 'doom');
     });
 });
diff --git a/test/filter_sync.js b/test/filter_sync.js
index 3f89b79..fd4e97c 100644
--- a/test/filter_sync.js
+++ b/test/filter_sync.js
@@ -1,15 +1,16 @@
+var path = require('path');
 var test = require('tape');
 var resolve = require('../');
 
 test('filter', function (t) {
-    var dir = __dirname + '/resolver';
+    var dir = path.join(__dirname, 'resolver');
     var res = resolve.sync('./baz', {
-        basedir : dir,
-        packageFilter : function (pkg) {
-            pkg.main = 'doom'
+        basedir: dir,
+        packageFilter: function (pkg) {
+            pkg.main = 'doom';
             return pkg;
         }
     });
-    t.equal(res, dir + '/baz/doom.js');
+    t.equal(res, path.join(dir, 'baz/doom.js'));
     t.end();
 });
diff --git a/test/mock.js b/test/mock.js
index 1cf3b12..a88059d 100644
--- a/test/mock.js
+++ b/test/mock.js
@@ -1,142 +1,143 @@
+var path = require('path');
 var test = require('tape');
 var resolve = require('../');
 
 test('mock', function (t) {
-    t.plan(6);
-    
-    var files = {
-        '/foo/bar/baz.js' : 'beep'
-    };
-    
-    function opts (basedir) {
+    t.plan(8);
+
+    var files = {};
+    files[path.resolve('/foo/bar/baz.js')] = 'beep';
+
+    function opts(basedir) {
         return {
-            basedir : basedir,
-            isFile : function (file, cb) {
-                cb(null, files.hasOwnProperty(file));
+            basedir: path.resolve(basedir),
+            isFile: function (file, cb) {
+                cb(null, Object.prototype.hasOwnProperty.call(files, path.resolve(file)));
             },
-            readFile : function (file, cb) {
-                cb(null, files[file]);
+            readFile: function (file, cb) {
+                cb(null, files[path.resolve(file)]);
             }
-        }
+        };
     }
-    
+
     resolve('./baz', opts('/foo/bar'), function (err, res, pkg) {
-        if (err) t.fail(err);
-        t.equal(res, '/foo/bar/baz.js');
+        if (err) return t.fail(err);
+        t.equal(res, path.resolve('/foo/bar/baz.js'));
         t.equal(pkg, undefined);
     });
-    
+
     resolve('./baz.js', opts('/foo/bar'), function (err, res, pkg) {
-        if (err) t.fail(err);
-        t.equal(res, '/foo/bar/baz.js');
+        if (err) return t.fail(err);
+        t.equal(res, path.resolve('/foo/bar/baz.js'));
         t.equal(pkg, undefined);
     });
-    
+
     resolve('baz', opts('/foo/bar'), function (err, res) {
-        t.equal(err.message, "Cannot find module 'baz' from '/foo/bar'");
+        t.equal(err.message, "Cannot find module 'baz' from '" + path.resolve('/foo/bar') + "'");
+        t.equal(err.code, 'MODULE_NOT_FOUND');
     });
-    
+
     resolve('../baz', opts('/foo/bar'), function (err, res) {
-        t.equal(err.message, "Cannot find module '../baz' from '/foo/bar'");
+        t.equal(err.message, "Cannot find module '../baz' from '" + path.resolve('/foo/bar') + "'");
+        t.equal(err.code, 'MODULE_NOT_FOUND');
     });
 });
 
 test('mock from package', function (t) {
-    t.plan(6);
-    
-    var files = {
-        '/foo/bar/baz.js' : 'beep'
-    };
-    
-    function opts (basedir) {
+    t.plan(8);
+
+    var files = {};
+    files[path.resolve('/foo/bar/baz.js')] = 'beep';
+
+    function opts(basedir) {
         return {
-            basedir : basedir,
-            package : { main: 'bar' },
-            isFile : function (file, cb) {
-                cb(null, files.hasOwnProperty(file));
+            basedir: path.resolve(basedir),
+            isFile: function (file, cb) {
+                cb(null, Object.prototype.hasOwnProperty.call(files, file));
             },
-            readFile : function (file, cb) {
+            'package': { main: 'bar' },
+            readFile: function (file, cb) {
                 cb(null, files[file]);
             }
-        }
+        };
     }
-    
+
     resolve('./baz', opts('/foo/bar'), function (err, res, pkg) {
-        if (err) t.fail(err);
-        t.equal(res, '/foo/bar/baz.js');
-        t.equal(pkg.main, 'bar');
+        if (err) return t.fail(err);
+        t.equal(res, path.resolve('/foo/bar/baz.js'));
+        t.equal(pkg && pkg.main, 'bar');
     });
-    
+
     resolve('./baz.js', opts('/foo/bar'), function (err, res, pkg) {
-        if (err) t.fail(err);
-        t.equal(res, '/foo/bar/baz.js');
-        t.equal(pkg.main, 'bar');
+        if (err) return t.fail(err);
+        t.equal(res, path.resolve('/foo/bar/baz.js'));
+        t.equal(pkg && pkg.main, 'bar');
     });
-    
+
     resolve('baz', opts('/foo/bar'), function (err, res) {
-        t.equal(err.message, "Cannot find module 'baz' from '/foo/bar'");
+        t.equal(err.message, "Cannot find module 'baz' from '" + path.resolve('/foo/bar') + "'");
+        t.equal(err.code, 'MODULE_NOT_FOUND');
     });
-    
+
     resolve('../baz', opts('/foo/bar'), function (err, res) {
-        t.equal(err.message, "Cannot find module '../baz' from '/foo/bar'");
+        t.equal(err.message, "Cannot find module '../baz' from '" + path.resolve('/foo/bar') + "'");
+        t.equal(err.code, 'MODULE_NOT_FOUND');
     });
 });
 
 test('mock package', function (t) {
     t.plan(2);
-    
-    var files = {
-        '/foo/node_modules/bar/baz.js' : 'beep',
-        '/foo/node_modules/bar/package.json' : JSON.stringify({
-            main : './baz.js'
-        })
-    };
-    
-    function opts (basedir) {
+
+    var files = {};
+    files[path.resolve('/foo/node_modules/bar/baz.js')] = 'beep';
+    files[path.resolve('/foo/node_modules/bar/package.json')] = JSON.stringify({
+        main: './baz.js'
+    });
+
+    function opts(basedir) {
         return {
-            basedir : basedir,
-            isFile : function (file, cb) {
-                cb(null, files.hasOwnProperty(file));
+            basedir: path.resolve(basedir),
+            isFile: function (file, cb) {
+                cb(null, Object.prototype.hasOwnProperty.call(files, path.resolve(file)));
             },
-            readFile : function (file, cb) {
-                cb(null, files[file]);
+            readFile: function (file, cb) {
+                cb(null, files[path.resolve(file)]);
             }
-        }
+        };
     }
-    
+
     resolve('bar', opts('/foo'), function (err, res, pkg) {
-        if (err) t.fail(err);
-        t.equal(res, '/foo/node_modules/bar/baz.js');
-        t.equal(pkg.main, './baz.js');
+        if (err) return t.fail(err);
+        t.equal(res, path.resolve('/foo/node_modules/bar/baz.js'));
+        t.equal(pkg && pkg.main, './baz.js');
     });
 });
 
 test('mock package from package', function (t) {
     t.plan(2);
-    
-    var files = {
-        '/foo/node_modules/bar/baz.js' : 'beep',
-        '/foo/node_modules/bar/package.json' : JSON.stringify({
-            main : './baz.js'
-        })
-    };
-    
-    function opts (basedir) {
+
+    var files = {};
+    files[path.resolve('/foo/node_modules/bar/baz.js')] = 'beep';
+    files[path.resolve('/foo/node_modules/bar/package.json')] = JSON.stringify({
+        main: './baz.js'
+    });
+
+    function opts(basedir) {
         return {
-            basedir : basedir,
-            package : { main: 'bar' },
-            isFile : function (file, cb) {
-                cb(null, files.hasOwnProperty(file));
+            basedir: path.resolve(basedir),
+            isFile: function (file, cb) {
+                cb(null, Object.prototype.hasOwnProperty.call(files, path.resolve(file)));
             },
-            readFile : function (file, cb) {
-                cb(null, files[file]);
+            'package': { main: 'bar' },
+            readFile: function (file, cb) {
+                cb(null, files[path.resolve(file)]);
             }
-        }
+        };
     }
-    
+
     resolve('bar', opts('/foo'), function (err, res, pkg) {
-        if (err) t.fail(err);
-        t.equal(res, '/foo/node_modules/bar/baz.js');
-        t.equal(pkg.main, './baz.js');
+        if (err) return t.fail(err);
+        t.equal(res, path.resolve('/foo/node_modules/bar/baz.js'));
+        t.equal(pkg && pkg.main, './baz.js');
     });
 });
diff --git a/test/mock_sync.js b/test/mock_sync.js
index abfd289..43af102 100644
--- a/test/mock_sync.js
+++ b/test/mock_sync.js
@@ -1,35 +1,35 @@
+var path = require('path');
 var test = require('tape');
 var resolve = require('../');
 
 test('mock', function (t) {
     t.plan(4);
-    
-    var files = {
-        '/foo/bar/baz.js' : 'beep'
-    };
-    
-    function opts (basedir) {
+
+    var files = {};
+    files[path.resolve('/foo/bar/baz.js')] = 'beep';
+
+    function opts(basedir) {
         return {
-            basedir : basedir,
-            isFile : function (file) {
-                return files.hasOwnProperty(file)
+            basedir: path.resolve(basedir),
+            isFile: function (file) {
+                return Object.prototype.hasOwnProperty.call(files, file);
             },
-            readFileSync : function (file) {
-                return files[file]
+            readFileSync: function (file) {
+                return files[file];
             }
-        }
+        };
     }
-    
+
     t.equal(
         resolve.sync('./baz', opts('/foo/bar')),
-        '/foo/bar/baz.js'
+        path.resolve('/foo/bar/baz.js')
     );
-    
+
     t.equal(
         resolve.sync('./baz.js', opts('/foo/bar')),
-        '/foo/bar/baz.js'
+        path.resolve('/foo/bar/baz.js')
     );
-    
+
     t.throws(function () {
         resolve.sync('baz', opts('/foo/bar'));
     });
@@ -41,28 +41,27 @@ test('mock', function (t) {
 
 test('mock package', function (t) {
     t.plan(1);
-    
-    var files = {
-        '/foo/node_modules/bar/baz.js' : 'beep',
-        '/foo/node_modules/bar/package.json' : JSON.stringify({
-            main : './baz.js'
-        })
-    };
-    
-    function opts (basedir) {
+
+    var files = {};
+    files[path.resolve('/foo/node_modules/bar/baz.js')] = 'beep';
+    files[path.resolve('/foo/node_modules/bar/package.json')] = JSON.stringify({
+        main: './baz.js'
+    });
+
+    function opts(basedir) {
         return {
-            basedir : basedir,
-            isFile : function (file) {
-                return files.hasOwnProperty(file)
+            basedir: path.resolve(basedir),
+            isFile: function (file) {
+                return Object.prototype.hasOwnProperty.call(files, file);
             },
-            readFileSync : function (file) {
-                return files[file]
+            readFileSync: function (file) {
+                return files[file];
             }
-        }
+        };
     }
-    
+
     t.equal(
         resolve.sync('bar', opts('/foo')),
-        '/foo/node_modules/bar/baz.js'
+        path.resolve('/foo/node_modules/bar/baz.js')
     );
 });
diff --git a/test/module_dir.js b/test/module_dir.js
index 06395d8..b50e5bb 100644
--- a/test/module_dir.js
+++ b/test/module_dir.js
@@ -4,53 +4,53 @@ var resolve = require('../');
 
 test('moduleDirectory strings', function (t) {
     t.plan(4);
-    var dir = __dirname + '/module_dir';
+    var dir = path.join(__dirname, 'module_dir');
     var xopts = {
-        basedir : dir,
+        basedir: dir,
         moduleDirectory: 'xmodules'
     };
     resolve('aaa', xopts, function (err, res, pkg) {
         t.ifError(err);
-        t.equal(res, dir + '/xmodules/aaa/index.js');
+        t.equal(res, path.join(dir, '/xmodules/aaa/index.js'));
     });
-    
+
     var yopts = {
-        basedir : dir,
+        basedir: dir,
         moduleDirectory: 'ymodules'
     };
     resolve('aaa', yopts, function (err, res, pkg) {
         t.ifError(err);
-        t.equal(res, dir + '/ymodules/aaa/index.js');
+        t.equal(res, path.join(dir, '/ymodules/aaa/index.js'));
     });
 });
 
 test('moduleDirectory array', function (t) {
     t.plan(6);
-    var dir = __dirname + '/module_dir';
+    var dir = path.join(__dirname, 'module_dir');
     var aopts = {
-        basedir : dir,
-        moduleDirectory: [ 'xmodules', 'ymodules', 'zmodules' ]
+        basedir: dir,
+        moduleDirectory: ['xmodules', 'ymodules', 'zmodules']
     };
     resolve('aaa', aopts, function (err, res, pkg) {
         t.ifError(err);
-        t.equal(res, dir + '/xmodules/aaa/index.js');
+        t.equal(res, path.join(dir, '/xmodules/aaa/index.js'));
     });
-    
+
     var bopts = {
-        basedir : dir,
-        moduleDirectory: [ 'zmodules', 'ymodules', 'xmodules' ]
+        basedir: dir,
+        moduleDirectory: ['zmodules', 'ymodules', 'xmodules']
     };
     resolve('aaa', bopts, function (err, res, pkg) {
         t.ifError(err);
-        t.equal(res, dir + '/ymodules/aaa/index.js');
+        t.equal(res, path.join(dir, '/ymodules/aaa/index.js'));
     });
-    
+
     var copts = {
-        basedir : dir,
-        moduleDirectory: [ 'xmodules', 'ymodules', 'zmodules' ]
+        basedir: dir,
+        moduleDirectory: ['xmodules', 'ymodules', 'zmodules']
     };
     resolve('bbb', copts, function (err, res, pkg) {
         t.ifError(err);
-        t.equal(res, dir + '/zmodules/bbb/main.js');
+        t.equal(res, path.join(dir, '/zmodules/bbb/main.js'));
     });
 });
diff --git a/test/module_dir/xmodules/aaa/index.js b/test/module_dir/xmodules/aaa/index.js
index 55cd18c..dd7cf7b 100644
--- a/test/module_dir/xmodules/aaa/index.js
+++ b/test/module_dir/xmodules/aaa/index.js
@@ -1 +1 @@
-module.exports = function (x) { return x * 100 }
+module.exports = function (x) { return x * 100; };
diff --git a/test/module_dir/ymodules/aaa/index.js b/test/module_dir/ymodules/aaa/index.js
index 651aca8..ef2d4d4 100644
--- a/test/module_dir/ymodules/aaa/index.js
+++ b/test/module_dir/ymodules/aaa/index.js
@@ -1 +1 @@
-module.exports = function (x) { return x + 100 }
+module.exports = function (x) { return x + 100; };
diff --git a/test/module_dir/zmodules/bbb/main.js b/test/module_dir/zmodules/bbb/main.js
index 4325a0b..e8ba629 100644
--- a/test/module_dir/zmodules/bbb/main.js
+++ b/test/module_dir/zmodules/bbb/main.js
@@ -1 +1 @@
-module.exports = function (n) { return n * 111 }
+module.exports = function (n) { return n * 111; };
diff --git a/test/node-modules-paths.js b/test/node-modules-paths.js
new file mode 100644
index 0000000..a917f06
--- /dev/null
+++ b/test/node-modules-paths.js
@@ -0,0 +1,93 @@
+var test = require('tape');
+var path = require('path');
+var parse = path.parse || require('path-parse');
+var keys = require('object-keys');
+
+var nodeModulesPaths = require('../lib/node-modules-paths');
+
+var verifyDirs = function verifyDirs(t, start, dirs, moduleDirectories, paths) {
+    var moduleDirs = [].concat(moduleDirectories || 'node_modules');
+
+    var foundModuleDirs = {};
+    var uniqueDirs = {};
+    var parsedDirs = {};
+    for (var i = 0; i < dirs.length; ++i) {
+        var parsed = parse(dirs[i]);
+        if (!foundModuleDirs[parsed.base]) { foundModuleDirs[parsed.base] = 0; }
+        foundModuleDirs[parsed.base] += 1;
+        parsedDirs[parsed.dir] = true;
+        uniqueDirs[dirs[i]] = true;
+    }
+    t.equal(keys(parsedDirs).length >= start.split(path.sep).length, true, 'there are >= dirs than "start" has');
+    var foundModuleDirNames = keys(foundModuleDirs);
+    t.deepEqual(foundModuleDirNames, moduleDirs.concat(paths || []), 'all desired module dirs were found');
+    t.equal(keys(uniqueDirs).length, dirs.length, 'all dirs provided were unique');
+
+    var counts = {};
+    for (var j = 0; j < foundModuleDirNames.length; ++j) {
+        counts[foundModuleDirs[j]] = true;
+    }
+    t.equal(keys(counts).length, 1, 'all found module directories had the same count');
+};
+
+test('node-modules-paths', function (t) {
+    t.test('no options', function (t) {
+        var start = path.join(__dirname, 'resolver');
+        var dirs = nodeModulesPaths(start);
+
+        verifyDirs(t, start, dirs);
+
+        t.end();
+    });
+
+    t.test('empty options', function (t) {
+        var start = path.join(__dirname, 'resolver');
+        var dirs = nodeModulesPaths(start, {});
+
+        verifyDirs(t, start, dirs);
+
+        t.end();
+    });
+
+    t.test('with paths option', function (t) {
+        var start = path.join(__dirname, 'resolver');
+        var paths = ['a', 'b'];
+        var dirs = nodeModulesPaths(start, { paths: paths });
+
+        verifyDirs(t, start, dirs, null, paths);
+
+        t.end();
+    });
+
+    t.test('with moduleDirectory option', function (t) {
+        var start = path.join(__dirname, 'resolver');
+        var moduleDirectory = 'not node modules';
+        var dirs = nodeModulesPaths(start, { moduleDirectory: moduleDirectory });
+
+        verifyDirs(t, start, dirs, moduleDirectory);
+
+        t.end();
+    });
+
+    t.test('with 1 moduleDirectory and paths options', function (t) {
+        var start = path.join(__dirname, 'resolver');
+        var paths = ['a', 'b'];
+        var moduleDirectory = 'not node modules';
+        var dirs = nodeModulesPaths(start, { paths: paths, moduleDirectory: moduleDirectory });
+
+        verifyDirs(t, start, dirs, moduleDirectory, paths);
+
+        t.end();
+    });
+
+    t.test('with 1+ moduleDirectory and paths options', function (t) {
+        var start = path.join(__dirname, 'resolver');
+        var paths = ['a', 'b'];
+        var moduleDirectories = ['not node modules', 'other modules'];
+        var dirs = nodeModulesPaths(start, { paths: paths, moduleDirectory: moduleDirectories });
+
+        verifyDirs(t, start, dirs, moduleDirectories, paths);
+
+        t.end();
+    });
+});
diff --git a/test/node_path.js b/test/node_path.js
index 2407189..38a7d7e 100644
--- a/test/node_path.js
+++ b/test/node_path.js
@@ -4,45 +4,46 @@ var resolve = require('../');
 
 test('$NODE_PATH', function (t) {
     t.plan(4);
-    
+
     resolve('aaa', {
         paths: [
-            __dirname + '/node_path/x',
-            __dirname + '/node_path/y'
+            path.join(__dirname, '/node_path/x'),
+            path.join(__dirname, '/node_path/y')
         ],
-        basedir: __dirname,
+        basedir: __dirname
     }, function (err, res) {
-        t.equal(res, __dirname + '/node_path/x/aaa/index.js');
+        t.equal(res, path.join(__dirname, '/node_path/x/aaa/index.js'));
     });
-    
+
     resolve('bbb', {
         paths: [
-            __dirname + '/node_path/x',
-            __dirname + '/node_path/y'
+            path.join(__dirname, '/node_path/x'),
+            path.join(__dirname, '/node_path/y')
         ],
-        basedir: __dirname,
+        basedir: __dirname
     }, function (err, res) {
-        t.equal(res, __dirname + '/node_path/y/bbb/index.js');
+        t.equal(res, path.join(__dirname, '/node_path/y/bbb/index.js'));
     });
-    
+
     resolve('ccc', {
         paths: [
-            __dirname + '/node_path/x',
-            __dirname + '/node_path/y'
+            path.join(__dirname, '/node_path/x'),
+            path.join(__dirname, '/node_path/y')
         ],
-        basedir: __dirname,
+        basedir: __dirname
     }, function (err, res) {
-        t.equal(res, __dirname + '/node_path/x/ccc/index.js');
+        t.equal(res, path.join(__dirname, '/node_path/x/ccc/index.js'));
     });
 
     // ensure that relative paths still resolve against the
     // regular `node_modules` correctly
     resolve('tap', {
         paths: [
-            'node_path',
+            'node_path'
         ],
-        basedir: 'node_path/x',
+        basedir: 'node_path/x'
     }, function (err, res) {
-        t.equal(res, path.resolve(__dirname, '..', 'node_modules/tap/lib/main.js'));
+        var root = require('tap/package.json').main;
+        t.equal(res, path.resolve(__dirname, '..', 'node_modules/tap', root));
     });
 });
diff --git a/test/node_path/x/aaa/index.js b/test/node_path/x/aaa/index.js
index 1ea5913..ad70d0b 100644
--- a/test/node_path/x/aaa/index.js
+++ b/test/node_path/x/aaa/index.js
@@ -1 +1 @@
-module.exports = 'A'
+module.exports = 'A';
diff --git a/test/node_path/x/ccc/index.js b/test/node_path/x/ccc/index.js
index f186fa7..a64132e 100644
--- a/test/node_path/x/ccc/index.js
+++ b/test/node_path/x/ccc/index.js
@@ -1 +1 @@
-module.exports = 'C'
+module.exports = 'C';
diff --git a/test/node_path/y/bbb/index.js b/test/node_path/y/bbb/index.js
index e22dd83..4d0f32e 100644
--- a/test/node_path/y/bbb/index.js
+++ b/test/node_path/y/bbb/index.js
@@ -1 +1 @@
-module.exports = 'B'
+module.exports = 'B';
diff --git a/test/node_path/y/ccc/index.js b/test/node_path/y/ccc/index.js
index d0043d1..793315e 100644
--- a/test/node_path/y/ccc/index.js
+++ b/test/node_path/y/ccc/index.js
@@ -1 +1 @@
-module.exports = 'CY'
+module.exports = 'CY';
diff --git a/test/pathfilter.js b/test/pathfilter.js
index 142f94d..733045a 100644
--- a/test/pathfilter.js
+++ b/test/pathfilter.js
@@ -1,35 +1,42 @@
+var path = require('path');
 var test = require('tape');
 var resolve = require('../');
 
-test('#62: deep module references and the pathFilter', function(t){
-	t.plan(9);
-    
-	var resolverDir = __dirname + '/pathfilter/deep_ref';
-	var pathFilter = function(pkg, x, remainder){
-		t.equal(pkg.version, "1.2.3");
-		t.equal(x, resolverDir + '/node_modules/deep/ref');
-		t.equal(remainder, "ref");
-		return "alt";
-	};
-	
-	resolve('deep/ref', { basedir : resolverDir }, function (err, res, pkg) {
-        if (err) t.fail(err);
+test('#62: deep module references and the pathFilter', function (t) {
+    t.plan(9);
 
-        t.equal(pkg.version, "1.2.3");
-        t.equal(res, resolverDir + '/node_modules/deep/ref.js');
-    });
+    var resolverDir = path.join(__dirname, '/pathfilter/deep_ref');
+    var pathFilter = function (pkg, x, remainder) {
+        t.equal(pkg.version, '1.2.3');
+        t.equal(x, path.join(resolverDir, 'node_modules/deep/ref'));
+        t.equal(remainder, 'ref');
+        return 'alt';
+    };
 
-    resolve('deep/deeper/ref', { basedir: resolverDir },
-    function(err, res, pkg) {
-      if(err) t.fail(err);
-      t.notEqual(pkg, undefined);
-      t.equal(pkg.version, "1.2.3");
-      t.equal(res, resolverDir + '/node_modules/deep/deeper/ref.js');
-    });
-    
-    resolve('deep/ref', { basedir : resolverDir, pathFilter : pathFilter },
-    function (err, res, pkg) {
+    resolve('deep/ref', { basedir: resolverDir }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, resolverDir + '/node_modules/deep/alt.js');
+
+        t.equal(pkg.version, '1.2.3');
+        t.equal(res, path.join(resolverDir, 'node_modules/deep/ref.js'));
     });
+
+    resolve(
+        'deep/deeper/ref',
+        { basedir: resolverDir },
+        function (err, res, pkg) {
+            if (err) t.fail(err);
+            t.notEqual(pkg, undefined);
+            t.equal(pkg.version, '1.2.3');
+            t.equal(res, path.join(resolverDir, 'node_modules/deep/deeper/ref.js'));
+        }
+    );
+
+    resolve(
+        'deep/ref',
+        { basedir: resolverDir, pathFilter: pathFilter },
+        function (err, res, pkg) {
+            if (err) t.fail(err);
+            t.equal(res, path.join(resolverDir, 'node_modules/deep/alt.js'));
+        }
+    );
 });
diff --git a/test/precedence.js b/test/precedence.js
index c716f0e..2febb59 100644
--- a/test/precedence.js
+++ b/test/precedence.js
@@ -5,19 +5,19 @@ var resolve = require('../');
 test('precedence', function (t) {
     t.plan(3);
     var dir = path.join(__dirname, 'precedence/aaa');
-    
-    resolve('./', { basedir : dir }, function (err, res, pkg) {
+
+    resolve('./', { basedir: dir }, function (err, res, pkg) {
         t.ifError(err);
         t.equal(res, path.join(dir, 'index.js'));
         t.equal(pkg.name, 'resolve');
     });
 });
 
-test('./ should not load ${dir}.js', function (t) {
+test('./ should not load ${dir}.js', function (t) { // eslint-disable-line no-template-curly-in-string
     t.plan(1);
     var dir = path.join(__dirname, 'precedence/bbb');
-    
-    resolve('./', { basedir : dir }, function (err, res, pkg) {
+
+    resolve('./', { basedir: dir }, function (err, res, pkg) {
         t.ok(err);
     });
 });
diff --git a/test/precedence/aaa.js b/test/precedence/aaa.js
index a182397..b83a3e7 100644
--- a/test/precedence/aaa.js
+++ b/test/precedence/aaa.js
@@ -1 +1 @@
-module.exports = 'wtf'
+module.exports = 'wtf';
diff --git a/test/precedence/aaa/index.js b/test/precedence/aaa/index.js
index 993b03c..e0f8f6a 100644
--- a/test/precedence/aaa/index.js
+++ b/test/precedence/aaa/index.js
@@ -1 +1 @@
-module.exports = 'okok'
+module.exports = 'okok';
diff --git a/test/precedence/aaa/main.js b/test/precedence/aaa/main.js
index db38959..93542a9 100644
--- a/test/precedence/aaa/main.js
+++ b/test/precedence/aaa/main.js
@@ -1 +1 @@
-console.log(require('./'))
+console.log(require('./'));
diff --git a/test/precedence/bbb.js b/test/precedence/bbb.js
index c8a9996..2298f47 100644
--- a/test/precedence/bbb.js
+++ b/test/precedence/bbb.js
@@ -1 +1 @@
-module.exports '>_<'
+module.exports = '>_<';
diff --git a/test/resolver.js b/test/resolver.js
index 5bbb05f..56641df 100644
--- a/test/resolver.js
+++ b/test/resolver.js
@@ -3,279 +3,347 @@ var test = require('tape');
 var resolve = require('../');
 
 test('async foo', function (t) {
-    t.plan(9);
-    var dir = __dirname + '/resolver';
-    
-    resolve('./foo', { basedir : dir }, function (err, res, pkg) {
+    t.plan(10);
+    var dir = path.join(__dirname, 'resolver');
+
+    resolve('./foo', { basedir: dir }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/foo.js');
-        t.equal(pkg.name, 'resolve');
+        t.equal(res, path.join(dir, 'foo.js'));
+        t.equal(pkg && pkg.name, 'resolve');
     });
-    
-    resolve('./foo.js', { basedir : dir }, function (err, res, pkg) {
+
+    resolve('./foo.js', { basedir: dir }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/foo.js');
-        t.equal(pkg.name, 'resolve');
+        t.equal(res, path.join(dir, 'foo.js'));
+        t.equal(pkg && pkg.name, 'resolve');
     });
-    
-    resolve('./foo', { basedir : dir, package: { main: 'resolver' } }, function (err, res, pkg) {
+
+    resolve('./foo', { basedir: dir, 'package': { main: 'resolver' } }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/foo.js');
-        t.equal(pkg.main, 'resolver');
+        t.equal(res, path.join(dir, 'foo.js'));
+        t.equal(pkg && pkg.main, 'resolver');
     });
-    
-    resolve('./foo.js', { basedir : dir, package: { main: 'resolver' } }, function (err, res, pkg) {
+
+    resolve('./foo.js', { basedir: dir, 'package': { main: 'resolver' } }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/foo.js');
+        t.equal(res, path.join(dir, 'foo.js'));
         t.equal(pkg.main, 'resolver');
     });
-    
-    resolve('foo', { basedir : dir }, function (err) {
+
+    resolve('foo', { basedir: dir }, function (err) {
         t.equal(err.message, "Cannot find module 'foo' from '" + path.resolve(dir) + "'");
+        t.equal(err.code, 'MODULE_NOT_FOUND');
     });
 });
 
 test('bar', function (t) {
     t.plan(6);
-    var dir = __dirname + '/resolver';
-    
-    resolve('foo', { basedir : dir + '/bar' }, function (err, res, pkg) {
+    var dir = path.join(__dirname, 'resolver');
+
+    resolve('foo', { basedir: dir + '/bar' }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/bar/node_modules/foo/index.js');
+        t.equal(res, path.join(dir, 'bar/node_modules/foo/index.js'));
         t.equal(pkg, undefined);
     });
-    
-    resolve('foo', { basedir : dir + '/bar' }, function (err, res, pkg) {
+
+    resolve('foo', { basedir: dir + '/bar' }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/bar/node_modules/foo/index.js');
+        t.equal(res, path.join(dir, 'bar/node_modules/foo/index.js'));
         t.equal(pkg, undefined);
     });
-    
-    resolve('foo', { basedir : dir + '/bar', package: { main: 'bar' } }, function (err, res, pkg) {
+
+    resolve('foo', { basedir: dir + '/bar', 'package': { main: 'bar' } }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/bar/node_modules/foo/index.js');
+        t.equal(res, path.join(dir, 'bar/node_modules/foo/index.js'));
         t.equal(pkg, undefined);
     });
 });
 
 test('baz', function (t) {
     t.plan(4);
-    var dir = __dirname + '/resolver';
-    
-    resolve('./baz', { basedir : dir }, function (err, res, pkg) {
+    var dir = path.join(__dirname, 'resolver');
+
+    resolve('./baz', { basedir: dir }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/baz/quux.js');
+        t.equal(res, path.join(dir, 'baz/quux.js'));
         t.equal(pkg.main, 'quux.js');
     });
-    
-    resolve('./baz', { basedir : dir, package: { main: 'resolver' } }, function (err, res, pkg) {
+
+    resolve('./baz', { basedir: dir, 'package': { main: 'resolver' } }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/baz/quux.js');
+        t.equal(res, path.join(dir, 'baz/quux.js'));
         t.equal(pkg.main, 'quux.js');
     });
 });
 
 test('biz', function (t) {
     t.plan(24);
-    var dir = __dirname + '/resolver/biz/node_modules';
-    
-    resolve('./grux', { basedir : dir }, function (err, res, pkg) {
+    var dir = path.join(__dirname, 'resolver/biz/node_modules');
+
+    resolve('./grux', { basedir: dir }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/grux/index.js');
+        t.equal(res, path.join(dir, 'grux/index.js'));
         t.equal(pkg, undefined);
     });
-    
-    resolve('./grux', { basedir : dir, package: { main: 'biz' } }, function (err, res, pkg) {
+
+    resolve('./grux', { basedir: dir, 'package': { main: 'biz' } }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/grux/index.js');
+        t.equal(res, path.join(dir, 'grux/index.js'));
         t.equal(pkg.main, 'biz');
     });
-    
-    resolve('./garply', { basedir : dir }, function (err, res, pkg) {
+
+    resolve('./garply', { basedir: dir }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/garply/lib/index.js');
+        t.equal(res, path.join(dir, 'garply/lib/index.js'));
         t.equal(pkg.main, './lib');
     });
-    
-    resolve('./garply', { basedir : dir, package: { main: 'biz' } }, function (err, res, pkg) {
+
+    resolve('./garply', { basedir: dir, 'package': { main: 'biz' } }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/garply/lib/index.js');
+        t.equal(res, path.join(dir, 'garply/lib/index.js'));
         t.equal(pkg.main, './lib');
     });
-    
-    resolve('tiv', { basedir : dir + '/grux' }, function (err, res, pkg) {
+
+    resolve('tiv', { basedir: dir + '/grux' }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/tiv/index.js');
+        t.equal(res, path.join(dir, 'tiv/index.js'));
         t.equal(pkg, undefined);
     });
-    
-    resolve('tiv', { basedir : dir + '/grux', package: { main: 'grux' } }, function (err, res, pkg) {
+
+    resolve('tiv', { basedir: dir + '/grux', 'package': { main: 'grux' } }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/tiv/index.js');
+        t.equal(res, path.join(dir, 'tiv/index.js'));
         t.equal(pkg, undefined);
     });
-    
-    resolve('tiv', { basedir : dir + '/garply' }, function (err, res, pkg) {
+
+    resolve('tiv', { basedir: dir + '/garply' }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/tiv/index.js');
+        t.equal(res, path.join(dir, 'tiv/index.js'));
         t.equal(pkg, undefined);
     });
-    
-    resolve('tiv', { basedir : dir + '/garply', package: { main: './lib' } }, function (err, res, pkg) {
+
+    resolve('tiv', { basedir: dir + '/garply', 'package': { main: './lib' } }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/tiv/index.js');
+        t.equal(res, path.join(dir, 'tiv/index.js'));
         t.equal(pkg, undefined);
     });
-    
-    resolve('grux', { basedir : dir + '/tiv' }, function (err, res, pkg) {
+
+    resolve('grux', { basedir: dir + '/tiv' }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/grux/index.js');
+        t.equal(res, path.join(dir, 'grux/index.js'));
         t.equal(pkg, undefined);
     });
-    
-    resolve('grux', { basedir : dir + '/tiv', package: { main: 'tiv' }  }, function (err, res, pkg) {
+
+    resolve('grux', { basedir: dir + '/tiv', 'package': { main: 'tiv' } }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/grux/index.js');
+        t.equal(res, path.join(dir, 'grux/index.js'));
         t.equal(pkg, undefined);
     });
-    
-    resolve('garply', { basedir : dir + '/tiv' }, function (err, res, pkg) {
+
+    resolve('garply', { basedir: dir + '/tiv' }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/garply/lib/index.js');
+        t.equal(res, path.join(dir, 'garply/lib/index.js'));
         t.equal(pkg.main, './lib');
     });
-    
-    resolve('garply', { basedir : dir + '/tiv', package: { main: 'tiv' } }, function (err, res, pkg) {
+
+    resolve('garply', { basedir: dir + '/tiv', 'package': { main: 'tiv' } }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/garply/lib/index.js');
+        t.equal(res, path.join(dir, 'garply/lib/index.js'));
         t.equal(pkg.main, './lib');
     });
 });
 
 test('quux', function (t) {
     t.plan(2);
-    var dir = __dirname + '/resolver/quux';
-    
-    resolve('./foo', { basedir : dir, package: { main: 'quux' } }, function (err, res, pkg) {
+    var dir = path.join(__dirname, 'resolver/quux');
+
+    resolve('./foo', { basedir: dir, 'package': { main: 'quux' } }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/foo/index.js');
+        t.equal(res, path.join(dir, 'foo/index.js'));
         t.equal(pkg.main, 'quux');
     });
 });
 
 test('normalize', function (t) {
     t.plan(2);
-    var dir = __dirname + '/resolver/biz/node_modules/grux';
-    
-    resolve('../grux', { basedir : dir }, function (err, res, pkg) {
+    var dir = path.join(__dirname, 'resolver/biz/node_modules/grux');
+
+    resolve('../grux', { basedir: dir }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/index.js');
+        t.equal(res, path.join(dir, 'index.js'));
         t.equal(pkg, undefined);
     });
 });
 
 test('cup', function (t) {
-    t.plan(3);
-    var dir = __dirname + '/resolver';
-    
-    resolve('./cup', { basedir : dir, extensions : [ '.js', '.coffee' ] },
-    function (err, res) {
+    t.plan(4);
+    var dir = path.join(__dirname, 'resolver');
+
+    resolve('./cup', { basedir: dir, extensions: ['.js', '.coffee'] }, function (err, res) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/cup.coffee');
+        t.equal(res, path.join(dir, 'cup.coffee'));
     });
-    
-    resolve('./cup.coffee', { basedir : dir }, function (err, res) {
+
+    resolve('./cup.coffee', { basedir: dir }, function (err, res) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/cup.coffee');
+        t.equal(res, path.join(dir, 'cup.coffee'));
     });
-    
-    resolve('./cup', { basedir : dir, extensions : [ '.js' ] },
-    function (err, res) {
+
+    resolve('./cup', { basedir: dir, extensions: ['.js'] }, function (err, res) {
         t.equal(err.message, "Cannot find module './cup' from '" + path.resolve(dir) + "'");
+        t.equal(err.code, 'MODULE_NOT_FOUND');
     });
 });
 
 test('mug', function (t) {
     t.plan(3);
-    var dir = __dirname + '/resolver';
-    
-    resolve('./mug', { basedir : dir }, function (err, res) {
+    var dir = path.join(__dirname, 'resolver');
+
+    resolve('./mug', { basedir: dir }, function (err, res) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/mug.js');
+        t.equal(res, path.join(dir, 'mug.js'));
     });
-    
-    resolve('./mug', { basedir : dir, extensions : [ '.coffee', '.js' ] },
-    function (err, res) {
+
+    resolve('./mug', { basedir: dir, extensions: ['.coffee', '.js'] }, function (err, res) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/mug.coffee');
+        t.equal(res, path.join(dir, '/mug.coffee'));
     });
-    
-    resolve('./mug', { basedir : dir, extensions : [ '.js', '.coffee' ] },
-    function (err, res) {
-        t.equal(res, dir + '/mug.js');
+
+    resolve('./mug', { basedir: dir, extensions: ['.js', '.coffee'] }, function (err, res) {
+        t.equal(res, path.join(dir, '/mug.js'));
     });
 });
 
 test('other path', function (t) {
-    t.plan(4);
-    var resolverDir = __dirname + '/resolver';
-    var dir = resolverDir + '/bar';
-    var otherDir = resolverDir + '/other_path';
-    
-    resolve('root', { basedir : dir, paths: [otherDir] }, function (err, res) {
+    t.plan(6);
+    var resolverDir = path.join(__dirname, 'resolver');
+    var dir = path.join(resolverDir, 'bar');
+    var otherDir = path.join(resolverDir, 'other_path');
+
+    resolve('root', { basedir: dir, paths: [otherDir] }, function (err, res) {
         if (err) t.fail(err);
-        t.equal(res, resolverDir + '/other_path/root.js');
+        t.equal(res, path.join(resolverDir, 'other_path/root.js'));
     });
-    
-    resolve('lib/other-lib', { basedir : dir, paths: [otherDir] },
-    function (err, res) {
+
+    resolve('lib/other-lib', { basedir: dir, paths: [otherDir] }, function (err, res) {
         if (err) t.fail(err);
-        t.equal(res, resolverDir + '/other_path/lib/other-lib.js');
+        t.equal(res, path.join(resolverDir, 'other_path/lib/other-lib.js'));
     });
-    
-    resolve('root', { basedir : dir, }, function (err, res) {
+
+    resolve('root', { basedir: dir }, function (err, res) {
         t.equal(err.message, "Cannot find module 'root' from '" + path.resolve(dir) + "'");
+        t.equal(err.code, 'MODULE_NOT_FOUND');
     });
-    
-    resolve('zzz', { basedir : dir, paths: [otherDir] }, function (err, res) {
+
+    resolve('zzz', { basedir: dir, paths: [otherDir] }, function (err, res) {
         t.equal(err.message, "Cannot find module 'zzz' from '" + path.resolve(dir) + "'");
+        t.equal(err.code, 'MODULE_NOT_FOUND');
     });
 });
 
 test('incorrect main', function (t) {
-    t.plan(1)
+    t.plan(1);
 
-    var resolverDir = __dirname + '/resolver';
-    var dir = resolverDir + '/incorrect_main';
+    var resolverDir = path.join(__dirname, 'resolver');
+    var dir = path.join(resolverDir, 'incorrect_main');
 
-    resolve('./incorrect_main', { basedir : resolverDir }, function (err, res, pkg) {
+    resolve('./incorrect_main', { basedir: resolverDir }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, dir + '/index.js');
+        t.equal(res, path.join(dir, 'index.js'));
     });
 });
 
 test('without basedir', function (t) {
     t.plan(1);
 
-    var dir = __dirname + '/resolver/without_basedir';
-    var tester = require(dir + '/main.js');
+    var dir = path.join(__dirname, 'resolver/without_basedir');
+    var tester = require(path.join(dir, 'main.js'));
 
-    tester(t, function (err, res, pkg){
+    tester(t, function (err, res, pkg) {
         if (err) {
-	  t.fail(err);
-	} else {
-          t.equal(res, dir + '/node_modules/mymodule.js');
-	}
+            t.fail(err);
+        } else {
+            t.equal(res, path.join(dir, 'node_modules/mymodule.js'));
+        }
     });
 });
 
 test('#25: node modules with the same name as node stdlib modules', function (t) {
     t.plan(1);
 
-    var resolverDir = __dirname + '/resolver/punycode';
+    var resolverDir = path.join(__dirname, 'resolver/punycode');
 
-    resolve('punycode', { basedir : resolverDir }, function (err, res, pkg) {
+    resolve('punycode', { basedir: resolverDir }, function (err, res, pkg) {
         if (err) t.fail(err);
-        t.equal(res, resolverDir + '/node_modules/punycode/index.js');
+        t.equal(res, path.join(resolverDir, 'node_modules/punycode/index.js'));
+    });
+});
+
+test('#52 - incorrectly resolves module-paths like "./someFolder/" when there is a file of the same name', function (t) {
+    t.plan(2);
+
+    var dir = path.join(__dirname, 'resolver');
+
+    resolve('./foo', { basedir: path.join(dir, 'same_names') }, function (err, res, pkg) {
+        if (err) t.fail(err);
+        t.equal(res, path.join(dir, 'same_names/foo.js'));
+    });
+
+    resolve('./foo/', { basedir: path.join(dir, 'same_names') }, function (err, res, pkg) {
+        if (err) t.fail(err);
+        t.equal(res, path.join(dir, 'same_names/foo/index.js'));
+    });
+});
+
+test('async: #121 - treating an existing file as a dir when no basedir', function (t) {
+    var testFile = path.basename(__filename);
+
+    t.test('sanity check', function (st) {
+        st.plan(1);
+        resolve('./' + testFile, function (err, res, pkg) {
+            if (err) t.fail(err);
+            st.equal(res, __filename, 'sanity check');
+        });
+    });
+
+    t.test('with a fake directory', function (st) {
+        st.plan(4);
+
+        resolve('./' + testFile + '/blah', function (err, res, pkg) {
+            st.ok(err, 'there is an error');
+            st.notOk(res, 'no result');
+
+            st.equal(err && err.code, 'MODULE_NOT_FOUND', 'error code matches require.resolve');
+            st.equal(
+                err && err.message,
+                'Cannot find module \'./' + testFile + '/blah\' from \'' + __dirname + '\'',
+                'can not find nonexistent module'
+            );
+            st.end();
+        });
+    });
+
+    t.end();
+});
+
+test('async dot main', function (t) {
+    var start = new Date();
+    t.plan(3);
+    resolve('./resolver/dot_main', function (err, ret) {
+        t.notOk(err);
+        t.equal(ret, path.join(__dirname, 'resolver/dot_main/index.js'));
+        t.ok(new Date() - start < 50, 'resolve.sync timedout');
+        t.end();
+    });
+});
+
+test('async dot slash main', function (t) {
+    var start = new Date();
+    t.plan(3);
+    resolve('./resolver/dot_slash_main', function (err, ret) {
+        t.notOk(err);
+        t.equal(ret, path.join(__dirname, 'resolver/dot_slash_main/index.js'));
+        t.ok(new Date() - start < 50, 'resolve.sync timedout');
+        t.end();
     });
 });
diff --git a/test/resolver/baz/package.json b/test/resolver/baz/package.json
index 6b81dcd..c41e4db 100644
--- a/test/resolver/baz/package.json
+++ b/test/resolver/baz/package.json
@@ -1,3 +1,3 @@
 {
-    "main" : "quux.js"
+    "main": "quux.js"
 }
diff --git a/test/resolver/dot_main/index.js b/test/resolver/dot_main/index.js
new file mode 100644
index 0000000..bd816ea
--- /dev/null
+++ b/test/resolver/dot_main/index.js
@@ -0,0 +1 @@
+module.exports = 1;
diff --git a/test/resolver/dot_main/package.json b/test/resolver/dot_main/package.json
new file mode 100644
index 0000000..d7f4fc8
--- /dev/null
+++ b/test/resolver/dot_main/package.json
@@ -0,0 +1,3 @@
+{
+    "main": "."
+}
diff --git a/test/resolver/dot_slash_main/index.js b/test/resolver/dot_slash_main/index.js
new file mode 100644
index 0000000..bd816ea
--- /dev/null
+++ b/test/resolver/dot_slash_main/index.js
@@ -0,0 +1 @@
+module.exports = 1;
diff --git a/test/resolver/dot_slash_main/package.json b/test/resolver/dot_slash_main/package.json
new file mode 100644
index 0000000..f51287b
--- /dev/null
+++ b/test/resolver/dot_slash_main/package.json
@@ -0,0 +1,3 @@
+{
+    "main": "./"
+}
diff --git a/test/resolver/incorrect_main/package.json b/test/resolver/incorrect_main/package.json
index 1592ed3..b718804 100644
--- a/test/resolver/incorrect_main/package.json
+++ b/test/resolver/incorrect_main/package.json
@@ -1,3 +1,3 @@
 {
-    "main" : "wrong.js"
+    "main": "wrong.js"
 }
diff --git a/test/resolver/same_names/foo.js b/test/resolver/same_names/foo.js
new file mode 100644
index 0000000..888cae3
--- /dev/null
+++ b/test/resolver/same_names/foo.js
@@ -0,0 +1 @@
+module.exports = 42;
diff --git a/test/resolver/same_names/foo/index.js b/test/resolver/same_names/foo/index.js
new file mode 100644
index 0000000..bd816ea
--- /dev/null
+++ b/test/resolver/same_names/foo/index.js
@@ -0,0 +1 @@
+module.exports = 1;
diff --git a/test/resolver/symlinked/.gitignore b/test/resolver/symlinked/.gitignore
new file mode 100644
index 0000000..f23f892
--- /dev/null
+++ b/test/resolver/symlinked/.gitignore
@@ -0,0 +1 @@
+symlink
diff --git a/test/resolver/symlinked/_/.gitignore b/test/resolver/symlinked/_/.gitignore
new file mode 100644
index 0000000..cf4bab9
--- /dev/null
+++ b/test/resolver/symlinked/_/.gitignore
@@ -0,0 +1 @@
+!node_modules
diff --git a/test/resolver/symlinked/_/node_modules/foo.js b/test/resolver/symlinked/_/node_modules/foo.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/resolver/symlinked/_/symlink_target/.gitkeep b/test/resolver/symlinked/_/symlink_target/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/test/resolver/without_basedir/main.js b/test/resolver/without_basedir/main.js
index 5f211e9..5b31975 100644
--- a/test/resolver/without_basedir/main.js
+++ b/test/resolver/without_basedir/main.js
@@ -1,6 +1,5 @@
-resolve = require('../../../');
-
-module.exports = function(t, cb) {
-  resolve('mymodule', null, cb);
-}
+var resolve = require('../../../');
 
+module.exports = function (t, cb) {
+    resolve('mymodule', null, cb);
+};
diff --git a/test/resolver_sync.js b/test/resolver_sync.js
index 5982531..8e33dca 100644
--- a/test/resolver_sync.js
+++ b/test/resolver_sync.js
@@ -1,180 +1,267 @@
+var path = require('path');
 var test = require('tape');
 var resolve = require('../');
 
 test('foo', function (t) {
-    var dir = __dirname + '/resolver';
-    
+    var dir = path.join(__dirname, 'resolver');
+
     t.equal(
-        resolve.sync('./foo', { basedir : dir }),
-        dir + '/foo.js'
+        resolve.sync('./foo', { basedir: dir }),
+        path.join(dir, 'foo.js')
     );
-    
+
     t.equal(
-        resolve.sync('./foo.js', { basedir : dir }),
-        dir + '/foo.js'
+        resolve.sync('./foo.js', { basedir: dir }),
+        path.join(dir, 'foo.js')
     );
-    
+
     t.throws(function () {
-        resolve.sync('foo', { basedir : dir });
+        resolve.sync('foo', { basedir: dir });
     });
-    
+
     t.end();
 });
 
 test('bar', function (t) {
-    var dir = __dirname + '/resolver';
-    
+    var dir = path.join(__dirname, 'resolver');
+
     t.equal(
-        resolve.sync('foo', { basedir : dir + '/bar' }),
-        dir + '/bar/node_modules/foo/index.js'
+        resolve.sync('foo', { basedir: path.join(dir, 'bar') }),
+        path.join(dir, 'bar/node_modules/foo/index.js')
     );
     t.end();
 });
 
 test('baz', function (t) {
-    var dir = __dirname + '/resolver';
-    
+    var dir = path.join(__dirname, 'resolver');
+
     t.equal(
-        resolve.sync('./baz', { basedir : dir }),
-        dir + '/baz/quux.js'
+        resolve.sync('./baz', { basedir: dir }),
+        path.join(dir, 'baz/quux.js')
     );
     t.end();
 });
 
 test('biz', function (t) {
-    var dir = __dirname + '/resolver/biz/node_modules';
+    var dir = path.join(__dirname, 'resolver/biz/node_modules');
     t.equal(
-        resolve.sync('./grux', { basedir : dir }),
-        dir + '/grux/index.js'
+        resolve.sync('./grux', { basedir: dir }),
+        path.join(dir, 'grux/index.js')
     );
-    
+
     t.equal(
-        resolve.sync('tiv', { basedir : dir + '/grux' }),
-        dir + '/tiv/index.js'
+        resolve.sync('tiv', { basedir: path.join(dir, 'grux') }),
+        path.join(dir, 'tiv/index.js')
     );
-    
+
     t.equal(
-        resolve.sync('grux', { basedir : dir + '/tiv' }),
-        dir + '/grux/index.js'
+        resolve.sync('grux', { basedir: path.join(dir, 'tiv') }),
+        path.join(dir, 'grux/index.js')
     );
     t.end();
 });
 
 test('normalize', function (t) {
-    var dir = __dirname + '/resolver/biz/node_modules/grux';
+    var dir = path.join(__dirname, 'resolver/biz/node_modules/grux');
     t.equal(
-        resolve.sync('../grux', { basedir : dir }),
-        dir + '/index.js'
+        resolve.sync('../grux', { basedir: dir }),
+        path.join(dir, 'index.js')
     );
     t.end();
 });
 
 test('cup', function (t) {
-    var dir = __dirname + '/resolver';
+    var dir = path.join(__dirname, 'resolver');
     t.equal(
         resolve.sync('./cup', {
-            basedir : dir,
-            extensions : [ '.js', '.coffee' ]
+            basedir: dir,
+            extensions: ['.js', '.coffee']
         }),
-        dir + '/cup.coffee'
+        path.join(dir, 'cup.coffee')
     );
-    
+
     t.equal(
-        resolve.sync('./cup.coffee', {
-            basedir : dir
-        }),
-        dir + '/cup.coffee'
+        resolve.sync('./cup.coffee', { basedir: dir }),
+        path.join(dir, 'cup.coffee')
     );
-    
+
     t.throws(function () {
         resolve.sync('./cup', {
-            basedir : dir,
-            extensions : [ '.js' ]
-        })
+            basedir: dir,
+            extensions: ['.js']
+        });
     });
-    
+
     t.end();
 });
 
 test('mug', function (t) {
-    var dir = __dirname + '/resolver';
+    var dir = path.join(__dirname, 'resolver');
     t.equal(
-        resolve.sync('./mug', { basedir : dir }),
-        dir + '/mug.js'
+        resolve.sync('./mug', { basedir: dir }),
+        path.join(dir, 'mug.js')
     );
-    
+
     t.equal(
         resolve.sync('./mug', {
-            basedir : dir,
-            extensions : [ '.coffee', '.js' ]
+            basedir: dir,
+            extensions: ['.coffee', '.js']
         }),
-        dir + '/mug.coffee'
+        path.join(dir, 'mug.coffee')
     );
-    
+
     t.equal(
         resolve.sync('./mug', {
-            basedir : dir,
-            extensions : [ '.js', '.coffee' ]
+            basedir: dir,
+            extensions: ['.js', '.coffee']
         }),
-        dir + '/mug.js'
+        path.join(dir, 'mug.js')
     );
-    
+
     t.end();
 });
 
 test('other path', function (t) {
-    var resolverDir = __dirname + '/resolver';
-    var dir = resolverDir + '/bar';
-    var otherDir = resolverDir + '/other_path';
+    var resolverDir = path.join(__dirname, 'resolver');
+    var dir = path.join(resolverDir, 'bar');
+    var otherDir = path.join(resolverDir, 'other_path');
 
-    var path = require('path');
-    
     t.equal(
         resolve.sync('root', {
-            basedir : dir,
-            paths: [otherDir] }),
-        resolverDir + '/other_path/root.js'
+            basedir: dir,
+            paths: [otherDir]
+        }),
+        path.join(resolverDir, 'other_path/root.js')
     );
-    
+
     t.equal(
         resolve.sync('lib/other-lib', {
-            basedir : dir,
-            paths: [otherDir] }),
-        resolverDir + '/other_path/lib/other-lib.js'
+            basedir: dir,
+            paths: [otherDir]
+        }),
+        path.join(resolverDir, 'other_path/lib/other-lib.js')
     );
 
     t.throws(function () {
-        resolve.sync('root', { basedir : dir, });
+        resolve.sync('root', { basedir: dir });
     });
-    
+
     t.throws(function () {
         resolve.sync('zzz', {
-            basedir : dir,
-            paths: [otherDir] });
+            basedir: dir,
+            paths: [otherDir]
+        });
     });
-    
+
     t.end();
 });
 
 test('incorrect main', function (t) {
-    var resolverDir = __dirname + '/resolver';
-    var dir = resolverDir + '/incorrect_main';
+    var resolverDir = path.join(__dirname, 'resolver');
+    var dir = path.join(resolverDir, 'incorrect_main');
 
     t.equal(
-        resolve.sync('./incorrect_main', { basedir : resolverDir }),
-        dir + '/index.js'
-    )
+        resolve.sync('./incorrect_main', { basedir: resolverDir }),
+        path.join(dir, 'index.js')
+    );
 
-    t.end()
+    t.end();
 });
 
 test('#25: node modules with the same name as node stdlib modules', function (t) {
-    var resolverDir = __dirname + '/resolver/punycode';
+    var resolverDir = path.join(__dirname, 'resolver/punycode');
+
+    t.equal(
+        resolve.sync('punycode', { basedir: resolverDir }),
+        path.join(resolverDir, 'node_modules/punycode/index.js')
+    );
+
+    t.end();
+});
 
+var stubStatSync = function stubStatSync(fn) {
+    var fs = require('fs');
+    var statSync = fs.statSync;
+    try {
+        fs.statSync = function () {
+            throw new EvalError('Unknown Error');
+        };
+        return fn();
+    } finally {
+        fs.statSync = statSync;
+    }
+};
+
+test('#79 - re-throw non ENOENT errors from stat', function (t) {
+    var dir = path.join(__dirname, 'resolver');
+
+    stubStatSync(function () {
+        t.throws(function () {
+            resolve.sync('foo', { basedir: dir });
+        }, /Unknown Error/);
+    });
+
+    t.end();
+});
+
+test('#52 - incorrectly resolves module-paths like "./someFolder/" when there is a file of the same name', function (t) {
+    var dir = path.join(__dirname, 'resolver');
+
+    t.equal(
+        resolve.sync('./foo', { basedir: path.join(dir, 'same_names') }),
+        path.join(dir, 'same_names/foo.js')
+    );
     t.equal(
-        resolve.sync('punycode', { basedir : resolverDir }),
-        resolverDir + '/node_modules/punycode/index.js'
-    )
+        resolve.sync('./foo/', { basedir: path.join(dir, 'same_names') }),
+        path.join(dir, 'same_names/foo/index.js')
+    );
+    t.end();
+});
+
+test('sync: #121 - treating an existing file as a dir when no basedir', function (t) {
+    var testFile = path.basename(__filename);
 
-    t.end()
+    t.test('sanity check', function (st) {
+        st.equal(
+            resolve.sync('./' + testFile),
+            __filename,
+            'sanity check'
+        );
+        st.end();
+    });
+
+    t.test('with a fake directory', function (st) {
+        function run() { return resolve.sync('./' + testFile + '/blah'); }
+
+        st.throws(run, 'throws an error');
+
+        try {
+            run();
+        } catch (e) {
+            st.equal(e.code, 'MODULE_NOT_FOUND', 'error code matches require.resolve');
+            st.equal(
+                e.message,
+                'Cannot find module \'./' + testFile + '/blah\' from \'' + __dirname + '\'',
+                'can not find nonexistent module'
+            );
+        }
+
+        st.end();
+    });
+
+    t.end();
+});
+
+test('sync dot main', function (t) {
+    var start = new Date();
+    t.equal(resolve.sync('./resolver/dot_main'), path.join(__dirname, 'resolver/dot_main/index.js'));
+    t.ok(new Date() - start < 50, 'resolve.sync timedout');
+    t.end();
+});
+
+test('sync dot slash main', function (t) {
+    var start = new Date();
+    t.equal(resolve.sync('./resolver/dot_slash_main'), path.join(__dirname, 'resolver/dot_slash_main/index.js'));
+    t.ok(new Date() - start < 50, 'resolve.sync timedout');
+    t.end();
 });
diff --git a/test/subdirs.js b/test/subdirs.js
index 957abfe..b7b8450 100644
--- a/test/subdirs.js
+++ b/test/subdirs.js
@@ -4,7 +4,7 @@ var path = require('path');
 
 test('subdirs', function (t) {
     t.plan(2);
-    
+
     var dir = path.join(__dirname, '/subdirs');
     resolve('a/b/c/x.json', { basedir: dir }, function (err, res) {
         t.ifError(err);
diff --git a/test/symlinks.js b/test/symlinks.js
new file mode 100644
index 0000000..544a023
--- /dev/null
+++ b/test/symlinks.js
@@ -0,0 +1,54 @@
+var path = require('path');
+var fs = require('fs');
+var test = require('tape');
+var resolve = require('../');
+
+var symlinkDir = path.join(__dirname, 'resolver', 'symlinked', 'symlink');
+try {
+    fs.unlinkSync(symlinkDir);
+} catch (err) {}
+try {
+    fs.symlinkSync('./_/symlink_target', symlinkDir, 'dir');
+} catch (err) {
+    // if fails then it is probably on Windows and lets try to create a junction
+    fs.symlinkSync(path.join(__dirname, 'resolver', 'symlinked', '_', 'symlink_target') + '\\', symlinkDir, 'junction');
+}
+
+test('symlink', function (t) {
+    t.plan(1);
+
+    resolve('foo', { basedir: symlinkDir, preserveSymlinks: false }, function (err, res, pkg) {
+        if (err) t.fail(err);
+        t.equal(res, path.join(__dirname, 'resolver', 'symlinked', '_', 'node_modules', 'foo.js'));
+    });
+});
+
+test('sync symlink when preserveSymlinks = true', function (t) {
+    t.plan(4);
+
+    resolve('foo', { basedir: symlinkDir }, function (err, res, pkg) {
+        t.ok(err, 'there is an error');
+        t.notOk(res, 'no result');
+
+        t.equal(err && err.code, 'MODULE_NOT_FOUND', 'error code matches require.resolve');
+        t.equal(
+            err && err.message,
+            'Cannot find module \'foo\' from \'' + symlinkDir + '\'',
+            'can not find nonexistent module'
+        );
+    });
+});
+
+test('sync symlink', function (t) {
+    var start = new Date();
+    t.equal(resolve.sync('foo', { basedir: symlinkDir, preserveSymlinks: false }), path.join(__dirname, 'resolver', 'symlinked', '_', 'node_modules', 'foo.js'));
+    t.ok(new Date() - start < 50, 'resolve.sync timedout');
+    t.end();
+});
+
+test('sync symlink when preserveSymlinks = true', function (t) {
+    t.throws(function () {
+        resolve.sync('foo', { basedir: symlinkDir });
+    }, /Cannot find module 'foo'/);
+    t.end();
+});

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-resolve.git



More information about the Pkg-javascript-commits mailing list