Browse Source

node: allow multiple arguments passed to nextTick

PR-URL: https://github.com/iojs/io.js/pull/1077
Reviewed-by: Colin Ihrig <cjihrig@gmail.com>
v1.8.0-commit
Trevor Norris 10 years ago
parent
commit
10e31ba56c
  1. 2
      doc/api/process.markdown
  2. 4
      lib/_debugger.js
  3. 26
      lib/_http_client.js
  4. 25
      lib/_http_outgoing.js
  5. 6
      lib/_stream_duplex.js
  6. 31
      lib/_stream_readable.js
  7. 22
      lib/_stream_writable.js
  8. 37
      lib/_tls_legacy.js
  9. 12
      lib/child_process.js
  10. 20
      lib/cluster.js
  11. 20
      lib/dgram.js
  12. 10
      lib/dns.js
  13. 8
      lib/fs.js
  14. 34
      lib/net.js
  15. 9
      lib/zlib.js
  16. 18
      src/node.js
  17. 8
      test/message/stdin_messages.out
  18. 7
      test/parallel/test-next-tick.js

2
doc/api/process.markdown

@ -687,7 +687,7 @@ This will generate:
`heapTotal` and `heapUsed` refer to V8's memory usage.
## process.nextTick(callback)
## process.nextTick(callback[, arg][, ...])
* `callback` {Function}

4
lib/_debugger.js

@ -587,9 +587,7 @@ Client.prototype.mirrorObject = function(handle, depth, cb) {
} else {
val = handle;
}
process.nextTick(function() {
cb(null, val);
});
process.nextTick(cb, null, val);
};

26
lib/_http_client.js

