Browse files

Absolute path names for require() refer to node.libraryPaths

  • Loading branch information...
1 parent 5ddc4f5 commit c8b143bf30178bd8549af8a88f6a6f841fc0ae71 @ry ry committed Sep 18, 2009
View
200 src/node.js
@@ -71,6 +71,16 @@ clearInterval = clearTimeout;
// Module
+node.libraryPaths = [ node.path.join(ENV["HOME"], ".node_libraries")
+ , node.path.join(node.installPrefix, "lib/node_libraries")
+ , "/"
+ ];
+
+if (ENV["NODE_LIBRARY_PATHS"]) {
+ node.libraryPaths =
+ ENV["NODE_LIBRARY_PATHS"].split(":").concat(node.libraryPaths);
+}
+
node.loadingModules = [];
function require_async (url) {
@@ -83,49 +93,125 @@ function require (url) {
}
function include_async (url) {
- var currentModule = node.loadingModules[0];
- return currentModule.newChild(url, currentModule.target);
+ var promise = require_async(url)
+ promise.addCallback(function (t) {
+ // copy properties into global namespace.
+ for (var prop in t) {
+ if (t.hasOwnProperty(prop)) process[prop] = t[prop];
+ }
+ });
+ return promise;
}
function include (url) {
include_async(url).wait();
}
-node.Module = function (o) {
- this.parent = o.parent;
- this.target = o.target || {};
-
- if (!o.path) throw "path argument required";
-
- if (o.path.charAt(0) == "/") {
- throw "Absolute module paths are not yet supported by Node";
- }
-
- if (o.path.match(/:\/\//)) {
- this.filename = o.path;
- } else {
- var dir = o.base_directory || ".";
- this.filename = node.path.join(dir, o.path);
- }
+node.Module = function (filename, parent) {
+ node.assert(filename.charAt(0) == "/");
+ this.filename = filename;
+ this.target = {};
+ this.parent = parent;
this.loaded = false;
this.loadPromise = null;
this.exited = false;
this.children = [];
};
-node.Module.prototype.load = function (callback) {
+node.Module.cache = {};
+
+(function () {
+ function retrieveFromCache (loadPromise, fullPath, parent) {
+ var module;
+ if (fullPath in node.Module.cache) {
+ module = node.Module.cache[fullPath];
+ setTimeout(function () {
+ loadPromise.emitSuccess(module.target);
+ }, 0);
+ } else {
+ module = new node.Module(fullPath, parent);
+ node.Module.cache[fullPath] = module;
+ module.load(loadPromise);
+ }
+ }
+
+ function findPath (path, dirs, callback) {
+ node.assert(path.charAt(0) == "/");
+ node.assert(dirs.constructor == Array);
+
+ if (dirs.length == 0) {
+ callback();
+ } else {
+ var dir = dirs[0];
+ var rest = dirs.slice(1, dirs.length);
+
+ var fullPath = node.path.join(dir, path);
+ node.fs.exists(fullPath, function (doesExist) {
+ if (doesExist) {
+ callback(fullPath);
+ } else {
+ findPath(path, rest, callback);
+ }
+ });
+ }
+ }
+
+ node.loadModule = function (requestedPath, target, parent) {
+ var loadPromise = new node.Promise();
+
+ // On success copy the loaded properties into the target
+ loadPromise.addCallback(function (t) {
+ for (var prop in t) {
+ if (t.hasOwnProperty(prop)) target[prop] = t[prop];
+ }
+ });
+
+ if (!parent) {
+ // root module
+ node.assert(requestedPath.charAt(0) == "/");
+ retrieveFromCache(loadPromise, requestedPath);
+
+ } else {
+ if (requestedPath.charAt(0) == "/") {
+ // Need to find the module in node.libraryPaths
+ findPath(requestedPath, node.libraryPaths, function (fullPath) {
+ if (fullPath) {
+ retrieveFromCache(loadPromise, fullPath, parent);
+ } else {
+ loadPromise.emitError();
+ }
+ });
+
+ } else {
+ // Relative file load
+ var fullPath = node.path.join(node.path.dirname(parent.filename),
+ requestedPath);
+ retrieveFromCache(loadPromise, fullPath, parent);
+ }
+ }
+
+ return loadPromise;
+ };
+}());
+
+node.Module.prototype.load = function (loadPromise) {
+ if (this.loaded) {
+ loadPromise.emitError(new Error("Module '" + self.filename + "' is already loaded."));
+ return;
+ }
+ node.assert(!node.loadPromise);
+ this.loadPromise = loadPromise;
+
if (this.filename.match(/\.node$/)) {
- return this.loadObject(callback);
+ this.loadObject(loadPromise);
} else {
- return this.loadScript(callback);
+ this.loadScript(loadPromise);
}
};
-node.Module.prototype.loadObject = function (callback) {
+node.Module.prototype.loadObject = function (loadPromise) {
var self = this;
- var loadPromise = new node.Promise();
- self.loadPromise = loadPromise;
// XXX Not yet supporting loading from HTTP. would need to download the
// file, store it to tmp then run dlopen on it.
node.fs.exists(self.filename, function (does_exist) {
@@ -139,57 +225,28 @@ node.Module.prototype.loadObject = function (callback) {
node.exit(1);
}
});
- return loadPromise;
};
-node.Module.prototype.loadScript = function (callback) {
+node.Module.prototype.loadScript = function (loadPromise) {
var self = this;
- if (self.loaded) {
- throw "Module '" + self.filename + "' is already loaded.";
- }
+ var catPromise = node.cat(self.filename);
- var loadPromise = new node.Promise();
- node.assert(self.loadPromise === null);
- self.loadPromise = loadPromise;
-
- var cat_promise = node.cat(self.filename);
-
- cat_promise.addErrback(function () {
- node.stdio.writeError("Error reading " + self.filename + "\n");
- loadPromise.emitError();
- node.exit(1);
+ catPromise.addErrback(function () {
+ loadPromise.emitError(new Error("Error reading " + self.filename + "\n"));
});
- cat_promise.addCallback(function (content) {
+ catPromise.addCallback(function (content) {
// remove shebang
content = content.replace(/^\#\!.*/, '');
// create wrapper function
- var wrapper = "function (__filename) { "+
- " var onLoad; "+
- " var onExit; "+
- " var exports = this; "+
- content+
- "\n"+
- " this.__onLoad = onLoad;\n"+
- " this.__onExit = onExit;\n"+
- "};\n";
+ var wrapper = "function (__filename, exports) { " + content + "\n};";
var compiled_wrapper = node.compile(wrapper, self.filename);
node.loadingModules.unshift(self);
- compiled_wrapper.apply(self.target, [self.filename]);
+ compiled_wrapper.apply(self.target, [self.filename, self.target]);
node.loadingModules.shift();
- self.onLoad = self.target.__onLoad;
- self.onExit = self.target.__onExit;
- if (self.onLoad || self.onExit) {
- node.stdio.writeError( "(node) onLoad and onExit have been removed. "
- + " module load is synchronous so onLoad is unnecessary"
- + " Use process.addListener('exit') for onExit. "
- );
- node.exit(1);
- }
-
self.waitChildrenLoad(function () {
self.loaded = true;
loadPromise.emitSuccess(self.target);
@@ -198,15 +255,7 @@ node.Module.prototype.loadScript = function (callback) {
};
node.Module.prototype.newChild = function (path, target) {
- var child = new node.Module({
- target: target,
- path: path,
- base_directory: node.path.dirname(this.filename),
- parent: this
- });
- this.children.push(child);
- child.load();
- return child.loadPromise;
+ return node.loadModule(path, target, this);
};
node.Module.prototype.waitChildrenLoad = function (callback) {
@@ -227,22 +276,19 @@ node.Module.prototype.waitChildrenLoad = function (callback) {
};
(function () {
+ var cwd = node.cwd();
+
// Make ARGV[0] and ARGV[1] into full paths.
if (ARGV[0].charAt(0) != "/") {
- ARGV[0] = node.path.join(node.cwd(), ARGV[0]);
+ ARGV[0] = node.path.join(cwd, ARGV[0]);
}
if (ARGV[1].charAt(0) != "/") {
- ARGV[1] = node.path.join(node.cwd(), ARGV[1]);
+ ARGV[1] = node.path.join(cwd, ARGV[1]);
}
// Load the root module--the command line argument.
- var root_module = new node.Module({
- path: node.path.filename(ARGV[1]),
- base_directory: node.path.dirname(ARGV[1]),
- target: this
- });
- root_module.load();
+ node.loadModule(ARGV[1], process);
node.exit = function (code) {
process.emit("exit");
View
14 src/util.js
@@ -92,17 +92,23 @@ node.path = new function () {
};
print = function (x) {
- return node.stdio.write(x);
+ node.stdio.write(x);
};
puts = function (x) {
- return print(x.toString() + "\n");
+ print(x.toString() + "\n");
};
p = function (x) {
- return puts(JSON.stringify(x));
+ if (x === null) {
+ puts("null");
+ } else if (x === NaN) {
+ puts("NaN");
+ } else {
+ puts(JSON.stringify(x) || "undefined");
+ }
};
node.debug = function (x) {
- return node.stdio.writeError("DEBUG: " + x.toString() + "\n");
+ node.stdio.writeError("DEBUG: " + x.toString() + "\n");
};
View
0 test/mjsunit/test-remote-module-loading.js → ...it/disabled/test-remote-module-loading.js
File renamed without changes.
View
3 test/mjsunit/fixtures/a.js
@@ -1,6 +1,9 @@
+node.debug("load fixtures/a.js");
+
var c = require("b/c.js");
var string = "A";
+
exports.A = function () {
return string;
};
View
3 test/mjsunit/fixtures/b/c.js
@@ -1,3 +1,5 @@
+node.debug("load fixtures/b/c.js");
+
var d = require("d.js");
var string = "C";
@@ -12,4 +14,5 @@ exports.D = function () {
process.addListener("exit", function () {
string = "C done";
+ puts("b/c.js exit");
});
View
2 test/mjsunit/fixtures/b/d.js
@@ -1,3 +1,5 @@
+node.debug("load fixtures/b/d.js");
+
var string = "D";
exports.D = function () {
View
3 test/mjsunit/test-module-loading.js
@@ -1,3 +1,4 @@
+node.debug("load test-module-loading.js");
include("mjsunit.js");
var a = require("fixtures/a.js");
var d = require("fixtures/b/d.js");
@@ -35,4 +36,6 @@ process.addListener("exit", function () {
assertInstanceof(d2.D, Function);
assertEquals("D done", d2.D());
+
+ puts("exit");
});

0 comments on commit c8b143b

Please sign in to comment.