Browse Source

Simplified module system

createModule got removed as it was unnecessary and caused issues by
doing its own cache checks independent of loadModule. Internal modules
are now the only globally cached modules, all other modules are only
cached by inheriting their parent modules cache.

Credits: Module specific cache and a few other diffs by Blaine Cook

431662d25c
http://romeda.org/blog/2010/01/hot-code-loading-in-nodejs.html
http://thread.gmane.org/gmane.comp.lang.javascript.nodejs/1994
v0.7.4-release
Felix Geisendörfer 15 years ago
committed by Ryan Dahl
parent
commit
b73f61a137
  1. 59
      src/node.js
  2. 1
      test/mjsunit/test-module-loading.js

59
src/node.js

@ -41,11 +41,20 @@ node.dns.createConnection = removed("node.dns.createConnection() has moved. Use
// Module // Module
var internalModuleCache = {};
function Module (id, parent) { function Module (id, parent) {
this.id = id; this.id = id;
this.exports = {}; this.exports = {};
this.parent = parent; this.parent = parent;
this.moduleCache = {};
if (parent) {
process.mixin(this.moduleCache, parent.moduleCache);
this.moduleCache[parent.id] = parent;
}
this.filename = null; this.filename = null;
this.loaded = false; this.loaded = false;
this.loadPromise = null; this.loadPromise = null;
@ -53,23 +62,11 @@ function Module (id, parent) {
this.children = []; this.children = [];
}; };
var moduleCache = {};
function createModule (id, parent) {
if (id in moduleCache) {
debug("found " + JSON.stringify(id) + " in cache");
return moduleCache[id];
}
debug("didn't found " + JSON.stringify(id) + " in cache. creating new module");
var m = new Module(id, parent);
moduleCache[id] = m;
return m;
};
function createInternalModule (id, constructor) { function createInternalModule (id, constructor) {
var m = createModule(id); var m = new Module(id);
constructor(m.exports); constructor(m.exports);
m.loaded = true; m.loaded = true;
internalModuleCache[id] = m;
return m; return m;
}; };
@ -803,11 +800,7 @@ function findModulePath (id, dirs, callback) {
searchLocations(); searchLocations();
} }
function loadModule (request, parent) { function resolveModulePath(request, parent) {
// This is the promise which is actually returned from require.async()
var loadPromise = new events.Promise();
// debug("loadModule REQUEST " + (request) + " parent: " + JSON.stringify(parent));
var id, paths; var id, paths;
if (request.charAt(0) == "." && (request.charAt(1) == "/" || request.charAt(1) == ".")) { if (request.charAt(0) == "." && (request.charAt(1) == "/" || request.charAt(1) == ".")) {
@ -823,21 +816,33 @@ function loadModule (request, parent) {
paths = process.paths; paths = process.paths;
} }
if (id in moduleCache) { return [id, paths];
}
function loadModule (request, parent) {
var
// The promise returned from require.async()
loadPromise = new events.Promise(),
resolvedModule = resolveModulePath(request, parent),
id = resolvedModule[0],
paths = resolvedModule[1];
// debug("loadModule REQUEST " + (request) + " parent: " + JSON.stringify(parent));
var cachedModule = internalModuleCache[id] || parent.moduleCache[id];
if (cachedModule) {
debug("found " + JSON.stringify(id) + " in cache"); debug("found " + JSON.stringify(id) + " in cache");
// In cache process.nextTick(function() {
var module = moduleCache[id]; loadPromise.emitSuccess(cachedModule.exports);
process.nextTick(function () {
loadPromise.emitSuccess(module.exports);
}); });
} else { } else {
debug("looking for " + JSON.stringify(id) + " in " + JSON.stringify(paths)); debug("looking for " + JSON.stringify(id) + " in " + JSON.stringify(paths));
// Not in cache // Not in cache
findModulePath(request, paths, function (filename) { findModulePath(request, paths, function (filename) {
if (!filename) { if (!filename) {
loadPromise.emitError(new Error("Cannot find module '" + request + "'")); loadPromise.emitError(new Error("Cannot find module '" + request + "'"));
} else { } else {
var module = createModule(id, parent); var module = new Module(id, parent);
module.load(filename, loadPromise); module.load(filename, loadPromise);
} }
}); });
@ -978,7 +983,7 @@ if (process.argv[1].charAt(0) != "/" && !(/^http:\/\//).exec(process.argv[1])) {
} }
// Load the main module--the command line argument. // Load the main module--the command line argument.
process.mainModule = createModule("."); process.mainModule = new Module(".");
var loadPromise = new events.Promise(); var loadPromise = new events.Promise();
process.mainModule.load(process.argv[1], loadPromise); process.mainModule.load(process.argv[1], loadPromise);

1
test/mjsunit/test-module-loading.js

@ -41,7 +41,6 @@ assert.notEqual(one.hello, two.hello);
debug("test cycles containing a .. path"); debug("test cycles containing a .. path");
var root = require("./fixtures/cycles/root"), var root = require("./fixtures/cycles/root"),
foo = require("./fixtures/cycles/folder/foo"); foo = require("./fixtures/cycles/folder/foo");
assert.equal(root.foo, foo);
assert.equal(root.sayHello(), root.hello); assert.equal(root.sayHello(), root.hello);
var errorThrown = false; var errorThrown = false;

Loading…
Cancel
Save