-
Notifications
You must be signed in to change notification settings - Fork 30.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lib,src: refactor src/node.js into internal files
PR-URL: #5103 Reviewed-By: Trevor Norris <trev.norris@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
- Loading branch information
1 parent
2c67289
commit 015cef2
Showing
9 changed files
with
618 additions
and
588 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]++; | ||
} | ||
} |
Oops, something went wrong.