Browse Source

Standardise module load order for native and registered file extensions.

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
v0.7.4-release
Nick Stenning 15 years ago
committed by Ryan Dahl
parent
commit
0a3eff8021
  1. 38
      lib/module.js
  2. 1
      test/fixtures/module-load-order/file1
  3. 1
      test/fixtures/module-load-order/file1.js
  4. 1
      test/fixtures/module-load-order/file1.node
  5. 1
      test/fixtures/module-load-order/file1.reg
  6. 1
      test/fixtures/module-load-order/file1.reg2
  7. 1
      test/fixtures/module-load-order/file2.js
  8. 1
      test/fixtures/module-load-order/file2.node
  9. 1
      test/fixtures/module-load-order/file2.reg
  10. 1
      test/fixtures/module-load-order/file2.reg2
  11. 1
      test/fixtures/module-load-order/file2/index.js
  12. 1
      test/fixtures/module-load-order/file2/index.node
  13. 1
      test/fixtures/module-load-order/file2/index.reg
  14. 1
      test/fixtures/module-load-order/file2/index.reg2
  15. 1
      test/fixtures/module-load-order/file3.node
  16. 1
      test/fixtures/module-load-order/file3.reg
  17. 1
      test/fixtures/module-load-order/file3.reg2
  18. 1
      test/fixtures/module-load-order/file3/index.js
  19. 1
      test/fixtures/module-load-order/file3/index.node
  20. 1
      test/fixtures/module-load-order/file3/index.reg
  21. 1
      test/fixtures/module-load-order/file3/index.reg2
  22. 1
      test/fixtures/module-load-order/file4.reg
  23. 1
      test/fixtures/module-load-order/file4.reg2
  24. 1
      test/fixtures/module-load-order/file4/index.js
  25. 1
      test/fixtures/module-load-order/file4/index.node
  26. 1
      test/fixtures/module-load-order/file4/index.reg
  27. 1
      test/fixtures/module-load-order/file4/index.reg2
  28. 1
      test/fixtures/module-load-order/file5.reg2
  29. 1
      test/fixtures/module-load-order/file5/index.js
  30. 1
      test/fixtures/module-load-order/file5/index.node
  31. 1
      test/fixtures/module-load-order/file5/index.reg
  32. 1
      test/fixtures/module-load-order/file5/index.reg2
  33. 1
      test/fixtures/module-load-order/file6/index.js
  34. 1
      test/fixtures/module-load-order/file6/index.node
  35. 1
      test/fixtures/module-load-order/file6/index.reg
  36. 1
      test/fixtures/module-load-order/file6/index.reg2
  37. 1
      test/fixtures/module-load-order/file7/index.node
  38. 1
      test/fixtures/module-load-order/file7/index.reg
  39. 1
      test/fixtures/module-load-order/file7/index.reg2
  40. 1
      test/fixtures/module-load-order/file8/index.reg
  41. 1
      test/fixtures/module-load-order/file8/index.reg2
  42. 1
      test/fixtures/module-load-order/file9/index.reg2
  43. 30
      test/simple/test-module-loading.js

38
lib/module.js

