This patch removes require.async from nodejs.
1. It complicated the code unnecessarily.
2. Everyone uses sync require anyway.
3. It's got a lot of weird edge cases when mixed with sync require.
4. It is many months behind the commonjs spec anyhow.
This patch standardises the load order for modules. Highest priority is trying to load exactly the file the user specified, followed by native extensions, followed by registered extra extensions, etc.
In full, if we require('foo') having registered '.coffee' as an alternative extension, we try and load the following files in order:
foo
foo.js
foo.node
foo.coffee
foo/index.js
foo/index.node
foo/index.coffee
This patch replaces the path.exists check for module loading with a call to
fs.statSync (or fs.stat for require.async) which ensures that it's not trying
to load a directory.
This is ever so slightly less efficient than caching based on ID, since the
filename has to be looked up before we can check the cache. However, it's
the most minimal approach possible to get this change in place. Since
require() is a blocking startup-time operation anyway, a bit of slowness is
not a huge problem.
A test involving require.paths modification and absolute loading. Here's the
gist of it.
Files: /p1/foo.js /p2/foo.js
1. Add "/p1" to require.paths.
2. foo1 = require("foo")
3. assert foo1 === require("/p1/foo") (fail)
4. Remove /p1 from require.paths.
5. Add /p2 to require.paths.
6. foo2 = require("foo")
7. assert foo1 !== foo2 (fail)
8. assert foo2 === require("/p2/foo") (fail)
It's an edge case, but it affects how dependencies are mapped by npm.
If your module requires foo-1.2.3, and my module requires foo-2.3.4,
then you should expect to have require("foo") give you foo-1.2.3, and
I should expect require("foo") to give me foo-2.3.4. However, with
module ID based caching, if your code loads *first*, then your "foo"
is THE "foo", so I'll get your version instead of mine.
It hasn't yet been a problem, but only because there are so few
modules, and everyone pretty much uses the latest version all the
time. But as things start to get to the 1.x and 2.x versions, it'll
be an issue, I'm sure. Dependency hell isn't fun, so this is a way to
avoid it before it strikes.
It seems that the current __filename module global is mainly used to
determine the directory the current module is in. To make that
easier, this patch adds support for a __dirname module global
directly.
include() should not be used by libraries because it will pollute the global
namespace. To discourage this behavior and bring Node more in-line with
the current CommonJS module system, include() is removed.
Small scripts like unit tests often times do want to pollute the global
namespace for ease. To avoid the boiler plate code of
var x = require("/x.js");
var foo = x.foo;
var bar = x.bar;
The function node.mixin() is stolen from jQuery's jQuery.extend. So that it
can be written:
node.mixin(require("/x.js"));
Reference:
http://docs.jquery.com/Utilities/jQuery.extendhttp://groups.google.com/group/nodejs/browse_thread/thread/f9ac83e5c11e7e87
onExit() is similar to the onLoad() callback. onExit() is called on each
module just before the process exits. This can be used to check state in
unit tests, but not to perform I/O. The process will forcibly exit as soon
as all of the onExit callbacks are made.
There is one major API change in the refactor: filename extensions are now
required when requiring or including modules.
Added extra test to test-module-loading.js.