diff --git a/lib/internal/process.js b/lib/internal/process.js new file mode 100644 index 00000000000000..17ca5bc326c08a --- /dev/null +++ b/lib/internal/process.js @@ -0,0 +1,186 @@ +'use strict'; + +var _lazyConstants = null; + +function lazyConstants() { + if (!_lazyConstants) { + _lazyConstants = process.binding('constants'); + } + return _lazyConstants; +} + +exports.setup_hrtime = setup_hrtime; +exports.setupConfig = setupConfig; +exports.setupKillAndExit = setupKillAndExit; +exports.setupSignalHandlers = setupSignalHandlers; +exports.setupChannel = setupChannel; +exports.setupRawDebug = setupRawDebug; + + +const assert = process.assert = function(x, msg) { + if (!x) throw new Error(msg || 'assertion error'); +}; + + +function setup_hrtime() { + const _hrtime = process.hrtime; + const hrValues = new Uint32Array(3); + + process.hrtime = function hrtime(ar) { + _hrtime(hrValues); + + if (typeof ar !== 'undefined') { + if (Array.isArray(ar)) { + const sec = (hrValues[0] * 0x100000000 + hrValues[1]) - ar[0]; + const nsec = hrValues[2] - ar[1]; + return [nsec < 0 ? sec - 1 : sec, nsec < 0 ? nsec + 1e9 : nsec]; + } + + throw new TypeError('process.hrtime() only accepts an Array tuple'); + } + + return [ + hrValues[0] * 0x100000000 + hrValues[1], + hrValues[2] + ]; + }; +} + + +function setupConfig(_source) { + // NativeModule._source + // used for `process.config`, but not a real module + var config = _source.config; + delete _source.config; + + // strip the gyp comment line at the beginning + config = config.split('\n') + .slice(1) + .join('\n') + .replace(/"/g, '\\"') + .replace(/'/g, '"'); + + process.config = JSON.parse(config, function(key, value) { + if (value === 'true') return true; + if (value === 'false') return false; + return value; + }); +} + + +function setupKillAndExit() { + + process.exit = function(code) { + if (code || code === 0) + process.exitCode = code; + + if (!process._exiting) { + process._exiting = true; + process.emit('exit', process.exitCode || 0); + } + process.reallyExit(process.exitCode || 0); + }; + + process.kill = function(pid, sig) { + var err; + + if (pid != (pid | 0)) { + throw new TypeError('invalid pid'); + } + + // preserve null signal + if (0 === sig) { + err = process._kill(pid, 0); + } else { + sig = sig || 'SIGTERM'; + if (lazyConstants()[sig] && + sig.slice(0, 3) === 'SIG') { + err = process._kill(pid, lazyConstants()[sig]); + } else { + throw new Error(`Unknown signal: ${sig}`); + } + } + + if (err) { + var errnoException = require('util')._errnoException; + throw errnoException(err, 'kill'); + } + + return true; + }; +} + + +function setupSignalHandlers() { + // Load events module in order to access prototype elements on process like + // process.addListener. + var signalWraps = {}; + + function isSignal(event) { + return typeof event === 'string' && + event.slice(0, 3) === 'SIG' && + lazyConstants().hasOwnProperty(event); + } + + // Detect presence of a listener for the special signal types + process.on('newListener', function(type, listener) { + if (isSignal(type) && + !signalWraps.hasOwnProperty(type)) { + var Signal = process.binding('signal_wrap').Signal; + var wrap = new Signal(); + + wrap.unref(); + + wrap.onsignal = function() { process.emit(type); }; + + var signum = lazyConstants()[type]; + var err = wrap.start(signum); + if (err) { + wrap.close(); + var errnoException = require('util')._errnoException; + throw errnoException(err, 'uv_signal_start'); + } + + signalWraps[type] = wrap; + } + }); + + process.on('removeListener', function(type, listener) { + if (signalWraps.hasOwnProperty(type) && this.listenerCount(type) === 0) { + signalWraps[type].close(); + delete signalWraps[type]; + } + }); +} + + +function setupChannel() { + // If we were spawned with env NODE_CHANNEL_FD then load that up and + // start parsing data from that stream. + if (process.env.NODE_CHANNEL_FD) { + var fd = parseInt(process.env.NODE_CHANNEL_FD, 10); + assert(fd >= 0); + + // Make sure it's not accidentally inherited by child processes. + delete process.env.NODE_CHANNEL_FD; + + var cp = require('child_process'); + + // Load tcp_wrap to avoid situation where we might immediately receive + // a message. + // FIXME is this really necessary? + process.binding('tcp_wrap'); + + cp._forkChild(fd); + assert(process.send); + } +} + + +function setupRawDebug() { + var format = require('util').format; + var rawDebug = process._rawDebug; + process._rawDebug = function() { + rawDebug(format.apply(null, arguments)); + }; +} diff --git a/lib/internal/process/next_tick.js b/lib/internal/process/next_tick.js new file mode 100644 index 00000000000000..529645aa8d65c4 --- /dev/null +++ b/lib/internal/process/next_tick.js @@ -0,0 +1,157 @@ +'use strict'; + +exports.setup = setupNextTick; + +function setupNextTick() { + const promises = require('internal/process/promises'); + const emitPendingUnhandledRejections = promises.setup(scheduleMicrotasks); + var nextTickQueue = []; + var microtasksScheduled = false; + + // Used to run V8's micro task queue. + var _runMicrotasks = {}; + + // *Must* match Environment::TickInfo::Fields in src/env.h. + var kIndex = 0; + var kLength = 1; + + process.nextTick = nextTick; + // Needs to be accessible from beyond this scope. + process._tickCallback = _tickCallback; + process._tickDomainCallback = _tickDomainCallback; + + // This tickInfo thing is used so that the C++ code in src/node.cc + // can have easy access to our nextTick state, and avoid unnecessary + // calls into JS land. + const tickInfo = process._setupNextTick(_tickCallback, _runMicrotasks); + + _runMicrotasks = _runMicrotasks.runMicrotasks; + + function tickDone() { + if (tickInfo[kLength] !== 0) { + if (tickInfo[kLength] <= tickInfo[kIndex]) { + nextTickQueue = []; + tickInfo[kLength] = 0; + } else { + nextTickQueue.splice(0, tickInfo[kIndex]); + tickInfo[kLength] = nextTickQueue.length; + } + } + tickInfo[kIndex] = 0; + } + + function scheduleMicrotasks() { + if (microtasksScheduled) + return; + + nextTickQueue.push({ + callback: runMicrotasksCallback, + domain: null + }); + + tickInfo[kLength]++; + microtasksScheduled = true; + } + + function runMicrotasksCallback() { + microtasksScheduled = false; + _runMicrotasks(); + + if (tickInfo[kIndex] < tickInfo[kLength] || + emitPendingUnhandledRejections()) + scheduleMicrotasks(); + } + + function _combinedTickCallback(args, callback) { + if (args === undefined) { + callback(); + } else { + switch (args.length) { + case 1: + callback(args[0]); + break; + case 2: + callback(args[0], args[1]); + break; + case 3: + callback(args[0], args[1], args[2]); + break; + default: + callback.apply(null, args); + } + } + } + + // Run callbacks that have no domain. + // Using domains will cause this to be overridden. + function _tickCallback() { + var callback, args, tock; + + do { + while (tickInfo[kIndex] < tickInfo[kLength]) { + tock = nextTickQueue[tickInfo[kIndex]++]; + callback = tock.callback; + args = tock.args; + // Using separate callback execution functions allows direct + // callback invocation with small numbers of arguments to avoid the + // performance hit associated with using `fn.apply()` + _combinedTickCallback(args, callback); + if (1e4 < tickInfo[kIndex]) + tickDone(); + } + tickDone(); + _runMicrotasks(); + emitPendingUnhandledRejections(); + } while (tickInfo[kLength] !== 0); + } + + function _tickDomainCallback() { + var callback, domain, args, tock; + + do { + while (tickInfo[kIndex] < tickInfo[kLength]) { + tock = nextTickQueue[tickInfo[kIndex]++]; + callback = tock.callback; + domain = tock.domain; + args = tock.args; + if (domain) + domain.enter(); + // Using separate callback execution functions allows direct + // callback invocation with small numbers of arguments to avoid the + // performance hit associated with using `fn.apply()` + _combinedTickCallback(args, callback); + if (1e4 < tickInfo[kIndex]) + tickDone(); + if (domain) + domain.exit(); + } + tickDone(); + _runMicrotasks(); + emitPendingUnhandledRejections(); + } while (tickInfo[kLength] !== 0); + } + + function TickObject(c, args) { + this.callback = c; + this.domain = process.domain || null; + this.args = args; + } + + function nextTick(callback) { + if (typeof callback !== 'function') + throw new TypeError('callback is not a function'); + // on the way out, don't bother. it won't get fired anyway. + if (process._exiting) + return; + + var args; + if (arguments.length > 1) { + args = new Array(arguments.length - 1); + for (var i = 1; i < arguments.length; i++) + args[i - 1] = arguments[i]; + } + + nextTickQueue.push(new TickObject(callback, args)); + tickInfo[kLength]++; + } +} diff --git a/lib/internal/process/promises.js b/lib/internal/process/promises.js new file mode 100644 index 00000000000000..165bf3319ee7db --- /dev/null +++ b/lib/internal/process/promises.js @@ -0,0 +1,61 @@ +'use strict'; + +const promiseRejectEvent = process._promiseRejectEvent; +const hasBeenNotifiedProperty = new WeakMap(); +const pendingUnhandledRejections = []; + +exports.setup = setupPromises; + +function setupPromises(scheduleMicrotasks) { + process._setupPromises(function(event, promise, reason) { + if (event === promiseRejectEvent.unhandled) + unhandledRejection(promise, reason); + else if (event === promiseRejectEvent.handled) + rejectionHandled(promise); + else + require('assert').fail('unexpected PromiseRejectEvent'); + }); + + function unhandledRejection(promise, reason) { + hasBeenNotifiedProperty.set(promise, false); + addPendingUnhandledRejection(promise, reason); + } + + function rejectionHandled(promise) { + var hasBeenNotified = hasBeenNotifiedProperty.get(promise); + if (hasBeenNotified !== undefined) { + hasBeenNotifiedProperty.delete(promise); + if (hasBeenNotified === true) { + process.nextTick(function() { + process.emit('rejectionHandled', promise); + }); + } + + } + } + + function emitPendingUnhandledRejections() { + var hadListeners = false; + while (pendingUnhandledRejections.length > 0) { + var promise = pendingUnhandledRejections.shift(); + var reason = pendingUnhandledRejections.shift(); + if (hasBeenNotifiedProperty.get(promise) === false) { + hasBeenNotifiedProperty.set(promise, true); + if (!process.emit('unhandledRejection', reason, promise)) { + // Nobody is listening. + // TODO(petkaantonov) Take some default action, see #830 + } else { + hadListeners = true; + } + } + } + return hadListeners; + } + + function addPendingUnhandledRejection(promise, reason) { + pendingUnhandledRejections.push(promise, reason); + scheduleMicrotasks(); + } + + return emitPendingUnhandledRejections; +} diff --git a/lib/internal/process/stdio.js b/lib/internal/process/stdio.js new file mode 100644 index 00000000000000..55689069ff2cb5 --- /dev/null +++ b/lib/internal/process/stdio.js @@ -0,0 +1,161 @@ +'use strict'; + +exports.setup = setupStdio; + +function setupStdio() { + var stdin, stdout, stderr; + + process.__defineGetter__('stdout', function() { + if (stdout) return stdout; + stdout = createWritableStdioStream(1); + stdout.destroy = stdout.destroySoon = function(er) { + er = er || new Error('process.stdout cannot be closed.'); + stdout.emit('error', er); + }; + if (stdout.isTTY) { + process.on('SIGWINCH', function() { + stdout._refreshSize(); + }); + } + return stdout; + }); + + process.__defineGetter__('stderr', function() { + if (stderr) return stderr; + stderr = createWritableStdioStream(2); + stderr.destroy = stderr.destroySoon = function(er) { + er = er || new Error('process.stderr cannot be closed.'); + stderr.emit('error', er); + }; + if (stderr.isTTY) { + process.on('SIGWINCH', function() { + stderr._refreshSize(); + }); + } + return stderr; + }); + + process.__defineGetter__('stdin', function() { + if (stdin) return stdin; + + var tty_wrap = process.binding('tty_wrap'); + var fd = 0; + + switch (tty_wrap.guessHandleType(fd)) { + case 'TTY': + var tty = require('tty'); + stdin = new tty.ReadStream(fd, { + highWaterMark: 0, + readable: true, + writable: false + }); + break; + + case 'FILE': + var fs = require('fs'); + stdin = new fs.ReadStream(null, { fd: fd, autoClose: false }); + break; + + case 'PIPE': + case 'TCP': + var net = require('net'); + + // It could be that process has been started with an IPC channel + // sitting on fd=0, in such case the pipe for this fd is already + // present and creating a new one will lead to the assertion failure + // in libuv. + if (process._channel && process._channel.fd === fd) { + stdin = new net.Socket({ + handle: process._channel, + readable: true, + writable: false + }); + } else { + stdin = new net.Socket({ + fd: fd, + readable: true, + writable: false + }); + } + // Make sure the stdin can't be `.end()`-ed + stdin._writableState.ended = true; + break; + + default: + // Probably an error on in uv_guess_handle() + throw new Error('Implement me. Unknown stdin file type!'); + } + + // For supporting legacy API we put the FD here. + stdin.fd = fd; + + // stdin starts out life in a paused state, but node doesn't + // know yet. Explicitly to readStop() it to put it in the + // not-reading state. + if (stdin._handle && stdin._handle.readStop) { + stdin._handle.reading = false; + stdin._readableState.reading = false; + stdin._handle.readStop(); + } + + // if the user calls stdin.pause(), then we need to stop reading + // immediately, so that the process can close down. + stdin.on('pause', function() { + if (!stdin._handle) + return; + stdin._readableState.reading = false; + stdin._handle.reading = false; + stdin._handle.readStop(); + }); + + return stdin; + }); + + process.openStdin = function() { + process.stdin.resume(); + return process.stdin; + }; +} + +function createWritableStdioStream(fd) { + var stream; + var tty_wrap = process.binding('tty_wrap'); + + // Note stream._type is used for test-module-load-list.js + + switch (tty_wrap.guessHandleType(fd)) { + case 'TTY': + var tty = require('tty'); + stream = new tty.WriteStream(fd); + stream._type = 'tty'; + break; + + case 'FILE': + var fs = require('fs'); + stream = new fs.SyncWriteStream(fd, { autoClose: false }); + stream._type = 'fs'; + break; + + case 'PIPE': + case 'TCP': + var net = require('net'); + stream = new net.Socket({ + fd: fd, + readable: false, + writable: true + }); + stream._type = 'pipe'; + break; + + default: + // Probably an error on in uv_guess_handle() + throw new Error('Implement me. Unknown stream file type!'); + } + + // For supporting legacy API we put the FD here. + stream.fd = fd; + + stream._isStdio = true; + + return stream; +} diff --git a/node.gyp b/node.gyp index dc525e1421333d..944e29a5523026 100644 --- a/node.gyp +++ b/node.gyp @@ -75,6 +75,10 @@ 'lib/internal/linkedlist.js', 'lib/internal/net.js', 'lib/internal/module.js', + 'lib/internal/process/next_tick.js', + 'lib/internal/process/promises.js', + 'lib/internal/process/stdio.js', + 'lib/internal/process.js', 'lib/internal/readline.js', 'lib/internal/repl.js', 'lib/internal/socket_list.js', diff --git a/src/node.js b/src/node.js index c58871e31df084..0a688a1b0f915a 100644 --- a/src/node.js +++ b/src/node.js @@ -34,29 +34,30 @@ } }); - startup.setupProcessObject(); + setupProcessObject(); // do this good and early, since it handles errors. - startup.processFatal(); + setupProcessFatal(); - startup.globalVariables(); - startup.globalTimeouts(); - startup.globalConsole(); + setupGlobalVariables(); + setupGlobalTimeouts(); + setupGlobalConsole(); - startup.processAssert(); - startup.processConfig(); - startup.processNextTick(); - startup.processPromises(); - startup.processStdio(); - startup.processKillAndExit(); - startup.processSignalHandlers(); + const _process = NativeModule.require('internal/process'); + + _process.setup_hrtime(); + _process.setupConfig(NativeModule._source); + NativeModule.require('internal/process/next_tick').setup(); + NativeModule.require('internal/process/stdio').setup(); + _process.setupKillAndExit(); + _process.setupSignalHandlers(); // Do not initialize channel in debugger agent, it deletes env variable // and the main thread won't see it. if (process.argv[1] !== '--debug-agent') - startup.processChannel(); + _process.setupChannel(); - startup.processRawDebug(); + _process.setupRawDebug(); process.argv[0] = process.execPath; @@ -101,7 +102,7 @@ if (process._eval != null && !process._forceRepl) { // User passed '-e' or '--eval' arguments to Node without '-i' or // '--interactive' - startup.preloadModules(); + preloadModules(); evalScript('[eval]'); } else if (process.argv[1]) { // make process.argv[1] into a full path @@ -127,7 +128,8 @@ process.exit(0); } - startup.preloadModules(); + preloadModules(); + if (global.v8debug && process.execArgv.some(function(arg) { return arg.match(/^--debug-brk(=[0-9]*)?$/); @@ -153,7 +155,7 @@ } } else { - startup.preloadModules(); + preloadModules(); // If -i or --interactive were passed, or stdin is a TTY. if (process._forceRepl || NativeModule.require('tty').isatty(0)) { // REPL @@ -195,38 +197,16 @@ } } - startup.setupProcessObject = function() { - const _hrtime = process.hrtime; - const hrValues = new Uint32Array(3); - + function setupProcessObject() { process._setupProcessObject(pushValueToArray); function pushValueToArray() { for (var i = 0; i < arguments.length; i++) this.push(arguments[i]); } + } - process.hrtime = function hrtime(ar) { - _hrtime(hrValues); - - if (typeof ar !== 'undefined') { - if (Array.isArray(ar)) { - const sec = (hrValues[0] * 0x100000000 + hrValues[1]) - ar[0]; - const nsec = hrValues[2] - ar[1]; - return [nsec < 0 ? sec - 1 : sec, nsec < 0 ? nsec + 1e9 : nsec]; - } - - throw new TypeError('process.hrtime() only accepts an Array tuple'); - } - - return [ - hrValues[0] * 0x100000000 + hrValues[1], - hrValues[2] - ]; - }; - }; - - startup.globalVariables = function() { + function setupGlobalVariables() { global.process = process; global.global = global; const util = NativeModule.require('util'); @@ -253,9 +233,9 @@ global.Buffer = NativeModule.require('buffer').Buffer; process.domain = null; process._exiting = false; - }; + } - startup.globalTimeouts = function() { + function setupGlobalTimeouts() { const timers = NativeModule.require('timers'); global.clearImmediate = timers.clearImmediate; global.clearInterval = timers.clearInterval; @@ -263,25 +243,15 @@ global.setImmediate = timers.setImmediate; global.setInterval = timers.setInterval; global.setTimeout = timers.setTimeout; - }; + } - startup.globalConsole = function() { + function setupGlobalConsole() { global.__defineGetter__('console', function() { return NativeModule.require('console'); }); - }; - - - startup._lazyConstants = null; - - startup.lazyConstants = function() { - if (!startup._lazyConstants) { - startup._lazyConstants = process.binding('constants'); - } - return startup._lazyConstants; - }; + } - startup.processFatal = function() { + function setupProcessFatal() { process._fatalException = function(er) { var caught; @@ -311,242 +281,7 @@ return caught; }; - }; - - var assert; - startup.processAssert = function() { - assert = process.assert = function(x, msg) { - if (!x) throw new Error(msg || 'assertion error'); - }; - }; - - startup.processConfig = function() { - // used for `process.config`, but not a real module - var config = NativeModule._source.config; - delete NativeModule._source.config; - - // strip the gyp comment line at the beginning - config = config.split('\n') - .slice(1) - .join('\n') - .replace(/"/g, '\\"') - .replace(/'/g, '"'); - - process.config = JSON.parse(config, function(key, value) { - if (value === 'true') return true; - if (value === 'false') return false; - return value; - }); - }; - - var addPendingUnhandledRejection; - var hasBeenNotifiedProperty = new WeakMap(); - startup.processNextTick = function() { - var nextTickQueue = []; - var pendingUnhandledRejections = []; - var microtasksScheduled = false; - - // Used to run V8's micro task queue. - var _runMicrotasks = {}; - - // *Must* match Environment::TickInfo::Fields in src/env.h. - var kIndex = 0; - var kLength = 1; - - process.nextTick = nextTick; - // Needs to be accessible from beyond this scope. - process._tickCallback = _tickCallback; - process._tickDomainCallback = _tickDomainCallback; - - // This tickInfo thing is used so that the C++ code in src/node.cc - // can have easy access to our nextTick state, and avoid unnecessary - // calls into JS land. - const tickInfo = process._setupNextTick(_tickCallback, _runMicrotasks); - - _runMicrotasks = _runMicrotasks.runMicrotasks; - - function tickDone() { - if (tickInfo[kLength] !== 0) { - if (tickInfo[kLength] <= tickInfo[kIndex]) { - nextTickQueue = []; - tickInfo[kLength] = 0; - } else { - nextTickQueue.splice(0, tickInfo[kIndex]); - tickInfo[kLength] = nextTickQueue.length; - } - } - tickInfo[kIndex] = 0; - } - - function scheduleMicrotasks() { - if (microtasksScheduled) - return; - - nextTickQueue.push({ - callback: runMicrotasksCallback, - domain: null - }); - - tickInfo[kLength]++; - microtasksScheduled = true; - } - - function runMicrotasksCallback() { - microtasksScheduled = false; - _runMicrotasks(); - - if (tickInfo[kIndex] < tickInfo[kLength] || - emitPendingUnhandledRejections()) - scheduleMicrotasks(); - } - - function _combinedTickCallback(args, callback) { - if (args === undefined) { - callback(); - } else { - switch (args.length) { - case 1: - callback(args[0]); - break; - case 2: - callback(args[0], args[1]); - break; - case 3: - callback(args[0], args[1], args[2]); - break; - default: - callback.apply(null, args); - } - } - } - - // Run callbacks that have no domain. - // Using domains will cause this to be overridden. - function _tickCallback() { - var callback, args, tock; - - do { - while (tickInfo[kIndex] < tickInfo[kLength]) { - tock = nextTickQueue[tickInfo[kIndex]++]; - callback = tock.callback; - args = tock.args; - // Using separate callback execution functions allows direct - // callback invocation with small numbers of arguments to avoid the - // performance hit associated with using `fn.apply()` - _combinedTickCallback(args, callback); - if (1e4 < tickInfo[kIndex]) - tickDone(); - } - tickDone(); - _runMicrotasks(); - emitPendingUnhandledRejections(); - } while (tickInfo[kLength] !== 0); - } - - function _tickDomainCallback() { - var callback, domain, args, tock; - - do { - while (tickInfo[kIndex] < tickInfo[kLength]) { - tock = nextTickQueue[tickInfo[kIndex]++]; - callback = tock.callback; - domain = tock.domain; - args = tock.args; - if (domain) - domain.enter(); - // Using separate callback execution functions allows direct - // callback invocation with small numbers of arguments to avoid the - // performance hit associated with using `fn.apply()` - _combinedTickCallback(args, callback); - if (1e4 < tickInfo[kIndex]) - tickDone(); - if (domain) - domain.exit(); - } - tickDone(); - _runMicrotasks(); - emitPendingUnhandledRejections(); - } while (tickInfo[kLength] !== 0); - } - - function TickObject(c, args) { - this.callback = c; - this.domain = process.domain || null; - this.args = args; - } - - function nextTick(callback) { - if (typeof callback !== 'function') - throw new TypeError('callback is not a function'); - // on the way out, don't bother. it won't get fired anyway. - if (process._exiting) - return; - - var args; - if (arguments.length > 1) { - args = new Array(arguments.length - 1); - for (var i = 1; i < arguments.length; i++) - args[i - 1] = arguments[i]; - } - - nextTickQueue.push(new TickObject(callback, args)); - tickInfo[kLength]++; - } - - function emitPendingUnhandledRejections() { - var hadListeners = false; - while (pendingUnhandledRejections.length > 0) { - var promise = pendingUnhandledRejections.shift(); - var reason = pendingUnhandledRejections.shift(); - if (hasBeenNotifiedProperty.get(promise) === false) { - hasBeenNotifiedProperty.set(promise, true); - if (!process.emit('unhandledRejection', reason, promise)) { - // Nobody is listening. - // TODO(petkaantonov) Take some default action, see #830 - } else { - hadListeners = true; - } - } - } - return hadListeners; - } - - addPendingUnhandledRejection = function(promise, reason) { - pendingUnhandledRejections.push(promise, reason); - scheduleMicrotasks(); - }; - }; - - startup.processPromises = function() { - var promiseRejectEvent = process._promiseRejectEvent; - - function unhandledRejection(promise, reason) { - hasBeenNotifiedProperty.set(promise, false); - addPendingUnhandledRejection(promise, reason); - } - - function rejectionHandled(promise) { - var hasBeenNotified = hasBeenNotifiedProperty.get(promise); - if (hasBeenNotified !== undefined) { - hasBeenNotifiedProperty.delete(promise); - if (hasBeenNotified === true) { - process.nextTick(function() { - process.emit('rejectionHandled', promise); - }); - } - - } - } - - process._setupPromises(function(event, promise, reason) { - if (event === promiseRejectEvent.unhandled) - unhandledRejection(promise, reason); - else if (event === promiseRejectEvent.handled) - rejectionHandled(promise); - else - NativeModule.require('assert').fail('unexpected PromiseRejectEvent'); - }); - }; + } function evalScript(name) { var Module = NativeModule.require('module'); @@ -583,286 +318,12 @@ }); } - function createWritableStdioStream(fd) { - var stream; - var tty_wrap = process.binding('tty_wrap'); - - // Note stream._type is used for test-module-load-list.js - - switch (tty_wrap.guessHandleType(fd)) { - case 'TTY': - var tty = NativeModule.require('tty'); - stream = new tty.WriteStream(fd); - stream._type = 'tty'; - break; - - case 'FILE': - var fs = NativeModule.require('fs'); - stream = new fs.SyncWriteStream(fd, { autoClose: false }); - stream._type = 'fs'; - break; - - case 'PIPE': - case 'TCP': - var net = NativeModule.require('net'); - stream = new net.Socket({ - fd: fd, - readable: false, - writable: true - }); - stream._type = 'pipe'; - break; - - default: - // Probably an error on in uv_guess_handle() - throw new Error('Implement me. Unknown stream file type!'); - } - - // For supporting legacy API we put the FD here. - stream.fd = fd; - - stream._isStdio = true; - - return stream; - } - - startup.processStdio = function() { - var stdin, stdout, stderr; - - process.__defineGetter__('stdout', function() { - if (stdout) return stdout; - stdout = createWritableStdioStream(1); - stdout.destroy = stdout.destroySoon = function(er) { - er = er || new Error('process.stdout cannot be closed.'); - stdout.emit('error', er); - }; - if (stdout.isTTY) { - process.on('SIGWINCH', function() { - stdout._refreshSize(); - }); - } - return stdout; - }); - - process.__defineGetter__('stderr', function() { - if (stderr) return stderr; - stderr = createWritableStdioStream(2); - stderr.destroy = stderr.destroySoon = function(er) { - er = er || new Error('process.stderr cannot be closed.'); - stderr.emit('error', er); - }; - if (stderr.isTTY) { - process.on('SIGWINCH', function() { - stderr._refreshSize(); - }); - } - return stderr; - }); - - process.__defineGetter__('stdin', function() { - if (stdin) return stdin; - - var tty_wrap = process.binding('tty_wrap'); - var fd = 0; - - switch (tty_wrap.guessHandleType(fd)) { - case 'TTY': - var tty = NativeModule.require('tty'); - stdin = new tty.ReadStream(fd, { - highWaterMark: 0, - readable: true, - writable: false - }); - break; - - case 'FILE': - var fs = NativeModule.require('fs'); - stdin = new fs.ReadStream(null, { fd: fd, autoClose: false }); - break; - - case 'PIPE': - case 'TCP': - var net = NativeModule.require('net'); - - // It could be that process has been started with an IPC channel - // sitting on fd=0, in such case the pipe for this fd is already - // present and creating a new one will lead to the assertion failure - // in libuv. - if (process._channel && process._channel.fd === fd) { - stdin = new net.Socket({ - handle: process._channel, - readable: true, - writable: false - }); - } else { - stdin = new net.Socket({ - fd: fd, - readable: true, - writable: false - }); - } - // Make sure the stdin can't be `.end()`-ed - stdin._writableState.ended = true; - break; - - default: - // Probably an error on in uv_guess_handle() - throw new Error('Implement me. Unknown stdin file type!'); - } - - // For supporting legacy API we put the FD here. - stdin.fd = fd; - - // stdin starts out life in a paused state, but node doesn't - // know yet. Explicitly to readStop() it to put it in the - // not-reading state. - if (stdin._handle && stdin._handle.readStop) { - stdin._handle.reading = false; - stdin._readableState.reading = false; - stdin._handle.readStop(); - } - - // if the user calls stdin.pause(), then we need to stop reading - // immediately, so that the process can close down. - stdin.on('pause', function() { - if (!stdin._handle) - return; - stdin._readableState.reading = false; - stdin._handle.reading = false; - stdin._handle.readStop(); - }); - - return stdin; - }); - - process.openStdin = function() { - process.stdin.resume(); - return process.stdin; - }; - }; - - startup.processKillAndExit = function() { - - process.exit = function(code) { - if (code || code === 0) - process.exitCode = code; - - if (!process._exiting) { - process._exiting = true; - process.emit('exit', process.exitCode || 0); - } - process.reallyExit(process.exitCode || 0); - }; - - process.kill = function(pid, sig) { - var err; - - if (pid != (pid | 0)) { - throw new TypeError('invalid pid'); - } - - // preserve null signal - if (0 === sig) { - err = process._kill(pid, 0); - } else { - sig = sig || 'SIGTERM'; - if (startup.lazyConstants()[sig] && - sig.slice(0, 3) === 'SIG') { - err = process._kill(pid, startup.lazyConstants()[sig]); - } else { - throw new Error(`Unknown signal: ${sig}`); - } - } - - if (err) { - var errnoException = NativeModule.require('util')._errnoException; - throw errnoException(err, 'kill'); - } - - return true; - }; - }; - - startup.processSignalHandlers = function() { - // Load events module in order to access prototype elements on process like - // process.addListener. - var signalWraps = {}; - - function isSignal(event) { - return typeof event === 'string' && - event.slice(0, 3) === 'SIG' && - startup.lazyConstants().hasOwnProperty(event); - } - - // Detect presence of a listener for the special signal types - process.on('newListener', function(type, listener) { - if (isSignal(type) && - !signalWraps.hasOwnProperty(type)) { - var Signal = process.binding('signal_wrap').Signal; - var wrap = new Signal(); - - wrap.unref(); - - wrap.onsignal = function() { process.emit(type); }; - - var signum = startup.lazyConstants()[type]; - var err = wrap.start(signum); - if (err) { - wrap.close(); - var errnoException = NativeModule.require('util')._errnoException; - throw errnoException(err, 'uv_signal_start'); - } - - signalWraps[type] = wrap; - } - }); - - process.on('removeListener', function(type, listener) { - if (signalWraps.hasOwnProperty(type) && this.listenerCount(type) === 0) { - signalWraps[type].close(); - delete signalWraps[type]; - } - }); - }; - - - startup.processChannel = function() { - // If we were spawned with env NODE_CHANNEL_FD then load that up and - // start parsing data from that stream. - if (process.env.NODE_CHANNEL_FD) { - var fd = parseInt(process.env.NODE_CHANNEL_FD, 10); - assert(fd >= 0); - - // Make sure it's not accidentally inherited by child processes. - delete process.env.NODE_CHANNEL_FD; - - var cp = NativeModule.require('child_process'); - - // Load tcp_wrap to avoid situation where we might immediately receive - // a message. - // FIXME is this really necessary? - process.binding('tcp_wrap'); - - cp._forkChild(fd); - assert(process.send); - } - }; - - - startup.processRawDebug = function() { - var format = NativeModule.require('util').format; - var rawDebug = process._rawDebug; - process._rawDebug = function() { - rawDebug(format.apply(null, arguments)); - }; - }; - // Load preload modules - startup.preloadModules = function() { + function preloadModules() { if (process._preload_modules) { NativeModule.require('module')._preloadModules(process._preload_modules); } - }; + } // Below you find a minimal module system, which is used to load the node // core modules found in lib/*.js. All core modules are compiled into the diff --git a/test/message/eval_messages.out b/test/message/eval_messages.out index c299ec3ae1345c..62f330725606b2 100644 --- a/test/message/eval_messages.out +++ b/test/message/eval_messages.out @@ -7,8 +7,8 @@ SyntaxError: Strict mode code may not include a with statement at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at _combinedTickCallback (node.js:*:*) - at process._tickCallback (node.js:*:*) + at _combinedTickCallback (internal/process/next_tick.js:*:*) + at process._tickCallback (internal/process/next_tick.js:*:*) 42 42 [eval]:1 @@ -20,8 +20,8 @@ Error: hello at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at _combinedTickCallback (node.js:*:*) - at process._tickCallback (node.js:*:*) + at _combinedTickCallback (internal/process/next_tick.js:*:*) + at process._tickCallback (internal/process/next_tick.js:*:*) [eval]:1 throw new Error("hello") ^ @@ -31,8 +31,8 @@ Error: hello at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at _combinedTickCallback (node.js:*:*) - at process._tickCallback (node.js:*:*) + at _combinedTickCallback (internal/process/next_tick.js:*:*) + at process._tickCallback (internal/process/next_tick.js:*:*) 100 [eval]:1 var x = 100; y = x; @@ -43,8 +43,8 @@ ReferenceError: y is not defined at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at _combinedTickCallback (node.js:*:*) - at process._tickCallback (node.js:*:*) + at _combinedTickCallback (internal/process/next_tick.js:*:*) + at process._tickCallback (internal/process/next_tick.js:*:*) [eval]:1 var ______________________________________________; throw 10 ^ diff --git a/test/message/nexttick_throw.out b/test/message/nexttick_throw.out index 72f04b00936977..6504bd315da900 100644 --- a/test/message/nexttick_throw.out +++ b/test/message/nexttick_throw.out @@ -4,8 +4,8 @@ ^ ReferenceError: undefined_reference_error_maker is not defined at *test*message*nexttick_throw.js:*:* - at _combinedTickCallback (node.js:*:*) - at process._tickCallback (node.js:*:*) + at _combinedTickCallback (internal/process/next_tick.js:*:*) + at process._tickCallback (internal/process/next_tick.js:*:*) at Function.Module.runMain (module.js:*:*) at startup (node.js:*:*) at node.js:*:* diff --git a/test/message/stdin_messages.out b/test/message/stdin_messages.out index 2e08a70cc46fbc..a7c45a1fbb33fb 100644 --- a/test/message/stdin_messages.out +++ b/test/message/stdin_messages.out @@ -8,8 +8,8 @@ SyntaxError: Strict mode code may not include a with statement at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at _combinedTickCallback (node.js:*:*) - at process._tickCallback (node.js:*:*) + at _combinedTickCallback (internal/process/next_tick.js:*:*) + at process._tickCallback (internal/process/next_tick.js:*:*) 42 42 @@ -22,8 +22,8 @@ Error: hello at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at _combinedTickCallback (node.js:*:*) - at process._tickCallback (node.js:*:*) + at _combinedTickCallback (internal/process/next_tick.js:*:*) + at process._tickCallback (internal/process/next_tick.js:*:*) [stdin]:1 throw new Error("hello") @@ -34,8 +34,8 @@ Error: hello at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at _combinedTickCallback (node.js:*:*) - at process._tickCallback (node.js:*:*) + at _combinedTickCallback (internal/process/next_tick.js:*:*) + at process._tickCallback (internal/process/next_tick.js:*:*) 100 [stdin]:1 @@ -47,8 +47,8 @@ ReferenceError: y is not defined at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at node.js:*:* - at _combinedTickCallback (node.js:*:*) - at process._tickCallback (node.js:*:*) + at _combinedTickCallback (internal/process/next_tick.js:*:*) + at process._tickCallback (internal/process/next_tick.js:*:*) [stdin]:1 var ______________________________________________; throw 10