// Module
+node.loadingModules = [];
+
+function require_async (url) {
+ var currentModule = node.loadingModules[0];
+ return currentModule.newChild(url, {});
+}
+
+function require (url) {
+ return require_async(url).wait();
+}
+
+function include_async (url) {
+ var currentModule = node.loadingModules[0];
+ return currentModule.newChild(url, currentModule.target);
+}
+
+function include (url) {
+ include_async(url).wait();
+}
+
node.Module = function (o) {
this.parent = o.parent;
this.target = o.target || {};
}
this.loaded = false;
+ this.loadPromise = null;
this.exited = false;
this.children = [];
};
throw "Module '" + self.filename + "' is already loaded.";
}
- var promise = node.cat(self.filename, "utf8");
+ var loadPromise = new node.Promise();
+ node.assert(self.loadPromise === null);
+ self.loadPromise = loadPromise;
+
+ var cat_promise = node.cat(self.filename, "utf8");
- promise.addErrback(function () {
+ cat_promise.addErrback(function () {
node.stdio.writeError("Error reading " + self.filename + "\n");
- node.exit(1);
+ loadPromise.emitError();
});
- promise.addCallback(function (content) {
- self.target.__require = function (path) { return self.newChild(path, {}); };
- self.target.__include = function (path) { self.newChild(path, self.target); };
-
+ cat_promise.addCallback(function (content) {
// remove shebang
content = content.replace(/^\#\!.*/, '');
" var onLoad; "+
" var onExit; "+
" var exports = this; "+
- " var require = this.__require; "+
- " var include = this.__include; "+
content+
"\n"+
" this.__onLoad = onLoad;\n"+
" this.__onExit = onExit;\n"+
"};\n";
var compiled_wrapper = node.compile(wrapper, self.filename);
+
+ node.loadingModules.unshift(self);
compiled_wrapper.apply(self.target, [self.filename]);
+ node.loadingModules.shift();
+
self.onLoad = self.target.__onLoad;
self.onExit = self.target.__onExit;
- self.loadChildren(function () {
+ self.waitChildrenLoad(function () {
if (self.onLoad) self.onLoad();
self.loaded = true;
- if (callback) callback();
+ loadPromise.emitSuccess([self.target]);
});
});
};
parent: this
});
this.children.push(child);
- return target;
+ child.load();
+ return child.loadPromise;
};
-node.Module.prototype.loadChildren = function (callback) {
+node.Module.prototype.waitChildrenLoad = function (callback) {
+ var nloaded = 0;
var children = this.children;
- if (children.length == 0 && callback) callback();
- var nloaded = 0;
for (var i = 0; i < children.length; i++) {
var child = children[i];
- child.load(function () {
- nloaded += 1;
- if (nloaded == children.length && callback) callback();
- });
+ if (child.loaded) {
+ nloaded++;
+ } else {
+ child.addCallback(function () {
+ nloaded++;
+ if (children.length == nloaded && callback) callback();
+ });
+ }
}
+ if (children.length == nloaded && callback) callback();
};
node.Module.prototype.exitChildren = function (callback) {
----------------------------------------
var circle = require("circle.js");
-function onLoad () {
- puts("The area of a cirlce of radius 4 is " + circle.area(4));
-}
+puts("The area of a cirlce of radius 4 is " + circle.area(4));
----------------------------------------
The contents of +circle.js+:
----------------------------------------
include("circle.js");
-function onLoad () {
- puts("The area of a cirlce of radius 4 is " + area(4));
-}
+puts("The area of a cirlce of radius 4 is " + area(4));
----------------------------------------
-
-==== +onLoad()+
-
-Because module loading does not happen instantaneously and because Node has
-a policy of never blocking, a callback +onLoad+ can be set that will notify
-the user when the included modules are loaded. Each file/module can have
-its own +onLoad+ callback.
-
-+include()+ and +require()+ cannot be used after +onLoad()+ is called.
+Functions +require_async()+ and +include_async()+ also exist.
==== +onExit()+