1 // Hello, and welcome to hacking node.js!
3 // This file is invoked by node::Load in src/node.cc, and responsible for
4 // bootstrapping the node.js core. Special caution is given to the performance
5 // of the startup process, so many dependencies are invoked lazily.
13 var EventEmitter = NativeModule.require('events').EventEmitter;
15 process.__proto__ = Object.create(EventEmitter.prototype, {
17 value: process.constructor
20 EventEmitter.call(process);
22 process.EventEmitter = EventEmitter; // process.EventEmitter is deprecated
24 // do this good and early, since it handles errors.
25 startup.processFatal();
27 startup.globalVariables();
28 startup.globalTimeouts();
29 startup.globalConsole();
31 startup.processAssert();
32 startup.processConfig();
33 startup.processNextTick();
34 startup.processPromises();
35 startup.processStdio();
36 startup.processKillAndExit();
37 startup.processSignalHandlers();
39 // Do not initialize channel in debugger agent, it deletes env variable
40 // and the main thread won't see it.
41 if (process.argv[1] !== '--debug-agent')
42 startup.processChannel();
44 startup.processRawDebug();
46 startup.resolveArgv0();
48 // There are various modes that Node can run in. The most common two
49 // are running from a script and running the REPL - but there are a few
50 // others like the debugger or running --eval arguments. Here we decide
51 // which mode we run in.
53 if (NativeModule.exists('_third_party_main')) {
54 // To allow people to extend Node in different ways, this hook allows
55 // one to drop a file lib/_third_party_main.js into the build
56 // directory which will be executed instead of Node's normal loading.
57 process.nextTick(function() {
58 NativeModule.require('_third_party_main');
61 } else if (process.argv[1] == 'debug') {
62 // Start the debugger agent
63 var d = NativeModule.require('_debugger');
66 } else if (process.argv[1] == '--debug-agent') {
67 // Start the debugger agent
68 var d = NativeModule.require('_debug_agent');
71 } else if (process._eval != null) {
72 // User passed '-e' or '--eval' arguments to Node.
74 } else if (process.argv[1]) {
75 // make process.argv[1] into a full path
76 var path = NativeModule.require('path');
77 process.argv[1] = path.resolve(process.argv[1]);
79 // If this is a worker in cluster mode, start up the communication
81 if (process.env.NODE_UNIQUE_ID) {
82 var cluster = NativeModule.require('cluster');
83 cluster._setupWorker();
85 // Make sure it's not accidentally inherited by child processes.
86 delete process.env.NODE_UNIQUE_ID;
89 var Module = NativeModule.require('module');
92 process.execArgv.some(function(arg) {
93 return arg.match(/^--debug-brk(=[0-9]*)?$/);
96 // XXX Fix this terrible hack!
98 // Give the client program a few ticks to connect.
99 // Otherwise, there's a race condition where `node debug foo.js`
100 // will not be able to connect in time to catch the first
101 // breakpoint message on line 1.
103 // A better fix would be to somehow get a message from the
104 // global.v8debug object about a connection, and runMain when
105 // that occurs. --isaacs
107 var debugTimeout = +process.env.NODE_DEBUG_TIMEOUT || 50;
108 setTimeout(Module.runMain, debugTimeout);
111 // Main entry point into most programs:
116 var Module = NativeModule.require('module');
118 // If -i or --interactive were passed, or stdin is a TTY.
119 if (process._forceRepl || NativeModule.require('tty').isatty(0)) {
123 ignoreUndefined: false
125 if (parseInt(process.env['NODE_NO_READLINE'], 10)) {
126 opts.terminal = false;
128 if (parseInt(process.env['NODE_DISABLE_COLORS'], 10)) {
129 opts.useColors = false;
131 var repl = Module.requireRepl().start(opts);
132 repl.on('exit', function() {
137 // Read all of stdin - execute it.
138 process.stdin.setEncoding('utf8');
141 process.stdin.on('data', function(d) {
145 process.stdin.on('end', function() {
146 process._eval = code;
147 evalScript('[stdin]');
153 startup.globalVariables = function() {
154 global.process = process;
155 global.global = global;
156 global.GLOBAL = global;
157 global.root = global;
158 global.Buffer = NativeModule.require('buffer').Buffer;
159 process.domain = null;
160 process._exiting = false;
163 startup.globalTimeouts = function() {
164 global.setTimeout = function() {
165 var t = NativeModule.require('timers');
166 return t.setTimeout.apply(this, arguments);
169 global.setInterval = function() {
170 var t = NativeModule.require('timers');
171 return t.setInterval.apply(this, arguments);
174 global.clearTimeout = function() {
175 var t = NativeModule.require('timers');
176 return t.clearTimeout.apply(this, arguments);
179 global.clearInterval = function() {
180 var t = NativeModule.require('timers');
181 return t.clearInterval.apply(this, arguments);
184 global.setImmediate = function() {
185 var t = NativeModule.require('timers');
186 return t.setImmediate.apply(this, arguments);
189 global.clearImmediate = function() {
190 var t = NativeModule.require('timers');
191 return t.clearImmediate.apply(this, arguments);
195 startup.globalConsole = function() {
196 global.__defineGetter__('console', function() {
197 return NativeModule.require('console');
202 startup._lazyConstants = null;
204 startup.lazyConstants = function() {
205 if (!startup._lazyConstants) {
206 startup._lazyConstants = process.binding('constants');
208 return startup._lazyConstants;
211 startup.processFatal = function() {
212 process._makeCallbackAbortOnUncaught = function() {
214 return this[1].apply(this[0], arguments);
216 process._fatalException(err);
220 process._fatalException = function(er) {
223 if (process.domain && process.domain._errorHandler)
224 caught = process.domain._errorHandler(er) || caught;
227 caught = process.emit('uncaughtException', er);
229 // If someone handled it, then great. otherwise, die in C++ land
230 // since that means that we'll exit the process, emit the 'exit' event
233 if (!process._exiting) {
234 process._exiting = true;
235 process.emit('exit', 1);
238 // nothing to be done about it at this point.
241 // if we handled an error, then make sure any ticks get processed
243 NativeModule.require('timers').setImmediate(process._tickCallback);
251 startup.processAssert = function() {
252 assert = process.assert = function(x, msg) {
253 if (!x) throw new Error(msg || 'assertion error');
257 startup.processConfig = function() {
258 // used for `process.config`, but not a real module
259 var config = NativeModule._source.config;
260 delete NativeModule._source.config;
262 // strip the gyp comment line at the beginning
263 config = config.split('\n')
266 .replace(/"/g, '\\"')
269 process.config = JSON.parse(config, function(key, value) {
270 if (value === 'true') return true;
271 if (value === 'false') return false;
276 var addPendingUnhandledRejection;
277 var hasBeenNotifiedProperty = new WeakMap();
278 startup.processNextTick = function() {
279 var nextTickQueue = [];
280 var pendingUnhandledRejections = [];
281 var microtasksScheduled = false;
283 // Used to run V8's micro task queue.
284 var _runMicrotasks = {};
286 // This tickInfo thing is used so that the C++ code in src/node.cc
287 // can have easy accesss to our nextTick state, and avoid unnecessary
290 // *Must* match Environment::TickInfo::Fields in src/env.h.
294 process.nextTick = nextTick;
295 // Needs to be accessible from beyond this scope.
296 process._tickCallback = _tickCallback;
297 process._tickDomainCallback = _tickDomainCallback;
299 process._setupNextTick(tickInfo, _tickCallback, _runMicrotasks);
301 _runMicrotasks = _runMicrotasks.runMicrotasks;
303 function tickDone() {
304 if (tickInfo[kLength] !== 0) {
305 if (tickInfo[kLength] <= tickInfo[kIndex]) {
307 tickInfo[kLength] = 0;
309 nextTickQueue.splice(0, tickInfo[kIndex]);
310 tickInfo[kLength] = nextTickQueue.length;
313 tickInfo[kIndex] = 0;
316 function scheduleMicrotasks() {
317 if (microtasksScheduled)
321 callback: runMicrotasksCallback,
326 microtasksScheduled = true;
329 function runMicrotasksCallback() {
330 microtasksScheduled = false;
333 if (tickInfo[kIndex] < tickInfo[kLength] ||
334 emitPendingUnhandledRejections())
335 scheduleMicrotasks();
338 // Run callbacks that have no domain.
339 // Using domains will cause this to be overridden.
340 function _tickCallback() {
341 var callback, threw, tock;
343 scheduleMicrotasks();
345 while (tickInfo[kIndex] < tickInfo[kLength]) {
346 tock = nextTickQueue[tickInfo[kIndex]++];
347 callback = tock.callback;
356 if (1e4 < tickInfo[kIndex])
363 function _tickDomainCallback() {
364 var callback, domain, threw, tock;
366 scheduleMicrotasks();
368 while (tickInfo[kIndex] < tickInfo[kLength]) {
369 tock = nextTickQueue[tickInfo[kIndex]++];
370 callback = tock.callback;
371 domain = tock.domain;
382 if (1e4 < tickInfo[kIndex])
391 function nextTick(callback) {
392 // on the way out, don't bother. it won't get fired anyway.
393 if (process._exiting)
398 domain: process.domain || null
401 nextTickQueue.push(obj);
405 function emitPendingUnhandledRejections() {
406 var hadListeners = false;
407 while (pendingUnhandledRejections.length > 0) {
408 var promise = pendingUnhandledRejections.shift();
409 var reason = pendingUnhandledRejections.shift();
410 if (hasBeenNotifiedProperty.get(promise) === false) {
411 hasBeenNotifiedProperty.set(promise, true);
412 if (!process.emit('unhandledRejection', reason, promise)) {
413 // Nobody is listening.
414 // TODO(petkaantonov) Take some default action, see #830
422 addPendingUnhandledRejection = function(promise, reason) {
423 pendingUnhandledRejections.push(promise, reason);
424 scheduleMicrotasks();
428 startup.processPromises = function() {
429 var promiseRejectEvent = process._promiseRejectEvent;
431 function unhandledRejection(promise, reason) {
432 hasBeenNotifiedProperty.set(promise, false);
433 addPendingUnhandledRejection(promise, reason);
436 function rejectionHandled(promise) {
437 var hasBeenNotified = hasBeenNotifiedProperty.get(promise);
438 if (hasBeenNotified !== undefined) {
439 hasBeenNotifiedProperty.delete(promise);
440 if (hasBeenNotified === true)
441 process.emit('rejectionHandled', promise);
445 process._setupPromises(function(event, promise, reason) {
446 if (event === promiseRejectEvent.unhandled)
447 unhandledRejection(promise, reason);
448 else if (event === promiseRejectEvent.handled)
449 process.nextTick(function() {
450 rejectionHandled(promise);
453 NativeModule.require('assert').fail('unexpected PromiseRejectEvent');
457 function evalScript(name) {
458 var Module = NativeModule.require('module');
459 var path = NativeModule.require('path');
460 var cwd = process.cwd();
462 var module = new Module(name);
463 module.filename = path.join(cwd, name);
464 module.paths = Module._nodeModulePaths(cwd);
465 var script = process._eval;
466 if (!Module._contextLoad) {
468 script = 'global.__filename = ' + JSON.stringify(name) + ';\n' +
469 'global.exports = exports;\n' +
470 'global.module = module;\n' +
471 'global.__dirname = __dirname;\n' +
472 'global.require = require;\n' +
473 'return require("vm").runInThisContext(' +
474 JSON.stringify(body) + ', { filename: ' +
475 JSON.stringify(name) + ' });\n';
477 var result = module._compile(script, name + '-wrapper');
478 if (process._print_eval) console.log(result);
481 function createWritableStdioStream(fd) {
483 var tty_wrap = process.binding('tty_wrap');
485 // Note stream._type is used for test-module-load-list.js
487 switch (tty_wrap.guessHandleType(fd)) {
489 var tty = NativeModule.require('tty');
490 stream = new tty.WriteStream(fd);
491 stream._type = 'tty';
493 // Hack to have stream not keep the event loop alive.
494 // See https://github.com/joyent/node/issues/1726
495 if (stream._handle && stream._handle.unref) {
496 stream._handle.unref();
501 var fs = NativeModule.require('fs');
502 stream = new fs.SyncWriteStream(fd, { autoClose: false });
508 var net = NativeModule.require('net');
509 stream = new net.Socket({
515 // FIXME Should probably have an option in net.Socket to create a
516 // stream from an existing fd which is writable only. But for now
517 // we'll just add this hack and set the `readable` member to false.
518 // Test: ./node test/fixtures/echo.js < /etc/passwd
519 stream.readable = false;
521 stream._type = 'pipe';
523 // FIXME Hack to have stream not keep the event loop alive.
524 // See https://github.com/joyent/node/issues/1726
525 if (stream._handle && stream._handle.unref) {
526 stream._handle.unref();
531 // Probably an error on in uv_guess_handle()
532 throw new Error('Implement me. Unknown stream file type!');
535 // For supporting legacy API we put the FD here.
538 stream._isStdio = true;
543 startup.processStdio = function() {
544 var stdin, stdout, stderr;
546 process.__defineGetter__('stdout', function() {
547 if (stdout) return stdout;
548 stdout = createWritableStdioStream(1);
549 stdout.destroy = stdout.destroySoon = function(er) {
550 er = er || new Error('process.stdout cannot be closed.');
551 stdout.emit('error', er);
554 process.on('SIGWINCH', function() {
555 stdout._refreshSize();
561 process.__defineGetter__('stderr', function() {
562 if (stderr) return stderr;
563 stderr = createWritableStdioStream(2);
564 stderr.destroy = stderr.destroySoon = function(er) {
565 er = er || new Error('process.stderr cannot be closed.');
566 stderr.emit('error', er);
571 process.__defineGetter__('stdin', function() {
572 if (stdin) return stdin;
574 var tty_wrap = process.binding('tty_wrap');
577 switch (tty_wrap.guessHandleType(fd)) {
579 var tty = NativeModule.require('tty');
580 stdin = new tty.ReadStream(fd, {
588 var fs = NativeModule.require('fs');
589 stdin = new fs.ReadStream(null, { fd: fd, autoClose: false });
594 var net = NativeModule.require('net');
596 // It could be that process has been started with an IPC channel
597 // sitting on fd=0, in such case the pipe for this fd is already
598 // present and creating a new one will lead to the assertion failure
600 if (process._channel && process._channel.fd === fd) {
601 stdin = new net.Socket({
602 handle: process._channel,
607 stdin = new net.Socket({
616 // Probably an error on in uv_guess_handle()
617 throw new Error('Implement me. Unknown stdin file type!');
620 // For supporting legacy API we put the FD here.
623 // stdin starts out life in a paused state, but node doesn't
624 // know yet. Explicitly to readStop() it to put it in the
625 // not-reading state.
626 if (stdin._handle && stdin._handle.readStop) {
627 stdin._handle.reading = false;
628 stdin._readableState.reading = false;
629 stdin._handle.readStop();
632 // if the user calls stdin.pause(), then we need to stop reading
633 // immediately, so that the process can close down.
634 stdin.on('pause', function() {
637 stdin._readableState.reading = false;
638 stdin._handle.reading = false;
639 stdin._handle.readStop();
645 process.openStdin = function() {
646 process.stdin.resume();
647 return process.stdin;
651 startup.processKillAndExit = function() {
653 process.exit = function(code) {
654 if (code || code === 0)
655 process.exitCode = code;
657 if (!process._exiting) {
658 process._exiting = true;
659 process.emit('exit', process.exitCode || 0);
661 process.reallyExit(process.exitCode || 0);
664 process.kill = function(pid, sig) {
667 if (pid != (pid | 0)) {
668 throw new TypeError('invalid pid');
671 // preserve null signal
673 err = process._kill(pid, 0);
675 sig = sig || 'SIGTERM';
676 if (startup.lazyConstants()[sig] &&
677 sig.slice(0, 3) === 'SIG') {
678 err = process._kill(pid, startup.lazyConstants()[sig]);
680 throw new Error('Unknown signal: ' + sig);
685 var errnoException = NativeModule.require('util')._errnoException;
686 throw errnoException(err, 'kill');
693 startup.processSignalHandlers = function() {
694 // Load events module in order to access prototype elements on process like
695 // process.addListener.
696 var signalWraps = {};
698 function isSignal(event) {
699 return event.slice(0, 3) === 'SIG' &&
700 startup.lazyConstants().hasOwnProperty(event);
703 // Detect presence of a listener for the special signal types
704 process.on('newListener', function(type, listener) {
705 if (isSignal(type) &&
706 !signalWraps.hasOwnProperty(type)) {
707 var Signal = process.binding('signal_wrap').Signal;
708 var wrap = new Signal();
712 wrap.onsignal = function() { process.emit(type); };
714 var signum = startup.lazyConstants()[type];
715 var err = wrap.start(signum);
718 var errnoException = NativeModule.require('util')._errnoException;
719 throw errnoException(err, 'uv_signal_start');
722 signalWraps[type] = wrap;
726 process.on('removeListener', function(type, listener) {
727 if (signalWraps.hasOwnProperty(type) &&
728 NativeModule.require('events').listenerCount(this, type) === 0) {
729 signalWraps[type].close();
730 delete signalWraps[type];
736 startup.processChannel = function() {
737 // If we were spawned with env NODE_CHANNEL_FD then load that up and
738 // start parsing data from that stream.
739 if (process.env.NODE_CHANNEL_FD) {
740 var fd = parseInt(process.env.NODE_CHANNEL_FD, 10);
743 // Make sure it's not accidentally inherited by child processes.
744 delete process.env.NODE_CHANNEL_FD;
746 var cp = NativeModule.require('child_process');
748 // Load tcp_wrap to avoid situation where we might immediately receive
750 // FIXME is this really necessary?
751 process.binding('tcp_wrap');
754 assert(process.send);
759 startup.processRawDebug = function() {
760 var format = NativeModule.require('util').format;
761 var rawDebug = process._rawDebug;
762 process._rawDebug = function() {
763 rawDebug(format.apply(null, arguments));
768 startup.resolveArgv0 = function() {
769 var cwd = process.cwd();
770 var isWindows = process.platform === 'win32';
772 // Make process.argv[0] into a full path, but only touch argv[0] if it's
773 // not a system $PATH lookup.
774 // TODO: Make this work on Windows as well. Note that "node" might
775 // execute cwd\node.exe, or some %PATH%\node.exe on Windows,
776 // and that every directory has its own cwd, so d:node.exe is valid.
777 var argv0 = process.argv[0];
778 if (!isWindows && argv0.indexOf('/') !== -1 && argv0.charAt(0) !== '/') {
779 var path = NativeModule.require('path');
780 process.argv[0] = path.join(cwd, process.argv[0]);
784 // Below you find a minimal module system, which is used to load the node
785 // core modules found in lib/*.js. All core modules are compiled into the
786 // node binary, so they can be loaded faster.
788 var ContextifyScript = process.binding('contextify').ContextifyScript;
789 function runInThisContext(code, options) {
790 var script = new ContextifyScript(code, options);
791 return script.runInThisContext();
794 function NativeModule(id) {
795 this.filename = id + '.js';
801 NativeModule._source = process.binding('natives');
802 NativeModule._cache = {};
804 NativeModule.require = function(id) {
805 if (id == 'native_module') {
809 var cached = NativeModule.getCached(id);
811 return cached.exports;
814 if (!NativeModule.exists(id)) {
815 throw new Error('No such native module ' + id);
818 process.moduleLoadList.push('NativeModule ' + id);
820 var nativeModule = new NativeModule(id);
822 nativeModule.cache();
823 nativeModule.compile();
825 return nativeModule.exports;
828 NativeModule.getCached = function(id) {
829 return NativeModule._cache[id];
832 NativeModule.exists = function(id) {
833 return NativeModule._source.hasOwnProperty(id);
836 NativeModule.getSource = function(id) {
837 return NativeModule._source[id];
840 NativeModule.wrap = function(script) {
841 return NativeModule.wrapper[0] + script + NativeModule.wrapper[1];
844 NativeModule.wrapper = [
845 '(function (exports, require, module, __filename, __dirname) { ',
849 NativeModule.prototype.compile = function() {
850 var source = NativeModule.getSource(this.id);
851 source = NativeModule.wrap(source);
853 var fn = runInThisContext(source, { filename: this.filename });
854 fn(this.exports, NativeModule.require, this, this.filename);
859 NativeModule.prototype.cache = function() {
860 NativeModule._cache[this.id] = this;