Skip to content

Commit 015cef2

Browse files
committed
lib,src: refactor src/node.js into internal files
PR-URL: #5103 Reviewed-By: Trevor Norris <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 2c67289 commit 015cef2

File tree

9 files changed

+618
-588
lines changed

9 files changed

+618
-588
lines changed

lib/internal/process.js

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
'use strict';
2+
3+
var _lazyConstants = null;
4+
5+
function lazyConstants() {
6+
if (!_lazyConstants) {
7+
_lazyConstants = process.binding('constants');
8+
}
9+
return _lazyConstants;
10+
}
11+
12+
exports.setup_hrtime = setup_hrtime;
13+
exports.setupConfig = setupConfig;
14+
exports.setupKillAndExit = setupKillAndExit;
15+
exports.setupSignalHandlers = setupSignalHandlers;
16+
exports.setupChannel = setupChannel;
17+
exports.setupRawDebug = setupRawDebug;
18+
19+
20+
const assert = process.assert = function(x, msg) {
21+
if (!x) throw new Error(msg || 'assertion error');
22+
};
23+
24+
25+
function setup_hrtime() {
26+
const _hrtime = process.hrtime;
27+
const hrValues = new Uint32Array(3);
28+
29+
process.hrtime = function hrtime(ar) {
30+
_hrtime(hrValues);
31+
32+
if (typeof ar !== 'undefined') {
33+
if (Array.isArray(ar)) {
34+
const sec = (hrValues[0] * 0x100000000 + hrValues[1]) - ar[0];
35+
const nsec = hrValues[2] - ar[1];
36+
return [nsec < 0 ? sec - 1 : sec, nsec < 0 ? nsec + 1e9 : nsec];
37+
}
38+
39+
throw new TypeError('process.hrtime() only accepts an Array tuple');
40+
}
41+
42+
return [
43+
hrValues[0] * 0x100000000 + hrValues[1],
44+
hrValues[2]
45+
];
46+
};
47+
}
48+
49+
50+
function setupConfig(_source) {
51+
// NativeModule._source
52+
// used for `process.config`, but not a real module
53+
var config = _source.config;
54+
delete _source.config;
55+
56+
// strip the gyp comment line at the beginning
57+
config = config.split('\n')
58+
.slice(1)
59+
.join('\n')
60+
.replace(/"/g, '\\"')
61+
.replace(/'/g, '"');
62+
63+
process.config = JSON.parse(config, function(key, value) {
64+
if (value === 'true') return true;
65+
if (value === 'false') return false;
66+
return value;
67+
});
68+
}
69+
70+
71+
function setupKillAndExit() {
72+
73+
process.exit = function(code) {
74+
if (code || code === 0)
75+
process.exitCode = code;
76+
77+
if (!process._exiting) {
78+
process._exiting = true;
79+
process.emit('exit', process.exitCode || 0);
80+
}
81+
process.reallyExit(process.exitCode || 0);
82+
};
83+
84+
process.kill = function(pid, sig) {
85+
var err;
86+
87+
if (pid != (pid | 0)) {
88+
throw new TypeError('invalid pid');
89+
}
90+
91+
// preserve null signal
92+
if (0 === sig) {
93+
err = process._kill(pid, 0);
94+
} else {
95+
sig = sig || 'SIGTERM';
96+
if (lazyConstants()[sig] &&
97+
sig.slice(0, 3) === 'SIG') {
98+
err = process._kill(pid, lazyConstants()[sig]);
99+
} else {
100+
throw new Error(`Unknown signal: ${sig}`);
101+
}
102+
}
103+
104+
if (err) {
105+
var errnoException = require('util')._errnoException;
106+
throw errnoException(err, 'kill');
107+
}
108+
109+
return true;
110+
};
111+
}
112+
113+
114+
function setupSignalHandlers() {
115+
// Load events module in order to access prototype elements on process like
116+
// process.addListener.
117+
var signalWraps = {};
118+
119+
function isSignal(event) {
120+
return typeof event === 'string' &&
121+
event.slice(0, 3) === 'SIG' &&
122+
lazyConstants().hasOwnProperty(event);
123+
}
124+
125+
// Detect presence of a listener for the special signal types
126+
process.on('newListener', function(type, listener) {
127+
if (isSignal(type) &&
128+
!signalWraps.hasOwnProperty(type)) {
129+
var Signal = process.binding('signal_wrap').Signal;
130+
var wrap = new Signal();
131+
132+
wrap.unref();
133+
134+
wrap.onsignal = function() { process.emit(type); };
135+
136+
var signum = lazyConstants()[type];
137+
var err = wrap.start(signum);
138+
if (err) {
139+
wrap.close();
140+
var errnoException = require('util')._errnoException;
141+
throw errnoException(err, 'uv_signal_start');
142+
}
143+
144+
signalWraps[type] = wrap;
145+
}
146+
});
147+
148+
process.on('removeListener', function(type, listener) {
149+
if (signalWraps.hasOwnProperty(type) && this.listenerCount(type) === 0) {
150+
signalWraps[type].close();
151+
delete signalWraps[type];
152+
}
153+
});
154+
}
155+
156+
157+
function setupChannel() {
158+
// If we were spawned with env NODE_CHANNEL_FD then load that up and
159+
// start parsing data from that stream.
160+
if (process.env.NODE_CHANNEL_FD) {
161+
var fd = parseInt(process.env.NODE_CHANNEL_FD, 10);
162+
assert(fd >= 0);
163+
164+
// Make sure it's not accidentally inherited by child processes.
165+
delete process.env.NODE_CHANNEL_FD;
166+
167+
var cp = require('child_process');
168+
169+
// Load tcp_wrap to avoid situation where we might immediately receive
170+
// a message.
171+
// FIXME is this really necessary?
172+
process.binding('tcp_wrap');
173+
174+
cp._forkChild(fd);
175+
assert(process.send);
176+
}
177+
}
178+
179+
180+
function setupRawDebug() {
181+
var format = require('util').format;
182+
var rawDebug = process._rawDebug;
183+
process._rawDebug = function() {
184+
rawDebug(format.apply(null, arguments));
185+
};
186+
}

lib/internal/process/next_tick.js

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
'use strict';
2+
3+
exports.setup = setupNextTick;
4+
5+
function setupNextTick() {
6+
const promises = require('internal/process/promises');
7+
const emitPendingUnhandledRejections = promises.setup(scheduleMicrotasks);
8+
var nextTickQueue = [];
9+
var microtasksScheduled = false;
10+
11+
// Used to run V8's micro task queue.
12+
var _runMicrotasks = {};
13+
14+
// *Must* match Environment::TickInfo::Fields in src/env.h.
15+
var kIndex = 0;
16+
var kLength = 1;
17+
18+
process.nextTick = nextTick;
19+
// Needs to be accessible from beyond this scope.
20+
process._tickCallback = _tickCallback;
21+
process._tickDomainCallback = _tickDomainCallback;
22+
23+
// This tickInfo thing is used so that the C++ code in src/node.cc
24+
// can have easy access to our nextTick state, and avoid unnecessary
25+
// calls into JS land.
26+
const tickInfo = process._setupNextTick(_tickCallback, _runMicrotasks);
27+
28+
_runMicrotasks = _runMicrotasks.runMicrotasks;
29+
30+
function tickDone() {
31+
if (tickInfo[kLength] !== 0) {
32+
if (tickInfo[kLength] <= tickInfo[kIndex]) {
33+
nextTickQueue = [];
34+
tickInfo[kLength] = 0;
35+
} else {
36+
nextTickQueue.splice(0, tickInfo[kIndex]);
37+
tickInfo[kLength] = nextTickQueue.length;
38+
}
39+
}
40+
tickInfo[kIndex] = 0;
41+
}
42+
43+
function scheduleMicrotasks() {
44+
if (microtasksScheduled)
45+
return;
46+
47+
nextTickQueue.push({
48+
callback: runMicrotasksCallback,
49+
domain: null
50+
});
51+
52+
tickInfo[kLength]++;
53+
microtasksScheduled = true;
54+
}
55+
56+
function runMicrotasksCallback() {
57+
microtasksScheduled = false;
58+
_runMicrotasks();
59+
60+
if (tickInfo[kIndex] < tickInfo[kLength] ||
61+
emitPendingUnhandledRejections())
62+
scheduleMicrotasks();
63+
}
64+
65+
function _combinedTickCallback(args, callback) {
66+
if (args === undefined) {
67+
callback();
68+
} else {
69+
switch (args.length) {
70+
case 1:
71+
callback(args[0]);
72+
break;
73+
case 2:
74+
callback(args[0], args[1]);
75+
break;
76+
case 3:
77+
callback(args[0], args[1], args[2]);
78+
break;
79+
default:
80+
callback.apply(null, args);
81+
}
82+
}
83+
}
84+
85+
// Run callbacks that have no domain.
86+
// Using domains will cause this to be overridden.
87+
function _tickCallback() {
88+
var callback, args, tock;
89+
90+
do {
91+
while (tickInfo[kIndex] < tickInfo[kLength]) {
92+
tock = nextTickQueue[tickInfo[kIndex]++];
93+
callback = tock.callback;
94+
args = tock.args;
95+
// Using separate callback execution functions allows direct
96+
// callback invocation with small numbers of arguments to avoid the
97+
// performance hit associated with using `fn.apply()`
98+
_combinedTickCallback(args, callback);
99+
if (1e4 < tickInfo[kIndex])
100+
tickDone();
101+
}
102+
tickDone();
103+
_runMicrotasks();
104+
emitPendingUnhandledRejections();
105+
} while (tickInfo[kLength] !== 0);
106+
}
107+
108+
function _tickDomainCallback() {
109+
var callback, domain, args, tock;
110+
111+
do {
112+
while (tickInfo[kIndex] < tickInfo[kLength]) {
113+
tock = nextTickQueue[tickInfo[kIndex]++];
114+
callback = tock.callback;
115+
domain = tock.domain;
116+
args = tock.args;
117+
if (domain)
118+
domain.enter();
119+
// Using separate callback execution functions allows direct
120+
// callback invocation with small numbers of arguments to avoid the
121+
// performance hit associated with using `fn.apply()`
122+
_combinedTickCallback(args, callback);
123+
if (1e4 < tickInfo[kIndex])
124+
tickDone();
125+
if (domain)
126+
domain.exit();
127+
}
128+
tickDone();
129+
_runMicrotasks();
130+
emitPendingUnhandledRejections();
131+
} while (tickInfo[kLength] !== 0);
132+
}
133+
134+
function TickObject(c, args) {
135+
this.callback = c;
136+
this.domain = process.domain || null;
137+
this.args = args;
138+
}
139+
140+
function nextTick(callback) {
141+
if (typeof callback !== 'function')
142+
throw new TypeError('callback is not a function');
143+
// on the way out, don't bother. it won't get fired anyway.
144+
if (process._exiting)
145+
return;
146+
147+
var args;
148+
if (arguments.length > 1) {
149+
args = new Array(arguments.length - 1);
150+
for (var i = 1; i < arguments.length; i++)
151+
args[i - 1] = arguments[i];
152+
}
153+
154+
nextTickQueue.push(new TickObject(callback, args));
155+
tickInfo[kLength]++;
156+
}
157+
}

0 commit comments

Comments
 (0)