diff --git a/src/node.js b/src/node.js index 9ba3e97388..39cae19d60 100644 --- a/src/node.js +++ b/src/node.js @@ -76,67 +76,103 @@ process._needTickCallback(); }; - // This contains the source code for the files in lib/ - // Like, natives.fs is the contents of lib/fs.js - var natives = process.binding('natives'); - - // Module System - var Module = (function() { - function Module(id, parent) { + // Native modules don't need a full require function. So we can bootstrap + // most of the system with this mini module system. + var NativeModule = (function() { + function NativeModule(id) { + this.filename = id + '.js'; this.id = id; this.exports = {}; - this.parent = parent; - - this.filename = null; this.loaded = false; - this.exited = false; - this.children = []; - }; + } - // Set the environ variable NODE_MODULE_CONTEXTS=1 to make node load all - // modules in thier own context. - Module._contextLoad = (+process.env['NODE_MODULE_CONTEXTS'] > 0); - Module._internalCache = {}; - Module._cache = {}; - Module._extensions = {}; - Module._paths = []; + NativeModule._source = process.binding('natives'); + NativeModule._cache = {}; - // Native modules don't need a full require function. So we can bootstrap - // most of the system with this mini-require. - Module._requireNative = function(id) { + NativeModule.require = function(id) { if (id == 'module') { return Module; } - if (Module._internalCache[id]) { - return Module._internalCache[id].exports; + var cached = NativeModule.getCached(id); + if (cached) { + return cached.exports; } - if (!natives[id]) { + if (!NativeModule.exists(id)) { throw new Error('No such native module ' + id); } - var filename = id + '.js'; + var nativeModule = new NativeModule(id); - var fn = runInThisContext(Module.wrap(natives[id]), filename, true); + nativeModule.compile(); + nativeModule.cache(); - var m = {id: id, exports: {}}; - fn(m.exports, Module._requireNative, m, filename); - m.loaded = true; - Module._internalCache[id] = m; - return m.exports; + return nativeModule.exports; }; - Module.wrap = function(script) { - return Module.wrapper[0] + script + Module.wrapper[1]; + NativeModule.getCached = function(id) { + return NativeModule._cache[id]; + } + + NativeModule.exists = function(id) { + return (id in NativeModule._source); + } + + NativeModule.getSource = function(id) { + return NativeModule._source[id]; + } + + NativeModule.wrap = function(script) { + return NativeModule.wrapper[0] + script + NativeModule.wrapper[1]; }; - Module.wrapper = [ + NativeModule.wrapper = [ '(function (exports, require, module, __filename, __dirname) { ', '\n});' ]; - var path = Module._requireNative('path'); + NativeModule.prototype.compile = function() { + var source = NativeModule.getSource(this.id); + source = NativeModule.wrap(source); + + var fn = runInThisContext(source, this.filename, true); + fn(this.exports, NativeModule.require, this, this.filename); + + this.loaded = true; + }; + + NativeModule.prototype.cache = function() { + NativeModule._cache[this.id] = this; + }; + + return NativeModule; + })(); + + // Module System + var Module = (function() { + function Module(id, parent) { + this.id = id; + this.exports = {}; + this.parent = parent; + + this.filename = null; + this.loaded = false; + this.exited = false; + this.children = []; + }; + + // Set the environ variable NODE_MODULE_CONTEXTS=1 to make node load all + // modules in thier own context. + Module._contextLoad = (+process.env['NODE_MODULE_CONTEXTS'] > 0); + Module._cache = {}; + Module._extensions = {}; + Module._paths = []; + + Module.wrapper = NativeModule.wrapper; + Module.wrap = NativeModule.wrap; + + var path = NativeModule.require('path'); Module._debug = function() {}; if (process.env.NODE_DEBUG && /module/.test(process.env.NODE_DEBUG)) { @@ -159,7 +195,7 @@ // -> a. // -> a/index. Module._findPath = function(request, paths) { - var fs = Module._requireNative('fs'); + var fs = NativeModule.require('fs'); var exts = Object.keys(Module._extensions); if (request.charAt(0) === '/') { @@ -201,7 +237,7 @@ } Module._resolveLookupPaths = function(request, parent) { - if (natives[request]) { + if (NativeModule.exists(request)) { return [request, []]; } @@ -250,19 +286,17 @@ return cachedModule.exports; } - // With natives id === request - // We deal with these first - if (natives[id]) { + if (NativeModule.exists(id)) { // REPL is a special case, because it needs the real require. if (id == 'repl') { var replModule = new Module('repl'); - replModule._compile(natives.repl, 'repl.js'); - Module._internalCache.repl = replModule; + replModule._compile(NativeModule.getSource('repl'), 'repl.js'); + NativeModule._cache.repl = replModule; return replModule.exports; } debug('load native module ' + request); - return Module._requireNative(id); + return NativeModule.require(id); } var module = new Module(id, parent); @@ -272,7 +306,7 @@ }; Module._resolveFilename = function(request, parent) { - if (natives[request]) { + if (NativeModule.exists(request)) { return [request, request]; } @@ -375,7 +409,7 @@ // Native extension for .js Module._extensions['.js'] = function(module, filename) { - var content = Module._requireNative('fs').readFileSync(filename, 'utf8'); + var content = NativeModule.require('fs').readFileSync(filename, 'utf8'); module._compile(content, filename); }; @@ -424,7 +458,7 @@ // Load events module in order to access prototype elements on process like // process.addListener. - var events = Module._requireNative('events'); + var events = NativeModule.require('events'); // Signal Handlers (function() { @@ -471,22 +505,22 @@ global.setTimeout = function() { - var t = Module._requireNative('timers'); + var t = NativeModule.require('timers'); return t.setTimeout.apply(this, arguments); }; global.setInterval = function() { - var t = Module._requireNative('timers'); + var t = NativeModule.require('timers'); return t.setInterval.apply(this, arguments); }; global.clearTimeout = function() { - var t = Module._requireNative('timers'); + var t = NativeModule.require('timers'); return t.clearTimeout.apply(this, arguments); }; global.clearInterval = function() { - var t = Module._requireNative('timers'); + var t = NativeModule.require('timers'); return t.clearInterval.apply(this, arguments); }; @@ -498,8 +532,8 @@ if (stdout) return stdout; var binding = process.binding('stdio'), - net = Module._requireNative('net'), - fs = Module._requireNative('fs'), + net = NativeModule.require('net'), + fs = NativeModule.require('fs'), fd = binding.stdoutFD; if (binding.isStdoutBlocking()) { @@ -521,8 +555,8 @@ if (stdin) return stdin; var binding = process.binding('stdio'), - net = Module._requireNative('net'), - fs = Module._requireNative('fs'), + net = NativeModule.require('net'), + fs = NativeModule.require('fs'), fd = binding.openStdin(); if (binding.isStdinBlocking()) { @@ -544,11 +578,11 @@ // Lazy load console object global.__defineGetter__('console', function() { - return Module._requireNative('console'); + return NativeModule.require('console'); }); - global.Buffer = Module._requireNative('buffer').Buffer; + global.Buffer = NativeModule.require('buffer').Buffer; process.exit = function(code) { process.emit('exit', code || 0); @@ -563,7 +597,7 @@ var cwd = process.cwd(); - var path = Module._requireNative('path'); + var path = NativeModule.require('path'); var isWindows = process.platform === 'win32'; // Make process.argv[0] and process.argv[1] into full paths, but only @@ -579,9 +613,9 @@ // To allow people to extend Node in different ways, this hook allows // one to drop a file lib/_third_party_main.js into the build directory // which will be executed instead of Node's normal loading. - if (process.binding('natives')['_third_party_main']) { + if (NativeModule.exists('_third_party_main')) { process.nextTick(function () { - Module._requireNative('_third_party_main'); + NativeModule.require('_third_party_main'); }); return; } @@ -589,7 +623,7 @@ if (process.argv[1]) { if (process.argv[1] == 'debug') { // Start the debugger agent - var d = Module._requireNative('_debugger'); + var d = NativeModule.require('_debugger'); d.start(); return; }