Skip to content

Instantly share code, notes, and snippets.

@kthompson
Created June 28, 2011 00:31
Show Gist options
  • Save kthompson/1050210 to your computer and use it in GitHub Desktop.
Save kthompson/1050210 to your computer and use it in GitHub Desktop.
Javascript module implementation.
(function() {
function Module(id) {
this.id = id;
this.exports = {};
this.filename = null;
this.loaded = false;
this.exited = false;
}
//instance methods
Module.prototype.load = function(filename, success, failure) {
if(this.loaded){
failure("module already loaded");
return;
}
var $this = this;
this.filename = filename;
this.fetchSource(function(src){
$this._compile(src);
$this.loaded = true;
success($this.exports);
}, failure);
};
Module.prototype._fetchSource = function(success, failure) {
var req = new XMLHttpRequest();
req.open('GET', this.filename, true);
req.onreadystatechange = function (aEvt) {
if (req.readyState == 4) {
if(req.status == 200){
success(req.responseText);
} else {
var txt = "Failed GET request to '"+this.filename+"'";
if (req.statusText) txt += ": "+req.statusText;
if (req.status) txt += " ("+req.status+")";
failure(txt);
}
}
};
req.overrideMimeType("text/plain");
req.send(null);
};
// Returns exception if any
Module.prototype._compile = function(src) {
// remove shebang
src = src.replace(/^\#\!.*/, '');
// create wrapper function
var fn = new Function("exports", "require", "module", "__filename", src);
var args = [this.exports, Module.require, this, this.filename];
return f.apply(this.exports, args);
};
//class methods
Module._cache = {};
Module._pathCache = {};
Module._resolveFilename = function(id) {
if (/\/|\\|\.js$/.test(id))
return id;
if (Module._pathCache[id])
return Module._pathCache[id];
var parts = id.split('.'), used = [], ns;
while (parts.length) {
if (Module._pathCache[ns = parts.join('.')])
return Module._pathCache[ns] + used.reverse().join('/') + '.js';
used.push(parts.pop());
}
return used.reverse().join('/') + '.js';
};
Module.require = function(id, success, failure) {
var resolved = Module._resolveFilename(id);
var id = resolved[0];
var filename = resolved[1];
var cachedModule = Module._cache[filename];
if (cachedModule) {
success(cachedModule.exports);
return;
}
var module = new Module(id);
Module._cache[filename] = module;
module.load(filename, success, function(error){
delete Module._cache[filename];
failure(error)
});
};
Module.require.resolve = function(id) {
return Module._resolveFilename(id)[1];
}
Module.require.cache = Module._cache;
this.require = Module.require;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment