Skip to content

Commit

Permalink
removing the separate registry in favor of the nodejs registry
Browse files Browse the repository at this point in the history
  • Loading branch information
caridy committed Jun 28, 2014
1 parent 83b2206 commit f8f8bc6
Showing 1 changed file with 88 additions and 96 deletions.
184 changes: 88 additions & 96 deletions lib/system.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,114 +3,106 @@

var Promise = global.Promise || require("ypromise");
var m = require("module");
var Module = m.Module;
var originalLoader = m._load;
var registry = Object.create(null);
var seen = Object.create(null);
var path = require("path");
var justRegistered;
var System = {
get: function(name) {
var mod = registry[name];
if (mod && !seen[name]) {
seen[name] = true;
// one time operation to execute the module body
mod.execute();
}
return mod && mod.proxy;
},
register: function(name, deps, wrapper) {
var proxy = Object.create(null), values = Object.create(null), mod, meta;
justRegistered = name;
// creating a new entry in the internal registry
registry[name] = mod = {
name: name,
parent: null,
// live bindings
proxy: proxy,
// exported values
values: values,
// normalized deps
deps: deps.map(function(dep) {
if (dep.charAt(0) !== ".") {
return dep;
}
var parts = dep.split("/"),
parentBase = name.split("/").slice(0, -1);
while (parts[0] === "." || parts[0] === "..") {
if (parts.shift() === "..") {
parentBase.pop();
}
}
return parentBase.concat(parts).join("/");
}),
// other modules that depends on this so we can push updates into those modules
dependants: [],
// method used to push updates of dependencies into the module body
update: function(moduleName, moduleObj) {
meta.setters[mod.deps.indexOf(moduleName)](moduleObj);
},
execute: function () {
mod.deps.forEach(function(dep) {
var imports = System.get(dep) || require(m.Module._resolveFilename(mod.basePath + dep, mod.parent));
if (registry[dep]) {
registry[dep].dependants.push(name);
// optimization to push plain values instead of the bindings
imports = registry[dep].values;
}
if (imports) {
mod.update(dep, imports);
}
});
meta.execute();
var newEntry;

function get(name) {
var mod = registry[name];
if (mod && !seen[name]) {
seen[name] = true;
// one time operation to execute the module body
mod.execute();
}
return mod && mod.proxy;
}
function register(name, deps, wrapper) {
var mod;
// creating a new module entry that will be added to the cache later on
newEntry = mod = {
name: name,
setters: null,
proxy: Object.create(null),
// normalized deps
deps: deps.map(function(dep) {
if (dep.charAt(0) !== ".") {
return dep;
}
};
// collecting execute() and setters[]
meta = wrapper(function(identifier, value) {
values[identifier] = value;
mod.dependants.forEach(function(moduleName) {
if (registry[moduleName]) {
registry[moduleName].update(name, values);
var parts = dep.split("/"),
parentBase = name.split("/").slice(0, -1);
while (parts[0] === "." || parts[0] === "..") {
if (parts.shift() === "..") {
parentBase.pop();
}
});
if (!Object.getOwnPropertyDescriptor(proxy, identifier)) {
Object.defineProperty(proxy, identifier, {
enumerable: true,
get: function() {
return values[identifier];
}
});
}
});
},
import: function(name) {
return new Promise(function (resolve, reject) {
var mod = require(path.resolve(name));
return mod ? resolve(mod) : reject(new Error("Could not find module " + name));
});
}
};
return parentBase.concat(parts).join("/");
}),
// other modules that depends on this so we can push updates into those modules
dependants: [],
// method used to push updates of dependencies into the module body
update: function(moduleName, moduleObj) {
mod.setters[mod.deps.indexOf(moduleName)](moduleObj);
},
execute: wrapper
};
}

m._load = function hookedLoader(request, parent, isMain) {
var exports, i, mod, values;
justRegistered = undefined;
exports = originalLoader.apply(this, arguments);
if (justRegistered) {
// extending exports with the ES exports
mod = registry[justRegistered];
mod.basePath = request.slice(0, -justRegistered.length);
mod.parent = parent;
values = System.get(justRegistered) && mod.values;
for (i in values) {
Object.defineProperty(exports, i, {
enumerable: true,
get: function() {
return values[i];
var values, filename, cachedModule, metaModule, esModule;
newEntry = undefined;
values = originalLoader.apply(this, arguments);
if (newEntry) {
filename = Module._resolveFilename(request, parent);
cachedModule = Module._cache[filename];
if (cachedModule && !cachedModule._esModule) {
cachedModule._esModule = esModule = newEntry;
esModule.address = filename;
esModule.basePath = request.slice(0, -esModule.name.length);
esModule.parent = parent;
// collecting execute() and setters[]
metaModule = esModule.execute(function(identifier, value) {
values[identifier] = value;
esModule.dependants.forEach(function(dependant) {
dependant.update(esModule.name, values);
});
if (!Object.getOwnPropertyDescriptor(esModule.proxy, identifier)) {
Object.defineProperty(esModule.proxy, identifier, {
enumerable: true,
get: function() {
return values[identifier];
}
});
}
});
esModule.setters = metaModule.setters;
// requiring the dependencies
esModule.deps.forEach(function(dep) {
var depRequest = path.resolve(path.join(esModule.basePath, dep)),
imports = require(depRequest),
depFilename = Module._resolveFilename(depRequest, parent),
depModule = Module._cache[depFilename]._esModule;
if (depModule) {
depModule.dependants.push(esModule);
esModule.update(dep, imports);
}
});
// executing the module body
metaModule.execute();
}
mod.proxy = exports; // unifying the nodejs exports and the proxy object for the ES module
}
return exports;
return values;
};

module.exports = System;
module.exports = {
get: get,
register: register,
import: function(name) {
return new Promise(function (resolve, reject) {
var mod = require(path.resolve(name));
return mod ? resolve(mod) : reject(new Error("Could not find module " + name));
});
}
};

0 comments on commit f8f8bc6

Please sign in to comment.