@ -59,8 +59,6 @@ function requireNative (id) {
return loadNative(id).exports; return loadNative(id).exports;
} }
// Event // Event
var eventsFn = process.compile("(function (exports) {" + natives.events + "\n})", var eventsFn = process.compile("(function (exports) {" + natives.events + "\n})",
@ -93,6 +91,8 @@ if (process.env["NODE_PATH"]) {
modulePaths = process.env["NODE_PATH"].split(":").concat(modulePaths); modulePaths = process.env["NODE_PATH"].split(":").concat(modulePaths);
} }
var moduleNativeExtensions = ['js', 'node'];
/* Sync unless callback given */ /* Sync unless callback given */
function findModulePath (id, dirs, callback) { function findModulePath (id, dirs, callback) {
process.assert(dirs.constructor == Array); process.assert(dirs.constructor == Array);
@ -106,10 +106,6 @@ function findModulePath (id, dirs, callback) {
return; return;
} }
if (/\.(js|node)$/.exec(id)) {
throw new Error("No longer accepting filename extension in module names");
}
if (dirs.length == 0) { if (dirs.length == 0) {
if (callback) { if (callback) {
callback(); callback();
@ -126,22 +122,17 @@ function findModulePath (id, dirs, callback) {
rest = []; rest = [];
} }
var locations = [ var ext, locDirect = [], locIndex = [];
path.join(dir, id + ".js"), var extensions = moduleNativeExtensions.concat(Object.keys(extensionCache));
path.join(dir, id + ".node"),
path.join(dir, id, "index.js"),
path.join(dir, id, "index.node"),
path.join(dir, id)
];
var ext;
var extensions = Object.keys(extensionCache);
for (var i = 0, l = extensions.length; i < l; i++) { for (var i = 0, l = extensions.length; i < l; i++) {
var ext = extensions[i]; ext = extensions[i];
locations.push(path.join(dir, id + ext)); locDirect.push(path.join(dir, id + '.' + ext));
locations.push(path.join(dir, id, 'index' + ext)); locIndex.push(path.join(dir, id, 'index.' + ext));
} }
var locations = [path.join(dir, id)].concat(locDirect).concat(locIndex);
var fs = requireNative('fs'); var fs = requireNative('fs');
function searchLocations () { function searchLocations () {
@ -192,12 +183,7 @@ function resolveModulePath(request, parent) {
if (request.charAt(0) == "." && (request.charAt(1) == "/" || request.charAt(1) == ".")) { if (request.charAt(0) == "." && (request.charAt(1) == "/" || request.charAt(1) == ".")) {
// Relative request // Relative request
var exts = ['js', 'node'], ext; var exts = moduleNativeExtensions.concat(Object.keys(extensionCache));
var extensions = Object.keys(extensionCache);
for (var i = 0, l = extensions.length; i < l; i++) {
var ext = extensions[i];
exts.push(ext.slice(1));
}
var parentIdPath = path.dirname(parent.id + var parentIdPath = path.dirname(parent.id +
(path.basename(parent.filename).match(new RegExp('^index\\.(' + exts.join('|') + ')$')) ? "/." : "")); (path.basename(parent.filename).match(new RegExp('^index\\.(' + exts.join('|') + ')$')) ? "/." : ""));
@ -293,7 +279,7 @@ function registerExtension(ext, compiler) {
throw new Error('require.registerExtension: Second argument not a valid compiler function.'); throw new Error('require.registerExtension: Second argument not a valid compiler function.');
} }
extensionCache[ext] = compiler; extensionCache[ext.slice(1)] = compiler;
} }
@ -364,7 +350,7 @@ Module.prototype._compile = function (content, filename) {
content = content.replace(/^\#\!.*/, ''); content = content.replace(/^\#\!.*/, '');
// Compile content if needed // Compile content if needed
var ext = path.extname(filename); var ext = path.extname(filename).slice(1);
if (extensionCache[ext]) { if (extensionCache[ext]) {
content = extensionCache[ext](content); content = extensionCache[ext](content);
} }

1
test/fixtures/module-load-order/file1

@ -0,0 +1 @@
exports.file1 = 'file1';

1
test/fixtures/module-load-order/file1.js

@ -0,0 +1 @@
exports.file1 = 'file1.js';

1
test/fixtures/module-load-order/file1.node

@ -0,0 +1 @@
exports.file1 = 'file1.node';

1
test/fixtures/module-load-order/file1.reg

@ -0,0 +1 @@
exports.file1 = 'file1.reg';

1
test/fixtures/module-load-order/file1.reg2

@ -0,0 +1 @@
exports.file1 = 'file1.reg2';

1
test/fixtures/module-load-order/file2.js

@ -0,0 +1 @@
exports.file2 = 'file2.js';

1
test/fixtures/module-load-order/file2.node

@ -0,0 +1 @@
exports.file2 = 'file2.node';

1
test/fixtures/module-load-order/file2.reg

@ -0,0 +1 @@
exports.file2 = 'file2.reg';

1
test/fixtures/module-load-order/file2.reg2

@ -0,0 +1 @@
exports.file2 = 'file2.reg2';

1
test/fixtures/module-load-order/file2/index.js

@ -0,0 +1 @@
exports.file2 = 'file2/index.js';

1
test/fixtures/module-load-order/file2/index.node

@ -0,0 +1 @@
exports.file2 = 'file2/index.node';

1
test/fixtures/module-load-order/file2/index.reg

@ -0,0 +1 @@
exports.file2 = 'file2/index.reg';

1
test/fixtures/module-load-order/file2/index.reg2

@ -0,0 +1 @@
exports.file2 = 'file2/index.reg2';

1
test/fixtures/module-load-order/file3.node

@ -0,0 +1 @@
exports.file3 = 'file3.node';

1
test/fixtures/module-load-order/file3.reg

@ -0,0 +1 @@
exports.file3 = 'file3.reg';

1
test/fixtures/module-load-order/file3.reg2

@ -0,0 +1 @@
exports.file3 = 'file3.reg2';

1
test/fixtures/module-load-order/file3/index.js

@ -0,0 +1 @@
exports.file3 = 'file3/index.js';

1
test/fixtures/module-load-order/file3/index.node

@ -0,0 +1 @@
exports.file3 = 'file3/index.node';

1
test/fixtures/module-load-order/file3/index.reg

@ -0,0 +1 @@
exports.file3 = 'file3/index.reg';

1
test/fixtures/module-load-order/file3/index.reg2

@ -0,0 +1 @@
exports.file3 = 'file3/index.reg2';

1
test/fixtures/module-load-order/file4.reg

@ -0,0 +1 @@
exports.file4 = 'file4.reg';

1
test/fixtures/module-load-order/file4.reg2

@ -0,0 +1 @@
exports.file4 = 'file4.reg2';

1
test/fixtures/module-load-order/file4/index.js

@ -0,0 +1 @@
exports.file4 = 'file4/index.js';

1
test/fixtures/module-load-order/file4/index.node

@ -0,0 +1 @@
exports.file4 = 'file4/index.node';

1
test/fixtures/module-load-order/file4/index.reg

@ -0,0 +1 @@
exports.file4 = 'file4/index.reg';

1
test/fixtures/module-load-order/file4/index.reg2

@ -0,0 +1 @@
exports.file4 = 'file4/index.reg2';

1
test/fixtures/module-load-order/file5.reg2

@ -0,0 +1 @@
exports.file5 = 'file5.reg2';

1
test/fixtures/module-load-order/file5/index.js

@ -0,0 +1 @@
exports.file5 = 'file5/index.js';

1
test/fixtures/module-load-order/file5/index.node

@ -0,0 +1 @@
exports.file5 = 'file5/index.node';

1
test/fixtures/module-load-order/file5/index.reg

@ -0,0 +1 @@
exports.file5 = 'file5/index.reg';

1
test/fixtures/module-load-order/file5/index.reg2

@ -0,0 +1 @@
exports.file5 = 'file5/index.reg2';

1
test/fixtures/module-load-order/file6/index.js

@ -0,0 +1 @@
exports.file6 = 'file6/index.js';

1
test/fixtures/module-load-order/file6/index.node

@ -0,0 +1 @@
exports.file6 = 'file6/index.node';

1
test/fixtures/module-load-order/file6/index.reg

@ -0,0 +1 @@
exports.file6 = 'file6/index.reg';

1
test/fixtures/module-load-order/file6/index.reg2

@ -0,0 +1 @@
exports.file6 = 'file6/index.reg2';

1
test/fixtures/module-load-order/file7/index.node

@ -0,0 +1 @@
exports.file7 = 'file7/index.node';

1
test/fixtures/module-load-order/file7/index.reg

@ -0,0 +1 @@
exports.file7 = 'file7/index.reg';

1
test/fixtures/module-load-order/file7/index.reg2

@ -0,0 +1 @@
exports.file7 = 'file7/index.reg2';

1
test/fixtures/module-load-order/file8/index.reg

@ -0,0 +1 @@
exports.file8 = 'file8/index.reg';

1
test/fixtures/module-load-order/file8/index.reg2

@ -0,0 +1 @@
exports.file8 = 'file8/index.reg2';

1
test/fixtures/module-load-order/file9/index.reg2

@ -0,0 +1 @@
exports.file9 = 'file9/index.reg2';

30
test/simple/test-module-loading.js

@ -123,6 +123,36 @@ require.async("../fixtures/empty", function (err, a) {
} }
}); });
// Check load order is as expected
common.debug('load order');
var loadOrder = '../fixtures/module-load-order/',
msg = "Load order incorrect.";
require.registerExtension('.reg', function(content) { return content; });
require.registerExtension('.reg2', function(content) { return content; });
assert.equal(require(loadOrder + 'file1').file1, 'file1', msg);
assert.equal(require(loadOrder + 'file2').file2, 'file2.js', msg);
try {
require(loadOrder + 'file3');
} catch (e) {
// Not a real .node module, but we know we require'd the right thing.
assert.ok(e.message.match(/^dlopen/));
assert.ok(e.message.match(/file3\.node/));
}
assert.equal(require(loadOrder + 'file4').file4, 'file4.reg', msg);
assert.equal(require(loadOrder + 'file5').file5, 'file5.reg2', msg);
assert.equal(require(loadOrder + 'file6').file6, 'file6/index.js', msg);
try {
require(loadOrder + 'file7');
} catch (e) {
assert.ok(e.message.match(/^dlopen/));
assert.ok(e.message.match(/file7\/index\.node/));
}
assert.equal(require(loadOrder + 'file8').file8, 'file8/index.reg', msg);
assert.equal(require(loadOrder + 'file9').file9, 'file9/index.reg2', msg);
process.addListener("exit", function () { process.addListener("exit", function () {
assert.equal(true, a.A instanceof Function); assert.equal(true, a.A instanceof Function);
assert.equal("A done", a.A()); assert.equal("A done", a.A());

Loading…
Cancel
Save