@ -166,11 +166,8 @@ ClientRequest.prototype._implicitHeader = function() {
};
ClientRequest.prototype.abort = function() {
var self = this;
if (this.aborted === undefined) {
process.nextTick(function() {
self.emit('abort');
});
process.nextTick(emitAbortNT, this);
}
// Mark as aborting so we can avoid sending queued request data
// This is used as a truthy flag elsewhere. The use of Date.now is for
@ -194,6 +191,11 @@ ClientRequest.prototype.abort = function() {
};
function emitAbortNT(self) {
self.emit('abort');
}
function createHangUpError() {
var error = new Error('socket hang up');
error.code = 'ECONNRESET';
@ -440,12 +442,14 @@ function responseOnEnd() {
socket.removeListener('error', socketErrorListener);
// Mark this socket as available, AFTER user-added end
// handlers have a chance to run.
process.nextTick(function() {
socket.emit('free');
});
process.nextTick(emitFreeNT, socket);
}
}
function emitFreeNT(socket) {
socket.emit('free');
}
function tickOnSocket(req, socket) {
var parser = parsers.alloc();
req.socket = socket;
@ -478,17 +482,17 @@ function tickOnSocket(req, socket) {
}
ClientRequest.prototype.onSocket = function(socket) {
var req = this;
process.nextTick(onSocketNT, this, socket);
};
process.nextTick(function() {
function onSocketNT(req, socket) {
if (req.aborted) {
// If we were aborted while waiting for a socket, skip the whole thing.
socket.emit('free');
} else {
tickOnSocket(req, socket);
}
});
};
}
ClientRequest.prototype._deferToConnect = function(method, arguments_, cb) {
// This function is for calls that need to happen once the socket is

25
lib/_http_outgoing.js

@ -406,14 +406,9 @@ Object.defineProperty(OutgoingMessage.prototype, 'headersSent', {
OutgoingMessage.prototype.write = function(chunk, encoding, callback) {
var self = this;
if (this.finished) {
var err = new Error('write after end');
process.nextTick(function() {
self.emit('error', err);
if (callback) callback(err);
});
process.nextTick(writeAfterEndNT, this, err, callback);
return true;
}
@ -455,11 +450,7 @@ OutgoingMessage.prototype.write = function(chunk, encoding, callback) {
if (this.connection && !this.connection.corked) {
this.connection.cork();
var conn = this.connection;
process.nextTick(function connectionCork() {
if (conn)
conn.uncork();
});
process.nextTick(connectionCorkNT, this.connection);
}
this._send(len.toString(16), 'binary', null);
this._send(crlf_buf, null, null);
@ -475,6 +466,18 @@ OutgoingMessage.prototype.write = function(chunk, encoding, callback) {
};
function writeAfterEndNT(self, err, callback) {
self.emit('error', err);
if (callback) callback(err);
}
function connectionCorkNT(conn) {
if (conn)
conn.uncork();
}
OutgoingMessage.prototype.addTrailers = function(headers) {
this._trailer = '';
var keys = Object.keys(headers);

6
lib/_stream_duplex.js

@ -49,5 +49,9 @@ function onend() {
// no more data can be written.
// But allow more writes to happen in this tick.
process.nextTick(this.end.bind(this));
process.nextTick(onEndNT, this);
}
function onEndNT(self) {
self.end();
}

31
lib/_stream_readable.js

@ -395,9 +395,7 @@ function emitReadable(stream) {
debug('emitReadable', state.flowing);
state.emittedReadable = true;
if (state.sync)
process.nextTick(function() {
emitReadable_(stream);
});
process.nextTick(emitReadable_, stream);
else
emitReadable_(stream);
}
@ -419,9 +417,7 @@ function emitReadable_(stream) {
function maybeReadMore(stream, state) {
if (!state.readingMore) {
state.readingMore = true;
process.nextTick(function() {
maybeReadMore_(stream, state);
});
process.nextTick(maybeReadMore_, stream, state);
}
}
@ -667,11 +663,7 @@ Readable.prototype.on = function(ev, fn) {
state.emittedReadable = false;
state.needReadable = true;
if (!state.reading) {
var self = this;
process.nextTick(function() {
debug('readable nexttick read 0');
self.read(0);
});
process.nextTick(nReadingNextTick, this);
} else if (state.length) {
emitReadable(this, state);
}
@ -682,6 +674,11 @@ Readable.prototype.on = function(ev, fn) {
};
Readable.prototype.addListener = Readable.prototype.on;
function nReadingNextTick(self) {
debug('readable nexttick read 0');
self.read(0);
}
// pause() and resume() are remnants of the legacy readable stream API
// If the user uses them, then switch into old mode.
Readable.prototype.resume = function() {
@ -697,9 +694,7 @@ Readable.prototype.resume = function() {
function resume(stream, state) {
if (!state.resumeScheduled) {
state.resumeScheduled = true;
process.nextTick(function() {
resume_(stream, state);
});
process.nextTick(resume_, stream, state);
}
}
@ -883,13 +878,15 @@ function endReadable(stream) {
if (!state.endEmitted) {
state.ended = true;
process.nextTick(function() {
process.nextTick(endReadableNT, state, stream);
}
}
function endReadableNT(state, stream) {
// Check that we didn't get one last unshift.
if (!state.endEmitted && state.length === 0) {
state.endEmitted = true;
stream.readable = false;
stream.emit('end');
}
});
}
}

22
lib/_stream_writable.js

@ -158,9 +158,7 @@ function writeAfterEnd(stream, cb) {
var er = new Error('write after end');
// TODO: defer error events consistently everywhere, not just the cb
stream.emit('error', er);
process.nextTick(function() {
cb(er);
});
process.nextTick(cb, er);
}
// If we get something that is not a buffer, string, null, or undefined,
@ -178,9 +176,7 @@ function validChunk(stream, state, chunk, cb) {
!state.objectMode) {
var er = new TypeError('Invalid non-string/buffer chunk');
stream.emit('error', er);
process.nextTick(function() {
cb(er);
});
process.nextTick(cb, er);
valid = false;
}
return valid;
@ -298,10 +294,7 @@ function doWrite(stream, state, writev, len, chunk, encoding, cb) {
function onwriteError(stream, state, sync, er, cb) {
if (sync)
process.nextTick(function() {
state.pendingcb--;
cb(er);
});
process.nextTick(onwriteErrorNT, state, cb, er);
else {
state.pendingcb--;
cb(er);
@ -311,6 +304,11 @@ function onwriteError(stream, state, sync, er, cb) {
stream.emit('error', er);
}
function onwriteErrorNT(state, cb, er) {
state.pendingcb--;
cb(er);
}
function onwriteStateUpdate(state) {
state.writing = false;
state.writecb = null;
@ -339,9 +337,7 @@ function onwrite(stream, er) {
}
if (sync) {
process.nextTick(function() {
afterWrite(stream, state, finished, cb);
});
process.nextTick(afterWrite, stream, state, finished, cb);
} else {
afterWrite(stream, state, finished, cb);
}

37
lib/_tls_legacy.js

@ -448,15 +448,17 @@ CryptoStream.prototype.destroy = function(err) {
}
this._opposite.destroy();
var self = this;
process.nextTick(function() {
process.nextTick(destroyNT, this, err);
};
function destroyNT(self, err) {
// Force EOF
self.push(null);
// Emit 'close' event
self.emit('close', err ? true : false);
});
};
}
CryptoStream.prototype._done = function() {
@ -667,8 +669,6 @@ function SecurePair(context, isServer, requestCert, rejectUnauthorized,
options);
}
var self = this;
options || (options = {});
events.EventEmitter.call(this);
@ -737,7 +737,12 @@ function SecurePair(context, isServer, requestCert, rejectUnauthorized,
this.cleartext.init();
this.encrypted.init();
process.nextTick(function() {
process.nextTick(securePairNT, this, options);
}
util.inherits(SecurePair, events.EventEmitter);
function securePairNT(self, options) {
/* The Connection may be destroyed by an abort call */
if (self.ssl) {
self.ssl.start();
@ -749,11 +754,8 @@ function SecurePair(context, isServer, requestCert, rejectUnauthorized,
if (self.ssl && self.ssl.error)
self.error();
}
});
}
util.inherits(SecurePair, events.EventEmitter);
exports.createSecurePair = function(context,
isServer,
@ -835,12 +837,7 @@ exports.pipe = function pipe(pair, socket) {
socket.pipe(pair.encrypted);
pair.encrypted.on('close', function() {
process.nextTick(function() {
// Encrypted should be unpiped from socket to prevent possible
// write after destroy.
pair.encrypted.unpipe(socket);
socket.destroySoon();
});
process.nextTick(pipeCloseNT, pair, socket);
});
pair.fd = socket.fd;
@ -886,3 +883,11 @@ exports.pipe = function pipe(pair, socket) {
return cleartext;
};
function pipeCloseNT(pair, socket) {
// Encrypted should be unpiped from socket to prevent possible
// write after destroy.
pair.encrypted.unpipe(socket);
socket.destroySoon();
}

12
lib/child_process.js

@ -1015,9 +1015,7 @@ function ChildProcess() {
// Do it on nextTick so that the user has one last chance
// to consume the output, if for example they only want to
// start reading the data once the process exits.
process.nextTick(function() {
flushStdio(self);
});
process.nextTick(flushStdio, self);
maybeClose(self);
};
@ -1075,9 +1073,7 @@ ChildProcess.prototype.spawn = function(options) {
err === uv.UV_EMFILE ||
err === uv.UV_ENFILE ||
err === uv.UV_ENOENT) {
process.nextTick(function() {
self._handle.onexit(err);
});
process.nextTick(onErrorNT, self, err);
// There is no point in continuing when we've hit EMFILE or ENFILE
// because we won't be able to set up the stdio file descriptors.
// It's kind of silly that the de facto spec for ENOENT (the test suite)
@ -1138,6 +1134,10 @@ ChildProcess.prototype.spawn = function(options) {
return err;
};
function onErrorNT(self, err) {
self._handle.onexit(err);
}
ChildProcess.prototype.kill = function(sig) {
var signal;

20
lib/cluster.js

@ -241,9 +241,7 @@ function masterInit() {
}
cluster.settings = settings;
if (initialized === true)
return process.nextTick(function() {
cluster.emit('setup', settings);
});
return process.nextTick(setupSettingsNT, settings);
initialized = true;
schedulingPolicy = cluster.schedulingPolicy; // Freeze policy.
assert(schedulingPolicy === SCHED_NONE || schedulingPolicy === SCHED_RR,
@ -253,9 +251,7 @@ function masterInit() {
return /^(--debug|--debug-brk)(=\d+)?$/.test(argv);
});
process.nextTick(function() {
cluster.emit('setup', settings);
});
process.nextTick(setupSettingsNT, settings);
// Send debug signal only if not started in debug mode, this helps a lot
// on windows, because RegisterDebugHandler is not called when node starts
@ -279,6 +275,10 @@ function masterInit() {
});
};
function setupSettingsNT(settings) {
cluster.emit('setup', settings);
}
function createWorkerProcess(id, env) {
var workerEnv = util._extend({}, process.env);
var execArgv = cluster.settings.execArgv.slice();
@ -376,13 +376,15 @@ function masterInit() {
});
worker.process.on('internalMessage', internal(worker, onmessage));
process.nextTick(function() {
cluster.emit('fork', worker);
});
process.nextTick(emitForkNT, worker);
cluster.workers[worker.id] = worker;
return worker;
};
function emitForkNT(worker) {
cluster.emit('fork', worker);
}
cluster.disconnect = function(cb) {
var workers = Object.keys(cluster.workers);
if (workers.length === 0) {

20
lib/dgram.js

@ -321,16 +321,19 @@ Socket.prototype.send = function(buffer,
!!callback);
if (err && callback) {
// don't emit as error, dgram_legacy.js compatibility
process.nextTick(function() {
var ex = exceptionWithHostPort(err, 'send', address, port);
callback(ex);
});
process.nextTick(sendEmitErrorNT, err, address, port, callback);
}
}
});
};
function sendEmitErrorNT(err, address, port, callback) {
var ex = exceptionWithHostPort(err, 'send', address, port);
callback(ex);
}
function afterSend(err) {
if (err) {
err = exceptionWithHostPort(err, 'send', this.address, this.port);
@ -347,14 +350,17 @@ Socket.prototype.close = function(callback) {
this._handle.close();
this._handle = null;
var self = this;
process.nextTick(function() {
self.emit('close');
});
process.nextTick(socketCloseNT, self);
return this;
};
function socketCloseNT(self) {
self.emit('close');
}
Socket.prototype.address = function() {
this._healthCheck();

10
lib/dns.js

@ -61,15 +61,17 @@ function makeAsync(callback) {
// The API already returned, we can invoke the callback immediately.
callback.apply(null, arguments);
} else {
var args = arguments;
process.nextTick(function() {
callback.apply(null, args);
});
process.nextTick(callMakeAsyncCbNT, callback, arguments);
}
};
}
function callMakeAsyncCbNT(callback, args) {
callback.apply(null, args);
}
function onlookup(err, addresses) {
if (err) {
return this.callback(errnoException(err, 'getaddrinfo', this.hostname));

8
lib/fs.js

@ -91,14 +91,16 @@ function nullCheck(path, callback) {
er.code = 'ENOENT';
if (typeof callback !== 'function')
throw er;
process.nextTick(function() {
callback(er);
});
process.nextTick(nullCheckCallNT, callback, er);
return false;
}
return true;
}
function nullCheckCallNT(callback, er) {
callback(er);
}
// Static method to set the stats properties on a Stats object.
fs.Stats = function(
dev,

34
lib/net.js

@ -267,12 +267,14 @@ function writeAfterFIN(chunk, encoding, cb) {
// TODO: defer error events consistently everywhere, not just the cb
self.emit('error', er);
if (typeof cb === 'function') {
process.nextTick(function() {
cb(er);
});
process.nextTick(writeAfterFINNT, cb, er);
}
}
function writeAfterFINNT(cb, er) {
cb(er);
}
exports.Socket = Socket;
exports.Stream = Socket; // Legacy naming.
@ -923,13 +925,7 @@ Socket.prototype.connect = function(options, cb) {
// immediately calls net.Socket.connect() on it (that's us).
// There are no event listeners registered yet so defer the
// error event to the next tick.
process.nextTick(function() {
err.host = options.host;
err.port = options.port;
err.message = err.message + ' ' + options.host + ':' + options.port;
self.emit('error', err);
self._destroy();
});
process.nextTick(connectErrorNT, self, err, options);
} else {
self._unrefTimer();
connect(self,
@ -945,6 +941,15 @@ Socket.prototype.connect = function(options, cb) {
};
function connectErrorNT(self, err, options) {
err.host = options.host;
err.port = options.port;
err.message = err.message + ' ' + options.host + ':' + options.port;
self.emit('error', err);
self._destroy();
}
Socket.prototype.ref = function() {
if (this._handle)
this._handle.ref();
@ -1183,12 +1188,15 @@ Server.prototype._listen2 = function(address, port, addressType, backlog, fd) {
if (this._unref)
this.unref();
process.nextTick(function() {
process.nextTick(emitListeningNT, self);
};
function emitListeningNT(self) {
// ensure handle hasn't closed
if (self._handle)
self.emit('listening');
});
};
}
function listen(self, address, port, addressType, backlog, fd, exclusive) {

9
lib/zlib.js

@ -455,12 +455,13 @@ Zlib.prototype.close = function(callback) {
this._handle.close();
var self = this;
process.nextTick(function() {
self.emit('close');
});
process.nextTick(emitCloseNT, this);
};
function emitCloseNT(self) {
self.emit('close');
}
Zlib.prototype._transform = function(chunk, encoding, cb) {
var flushFlag;
var ws = this._writableState;

18
src/node.js

@ -337,7 +337,10 @@
callback = tock.callback;
threw = true;
try {
if (tock.args === undefined)
callback();
else
callback.apply(null, tock.args);
threw = false;
} finally {
if (threw)
@ -364,7 +367,10 @@
domain.enter();
threw = true;
try {
if (tock.args === undefined)
callback();
else
callback.apply(null, tock.args);
threw = false;
} finally {
if (threw)
@ -381,9 +387,10 @@
} while (tickInfo[kLength] !== 0);
}
function TickObject(c) {
function TickObject(c, args) {
this.callback = c;
this.domain = process.domain || null;
this.args = args;
}
function nextTick(callback) {
@ -391,7 +398,14 @@
if (process._exiting)
return;
nextTickQueue.push(new TickObject(callback));
var args = undefined;
if (arguments.length > 1) {
args = [];
for (var i = 1; i < arguments.length; i++)
args.push(arguments[i]);
}
nextTickQueue.push(new TickObject(callback, args));
tickInfo[kLength]++;
}

8
test/message/stdin_messages.out

@ -11,7 +11,7 @@ SyntaxError: Strict mode code may not include a with statement
at Socket.<anonymous> (node.js:*:*)
at emitNone (events.js:*:*)
at Socket.emit (events.js:*:*)
at _stream_readable.js:*:*
at endReadableNT (_stream_readable.js:*:*)
at process._tickCallback (node.js:*:*)
42
42
@ -28,7 +28,7 @@ Error: hello
at Socket.<anonymous> (node.js:*:*)
at emitNone (events.js:*:*)
at Socket.emit (events.js:*:*)
at _stream_readable.js:*:*
at endReadableNT (_stream_readable.js:*:*)
at process._tickCallback (node.js:*:*)
[stdin]:1
@ -43,7 +43,7 @@ Error: hello
at Socket.<anonymous> (node.js:*:*)
at emitNone (events.js:*:*)
at Socket.emit (events.js:*:*)
at _stream_readable.js:*:*
at endReadableNT (_stream_readable.js:*:*)
at process._tickCallback (node.js:*:*)
100
@ -59,7 +59,7 @@ ReferenceError: y is not defined
at Socket.<anonymous> (node.js:*:*)
at emitNone (events.js:*:*)
at Socket.emit (events.js:*:*)
at _stream_readable.js:*:*
at endReadableNT (_stream_readable.js:*:*)
at process._tickCallback (node.js:*:*)
[stdin]:1

7
test/parallel/test-next-tick.js

@ -23,6 +23,13 @@ process.nextTick(function() {
complete++;
});
var obj = {};
process.nextTick(function(a, b) {
assert.equal(a, 42);
assert.equal(b, obj);
}, 42, obj);
process.on('exit', function() {
assert.equal(5, complete);
process.nextTick(function() {

Loading…
Cancel
Save