Browse Source

src, lib: update after internal api change

Libuv now returns errors directly.  Make everything in src/ and lib/
follow suit.

The changes to lib/ are not strictly necessary but they remove the need
for the abominations that are process._errno and node::SetErrno().
v0.11.5-release
Ben Noordhuis 12 years ago
parent
commit
ca9eb718fb
  1. 75
      lib/child_process.js
  2. 41
      lib/cluster.js
  3. 79
      lib/dgram.js
  4. 65
      lib/dns.js
  5. 11
      lib/fs.js
  6. 218
      lib/net.js
  7. 12
      lib/tty.js
  8. 260
      src/cares_wrap.cc
  9. 13
      src/fs_event_wrap.cc
  10. 70
      src/node.cc
  11. 2
      src/node.h
  12. 16
      src/node.js
  13. 32
      src/node_file.cc
  14. 15
      src/node_os.cc
  15. 3
      src/node_stat_watcher.cc
  16. 44
      src/pipe_wrap.cc
  17. 20
      src/process_wrap.cc
  18. 10
      src/signal_wrap.cc
  19. 183
      src/stream_wrap.cc
  20. 3
      src/stream_wrap.h
  21. 141
      src/tcp_wrap.cc
  22. 16
      src/timer_wrap.cc
  23. 14
      src/tls_wrap.cc
  24. 21
      src/tty_wrap.cc
  25. 142
      src/udp_wrap.cc

75
lib/child_process.js

@ -23,10 +23,13 @@ var StringDecoder = require('string_decoder').StringDecoder;
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var net = require('net'); var net = require('net');
var dgram = require('dgram'); var dgram = require('dgram');
var Process = process.binding('process_wrap').Process;
var assert = require('assert'); var assert = require('assert');
var util = require('util'); var util = require('util');
var constants; // if (!constants) constants = process.binding('constants');
var Process = process.binding('process_wrap').Process;
var uv = process.binding('uv');
var constants; // Lazy-loaded process.binding('constants')
var errnoException = util._errnoException; var errnoException = util._errnoException;
var handleWraps = {}; var handleWraps = {};
@ -326,7 +329,8 @@ function setupChannel(target, channel) {
var decoder = new StringDecoder('utf8'); var decoder = new StringDecoder('utf8');
var jsonBuffer = ''; var jsonBuffer = '';
channel.buffering = false; channel.buffering = false;
channel.onread = function(pool, recvHandle) { channel.onread = function(nread, pool, recvHandle) {
// TODO(bnoordhuis) Check that nread > 0.
if (pool) { if (pool) {
jsonBuffer += decoder.write(pool); jsonBuffer += decoder.write(pool);
@ -449,22 +453,18 @@ function setupChannel(target, channel) {
return; return;
} }
var req = { oncomplete: nop };
var string = JSON.stringify(message) + '\n'; var string = JSON.stringify(message) + '\n';
var writeReq = channel.writeUtf8String(string, handle); var err = channel.writeUtf8String(req, string, handle);
if (!writeReq) { if (err) {
var er = errnoException(process._errno, this.emit('error', errnoException(err, 'write'));
'write',
'cannot write to IPC channel.');
this.emit('error', er);
} else if (handle && !this._handleQueue) { } else if (handle && !this._handleQueue) {
this._handleQueue = []; this._handleQueue = [];
} }
if (obj && obj.postSend) { if (obj && obj.postSend) {
writeReq.oncomplete = obj.postSend.bind(null, handle); req.oncomplete = obj.postSend.bind(null, handle);
} else {
writeReq.oncomplete = nop;
} }
/* If the master is > 2 read() calls behind, please stop sending. */ /* If the master is > 2 read() calls behind, please stop sending. */
@ -617,7 +617,7 @@ exports.execFile = function(file /* args, options, callback */) {
var exited = false; var exited = false;
var timeoutId; var timeoutId;
var err; var ex;
function exithandler(code, signal) { function exithandler(code, signal) {
if (exited) return; if (exited) return;
@ -630,21 +630,21 @@ exports.execFile = function(file /* args, options, callback */) {
if (!callback) return; if (!callback) return;
if (err) { if (ex) {
callback(err, stdout, stderr); callback(ex, stdout, stderr);
} else if (code === 0 && signal === null) { } else if (code === 0 && signal === null) {
callback(null, stdout, stderr); callback(null, stdout, stderr);
} else { } else {
var e = new Error('Command failed: ' + stderr); ex = new Error('Command failed: ' + stderr);
e.killed = child.killed || killed; ex.killed = child.killed || killed;
e.code = code; ex.code = code < 0 ? uv.errname(code) : code;
e.signal = signal; ex.signal = signal;
callback(e, stdout, stderr); callback(ex, stdout, stderr);
} }
} }
function errorhandler(e) { function errorhandler(e) {
err = e; ex = e;
child.stdout.destroy(); child.stdout.destroy();
child.stderr.destroy(); child.stderr.destroy();
exithandler(); exithandler();
@ -658,7 +658,7 @@ exports.execFile = function(file /* args, options, callback */) {
try { try {
child.kill(options.killSignal); child.kill(options.killSignal);
} catch (e) { } catch (e) {
err = e; ex = e;
exithandler(); exithandler();
} }
} }
@ -676,7 +676,7 @@ exports.execFile = function(file /* args, options, callback */) {
child.stdout.addListener('data', function(chunk) { child.stdout.addListener('data', function(chunk) {
stdout += chunk; stdout += chunk;
if (stdout.length > options.maxBuffer) { if (stdout.length > options.maxBuffer) {
err = new Error('stdout maxBuffer exceeded.'); ex = new Error('stdout maxBuffer exceeded.');
kill(); kill();
} }
}); });
@ -684,7 +684,7 @@ exports.execFile = function(file /* args, options, callback */) {
child.stderr.addListener('data', function(chunk) { child.stderr.addListener('data', function(chunk) {
stderr += chunk; stderr += chunk;
if (stderr.length > options.maxBuffer) { if (stderr.length > options.maxBuffer) {
err = new Error('stderr maxBuffer exceeded.'); ex = new Error('stderr maxBuffer exceeded.');
kill(); kill();
} }
}); });
@ -767,9 +767,9 @@ function ChildProcess() {
// //
// new in 0.9.x: // new in 0.9.x:
// //
// - spawn failures are reported with exitCode == -1 // - spawn failures are reported with exitCode < 0
// //
var err = (exitCode == -1) ? errnoException(process._errno, 'spawn') : null; var err = (exitCode < 0) ? errnoException(exitCode, 'spawn') : null;
if (signalCode) { if (signalCode) {
self.signalCode = signalCode; self.signalCode = signalCode;
@ -784,7 +784,7 @@ function ChildProcess() {
self._handle.close(); self._handle.close();
self._handle = null; self._handle = null;
if (exitCode == -1) { if (exitCode < 0) {
self.emit('error', err); self.emit('error', err);
} else { } else {
self.emit('exit', self.exitCode, self.signalCode); self.emit('exit', self.exitCode, self.signalCode);
@ -913,9 +913,9 @@ ChildProcess.prototype.spawn = function(options) {
options.envPairs.push('NODE_CHANNEL_FD=' + ipcFd); options.envPairs.push('NODE_CHANNEL_FD=' + ipcFd);
} }
var r = this._handle.spawn(options); var err = this._handle.spawn(options);
if (r) { if (err) {
// Close all opened fds on error // Close all opened fds on error
stdio.forEach(function(stdio) { stdio.forEach(function(stdio) {
if (stdio.type === 'pipe') { if (stdio.type === 'pipe') {
@ -925,7 +925,7 @@ ChildProcess.prototype.spawn = function(options) {
this._handle.close(); this._handle.close();
this._handle = null; this._handle = null;
throw errnoException(process._errno, 'spawn'); throw errnoException(err, 'spawn');
} }
this.pid = this._handle.pid; this.pid = this._handle.pid;
@ -966,7 +966,7 @@ ChildProcess.prototype.spawn = function(options) {
// Add .send() method and start listening for IPC data // Add .send() method and start listening for IPC data
if (ipc !== undefined) setupChannel(this, ipc); if (ipc !== undefined) setupChannel(this, ipc);
return r; return err;
}; };
@ -990,19 +990,20 @@ ChildProcess.prototype.kill = function(sig) {
} }
if (this._handle) { if (this._handle) {
var r = this._handle.kill(signal); var err = this._handle.kill(signal);
if (r == 0) { if (err === 0) {
/* Success. */ /* Success. */
this.killed = true; this.killed = true;
return true; return true;
} else if (process._errno == 'ESRCH') { }
if (err === uv.UV_ESRCH) {
/* Already dead. */ /* Already dead. */
} else if (process._errno == 'EINVAL' || process._errno == 'ENOSYS') { } else if (err === uv.UV_EINVAL || err === uv.UV_ENOSYS) {
/* The underlying platform doesn't support this signal. */ /* The underlying platform doesn't support this signal. */
throw errnoException(process._errno, 'kill'); throw errnoException(err, 'kill');
} else { } else {
/* Other error, almost certainly EPERM. */ /* Other error, almost certainly EPERM. */
this.emit('error', errnoException(process._errno, 'kill')); this.emit('error', errnoException(err, 'kill'));
} }
} }

41
lib/cluster.js

@ -58,13 +58,20 @@ function SharedHandle(key, address, port, addressType, backlog, fd) {
this.key = key; this.key = key;
this.errno = ''; this.errno = '';
this.workers = []; this.workers = [];
this.handle = null;
this.errno = 0;
// FIXME(bnoordhuis) Polymorphic return type for lack of a better solution.
var rval;
if (addressType === 'udp4' || addressType === 'udp6') if (addressType === 'udp4' || addressType === 'udp6')
this.handle = dgram._createSocketHandle(address, port, addressType, fd); rval = dgram._createSocketHandle(address, port, addressType, fd);
else else
this.handle = net._createServerHandle(address, port, addressType, fd); rval = net._createServerHandle(address, port, addressType, fd);
this.errno = this.handle ? '' : process._errno; if (typeof rval === 'number')
this.errno = rval;
else
this.handle = rval;
} }
SharedHandle.prototype.add = function(worker, send) { SharedHandle.prototype.add = function(worker, send) {
@ -116,10 +123,15 @@ RoundRobinHandle.prototype.add = function(worker, send) {
var self = this; var self = this;
function done() { function done() {
if (self.handle.getsockname) if (self.handle.getsockname) {
send(null, { sockname: self.handle.getsockname() }, null); var out = {};
else var err = self.handle.getsockname(out);
// TODO(bnoordhuis) Check err.
send(null, { sockname: out }, null);
}
else {
send(null, null, null); // UNIX socket. send(null, null, null); // UNIX socket.
}
self.handoff(worker); // In case there are connections pending. self.handoff(worker); // In case there are connections pending.
} }
@ -143,7 +155,7 @@ RoundRobinHandle.prototype.remove = function(worker) {
return true; return true;
}; };
RoundRobinHandle.prototype.distribute = function(handle) { RoundRobinHandle.prototype.distribute = function(err, handle) {
this.handles.push(handle); this.handles.push(handle);
var worker = this.free.shift(); var worker = this.free.shift();
if (worker) this.handoff(worker); if (worker) this.handoff(worker);
@ -164,7 +176,7 @@ RoundRobinHandle.prototype.handoff = function(worker) {
if (reply.accepted) if (reply.accepted)
handle.close(); handle.close();
else else
self.distribute(handle); // Worker is shutting down. Send to another. self.distribute(0, handle); // Worker is shutting down. Send to another.
self.handoff(worker); self.handoff(worker);
}); });
}; };
@ -476,8 +488,9 @@ function workerInit() {
function onerror(message, cb) { function onerror(message, cb) {
function listen(backlog) { function listen(backlog) {
process._errno = message.errno; // Translate 'EADDRINUSE' error back to numeric value. This function
return -1; // is called as sock._handle.listen().
return process.binding('uv')['UV_' + message.errno];
} }
function close() { function close() {
} }
@ -503,10 +516,8 @@ function workerInit() {
delete handles[key]; delete handles[key];
key = undefined; key = undefined;
} }
function getsockname() { function getsockname(out) {
var rv = {}; if (key) util._extend(out, message.sockname);
if (key) return util._extend(rv, message.sockname);
return rv;
} }
// Faux handle. Mimics a TCPWrap with just enough fidelity to get away // Faux handle. Mimics a TCPWrap with just enough fidelity to get away
// with it. Fools net.Server into thinking that it's backed by a real // with it. Fools net.Server into thinking that it's backed by a real
@ -530,7 +541,7 @@ function workerInit() {
var server = handles[key]; var server = handles[key];
var accepted = (typeof server !== 'undefined'); var accepted = (typeof server !== 'undefined');
send({ ack: message.seq, accepted: accepted }); send({ ack: message.seq, accepted: accepted });
if (accepted) server.onconnection(handle); if (accepted) server.onconnection(0, handle);
} }
Worker.prototype.disconnect = function() { Worker.prototype.disconnect = function() {

79
lib/dgram.js

@ -96,10 +96,10 @@ exports._createSocketHandle = function(address, port, addressType, fd) {
var handle = newHandle(addressType); var handle = newHandle(addressType);
if (port || address) { if (port || address) {
var r = handle.bind(address, port || 0, 0); var err = handle.bind(address, port || 0, 0);
if (r == -1) { if (err) {
handle.close(); handle.close();
handle = null; return err;
} }
} }
@ -204,8 +204,9 @@ Socket.prototype.bind = function(/*port, address, callback*/) {
if (!self._handle) if (!self._handle)
return; // handle has been closed in the mean time return; // handle has been closed in the mean time
if (self._handle.bind(ip, port || 0, /*flags=*/ 0)) { var err = self._handle.bind(ip, port || 0, /*flags=*/ 0);
self.emit('error', errnoException(process._errno, 'bind')); if (err) {
self.emit('error', errnoException(err, 'bind'));
self._bindState = BIND_STATE_UNBOUND; self._bindState = BIND_STATE_UNBOUND;
// Todo: close? // Todo: close?
return; return;
@ -276,22 +277,18 @@ Socket.prototype.send = function(buffer,
return; return;
} }
self._handle.lookup(address, function(err, ip) { self._handle.lookup(address, function(ex, ip) {
if (err) { if (ex) {
if (callback) callback(err); if (callback) callback(ex);
self.emit('error', err); self.emit('error', ex);
} }
else if (self._handle) { else if (self._handle) {
var req = self._handle.send(buffer, offset, length, port, ip); var req = { cb: callback, oncomplete: afterSend };
if (req) { var err = self._handle.send(req, buffer, offset, length, port, ip);
req.oncomplete = afterSend; if (err) {
req.cb = callback;
}
else {
// don't emit as error, dgram_legacy.js compatibility // don't emit as error, dgram_legacy.js compatibility
var err = errnoException(process._errno, 'send');
process.nextTick(function() { process.nextTick(function() {
callback(err); callback(errnoException(err, 'send'));
}); });
} }
} }
@ -319,17 +316,20 @@ Socket.prototype.close = function() {
Socket.prototype.address = function() { Socket.prototype.address = function() {
this._healthCheck(); this._healthCheck();
var address = this._handle.getsockname(); var out = {};
if (!address) var err = this._handle.getsockname(out);
throw errnoException(process._errno, 'getsockname'); if (err) {
throw errnoException(err, 'getsockname');
}
return address; return out;
}; };
Socket.prototype.setBroadcast = function(arg) { Socket.prototype.setBroadcast = function(arg) {
if (this._handle.setBroadcast((arg) ? 1 : 0)) { var err = this._handle.setBroadcast(arg ? 1 : 0);
throw errnoException(process._errno, 'setBroadcast'); if (err) {
throw errnoException(err, 'setBroadcast');
} }
}; };
@ -339,8 +339,9 @@ Socket.prototype.setTTL = function(arg) {
throw new TypeError('Argument must be a number'); throw new TypeError('Argument must be a number');
} }
if (this._handle.setTTL(arg)) { var err = this._handle.setTTL(arg);
throw errnoException(process._errno, 'setTTL'); if (err) {
throw errnoException(err, 'setTTL');
} }
return arg; return arg;
@ -352,8 +353,9 @@ Socket.prototype.setMulticastTTL = function(arg) {
throw new TypeError('Argument must be a number'); throw new TypeError('Argument must be a number');
} }
if (this._handle.setMulticastTTL(arg)) { var err = this._handle.setMulticastTTL(arg);
throw errnoException(process._errno, 'setMulticastTTL'); if (err) {
throw errnoException(err, 'setMulticastTTL');
} }
return arg; return arg;
@ -361,10 +363,9 @@ Socket.prototype.setMulticastTTL = function(arg) {
Socket.prototype.setMulticastLoopback = function(arg) { Socket.prototype.setMulticastLoopback = function(arg) {
arg = arg ? 1 : 0; var err = this._handle.setMulticastLoopback(arg ? 1 : 0);
if (err) {
if (this._handle.setMulticastLoopback(arg)) { throw errnoException(err, 'setMulticastLoopback');
throw errnoException(process._errno, 'setMulticastLoopback');
} }
return arg; // 0.4 compatibility return arg; // 0.4 compatibility
@ -379,8 +380,9 @@ Socket.prototype.addMembership = function(multicastAddress,
throw new Error('multicast address must be specified'); throw new Error('multicast address must be specified');
} }
if (this._handle.addMembership(multicastAddress, interfaceAddress)) { var err = this._handle.addMembership(multicastAddress, interfaceAddress);
throw new errnoException(process._errno, 'addMembership'); if (err) {
throw new errnoException(err, 'addMembership');
} }
}; };
@ -393,8 +395,9 @@ Socket.prototype.dropMembership = function(multicastAddress,
throw new Error('multicast address must be specified'); throw new Error('multicast address must be specified');
} }
if (this._handle.dropMembership(multicastAddress, interfaceAddress)) { var err = this._handle.dropMembership(multicastAddress, interfaceAddress);
throw new errnoException(process._errno, 'dropMembership'); if (err) {
throw new errnoException(err, 'dropMembership');
} }
}; };
@ -415,10 +418,10 @@ Socket.prototype._stopReceiving = function() {
}; };
function onMessage(handle, buf, rinfo) { function onMessage(nread, handle, buf, rinfo) {
var self = handle.owner; var self = handle.owner;
if (!buf) { if (nread < 0) {
return self.emit('error', errnoException(process._errno, 'recvmsg')); return self.emit('error', errnoException(nread, 'recvmsg'));
} }
rinfo.size = buf.length; // compatibility rinfo.size = buf.length; // compatibility
self.emit('message', buf, rinfo); self.emit('message', buf, rinfo);

65
lib/dns.js

@ -19,14 +19,31 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE. // USE OR OTHER DEALINGS IN THE SOFTWARE.
var cares = process.binding('cares_wrap');
var net = require('net'); var net = require('net');
var util = require('util'); var util = require('util');
var errnoException = util._errnoException; var cares = process.binding('cares_wrap');
var uv = process.binding('uv');
var isIp = net.isIP; var isIp = net.isIP;
function errnoException(err, syscall) {
// FIXME(bnoordhuis) Remove this backwards compatibility shite and pass
// the true error to the user. ENOTFOUND is not even a proper POSIX error!
if (err === uv.UV_EAI_MEMORY ||
err === uv.UV_EAI_NODATA ||
err === uv.UV_EAI_NONAME) {
var ex = new Error(syscall + ' ENOTFOUND');
ex.code = 'ENOTFOUND';
ex.errno = 'ENOTFOUND';
ex.syscall = syscall;
return ex;
}
return util._errnoException(err, syscall);
}
// c-ares invokes a callback either synchronously or asynchronously, // c-ares invokes a callback either synchronously or asynchronously,
// but the dns API should always invoke a callback asynchronously. // but the dns API should always invoke a callback asynchronously.
// //
@ -98,28 +115,28 @@ exports.lookup = function(domain, family, callback) {
return {}; return {};
} }
function onanswer(addresses) { function onanswer(err, addresses) {
if (addresses) { if (err) {
if (family) { return callback(errnoException(err, 'getaddrinfo'));
callback(null, addresses[0], family); }
} else { if (family) {
callback(null, addresses[0], addresses[0].indexOf(':') >= 0 ? 6 : 4); callback(null, addresses[0], family);
}
} else { } else {
callback(errnoException(process._errno, 'getaddrinfo')); callback(null, addresses[0], addresses[0].indexOf(':') >= 0 ? 6 : 4);
} }
} }
var wrap = cares.getaddrinfo(domain, family); var req = {};
var err = cares.getaddrinfo(req, domain, family);
if (!wrap) { if (err) {
throw errnoException(process._errno, 'getaddrinfo'); throw errnoException(err, 'getaddrinfo');
} }
wrap.oncomplete = onanswer; req.oncomplete = onanswer;
callback.immediately = true; callback.immediately = true;
return wrap; return req;
}; };
@ -127,22 +144,22 @@ function resolver(bindingName) {
var binding = cares[bindingName]; var binding = cares[bindingName];
return function query(name, callback) { return function query(name, callback) {
function onanswer(status, result) { function onanswer(err, result) {
if (!status) { if (err)
callback(errnoException(err, bindingName));
else
callback(null, result); callback(null, result);
} else {
callback(errnoException(process._errno, bindingName));
}
} }
callback = makeAsync(callback); callback = makeAsync(callback);
var wrap = binding(name, onanswer); var req = {};
if (!wrap) { var err = binding(req, name, onanswer);
throw errnoException(process._errno, bindingName); if (err) {
throw errnoException(err, bindingName);
} }
callback.immediately = true; callback.immediately = true;
return wrap; return req;
} }
} }

11
lib/fs.js

@ -1004,9 +1004,9 @@ function FSWatcher() {
this._handle.owner = this; this._handle.owner = this;
this._handle.onchange = function(status, event, filename) { this._handle.onchange = function(status, event, filename) {
if (status) { if (status < 0) {
self._handle.close(); self._handle.close();
self.emit('error', errnoException(process._errno, 'watch')); self.emit('error', errnoException(status, 'watch'));
} else { } else {
self.emit('change', event, filename); self.emit('change', event, filename);
} }
@ -1016,11 +1016,10 @@ util.inherits(FSWatcher, EventEmitter);
FSWatcher.prototype.start = function(filename, persistent) { FSWatcher.prototype.start = function(filename, persistent) {
nullCheck(filename); nullCheck(filename);
var r = this._handle.start(pathModule._makeLong(filename), persistent); var err = this._handle.start(pathModule._makeLong(filename), persistent);
if (err) {
if (r) {
this._handle.close(); this._handle.close();
throw errnoException(process._errno, 'watch'); throw errnoException(err, 'watch');
} }
}; };

218
lib/net.js

@ -25,6 +25,7 @@ var timers = require('timers');
var util = require('util'); var util = require('util');
var assert = require('assert'); var assert = require('assert');
var cares = process.binding('cares_wrap'); var cares = process.binding('cares_wrap');
var uv = process.binding('uv');
var cluster; var cluster;
var errnoException = util._errnoException; var errnoException = util._errnoException;
@ -206,12 +207,11 @@ function onSocketFinish() {
if (!this._handle || !this._handle.shutdown) if (!this._handle || !this._handle.shutdown)
return this.destroy(); return this.destroy();
var shutdownReq = this._handle.shutdown(); var req = { oncomplete: afterShutdown };
var err = this._handle.shutdown(req);
if (!shutdownReq) if (err)
return this._destroy(errnoException(process._errno, 'shutdown')); return this._destroy(errnoException(err, 'shutdown'));
shutdownReq.oncomplete = afterShutdown;
} }
@ -338,7 +338,10 @@ Socket.prototype.setKeepAlive = function(setting, msecs) {
Socket.prototype.address = function() { Socket.prototype.address = function() {
if (this._handle && this._handle.getsockname) { if (this._handle && this._handle.getsockname) {
return this._handle.getsockname(); var out = {};
var err = this._handle.getsockname(out);
// TODO(bnoordhuis) Check err and throw?
return out;
} }
return null; return null;
}; };
@ -381,9 +384,9 @@ Socket.prototype._read = function(n) {
// not already reading, start the flow // not already reading, start the flow
debug('Socket._read readStart'); debug('Socket._read readStart');
this._handle.reading = true; this._handle.reading = true;
var r = this._handle.readStart(); var err = this._handle.readStart();
if (r) if (err)
this._destroy(errnoException(process._errno, 'read')); this._destroy(errnoException(err, 'read'));
} }
}; };
@ -486,17 +489,16 @@ Socket.prototype.destroy = function(exception) {
// This function is called whenever the handle gets a // This function is called whenever the handle gets a
// buffer, or when there's an error reading. // buffer, or when there's an error reading.
function onread(buffer) { function onread(nread, buffer) {
var handle = this; var handle = this;
var self = handle.owner; var self = handle.owner;
var length = !!buffer ? buffer.length : 0;
assert(handle === self._handle, 'handle != self._handle'); assert(handle === self._handle, 'handle != self._handle');
timers._unrefActive(self); timers._unrefActive(self);
debug('onread', process._errno, length); debug('onread', nread);
if (buffer) { if (nread > 0) {
debug('got data'); debug('got data');
// read success. // read success.
@ -504,16 +506,9 @@ function onread(buffer) {
// will prevent this from being called again until _read() gets // will prevent this from being called again until _read() gets
// called again. // called again.
// if we didn't get any bytes, that doesn't necessarily mean EOF.
// wait for the next one.
if (length === 0) {
debug('not any data, keep waiting');
return;
}
// if it's not enough data, we'll just call handle.readStart() // if it's not enough data, we'll just call handle.readStart()
// again right away. // again right away.
self.bytesRead += length; self.bytesRead += nread;
// Optimization: emit the original buffer with end points // Optimization: emit the original buffer with end points
var ret = true; var ret = true;
@ -523,33 +518,41 @@ function onread(buffer) {
if (handle.reading && !ret) { if (handle.reading && !ret) {
handle.reading = false; handle.reading = false;
debug('readStop'); debug('readStop');
var r = handle.readStop(); var err = handle.readStop();
if (r) if (err)
self._destroy(errnoException(process._errno, 'read')); self._destroy(errnoException(err, 'read'));
} }
return;
}
} else if (process._errno == 'EOF') { // if we didn't get any bytes, that doesn't necessarily mean EOF.
debug('EOF'); // wait for the next one.
if (nread === 0) {
if (self._readableState.length === 0) { debug('not any data, keep waiting');
self.readable = false; return;
maybeDestroy(self); }
}
if (self.onend) self.once('end', self.onend); // Error, possibly EOF.
if (nread !== uv.UV_EOF) {
return self._destroy(errnoException(nread, 'read'));
}
// push a null to signal the end of data. debug('EOF');
self.push(null);
// internal end event so that we know that the actual socket if (self._readableState.length === 0) {
// is no longer readable, and we can start the shutdown self.readable = false;
// procedure. No need to wait for all the data to be consumed. maybeDestroy(self);
self.emit('_socketEnd');
} else {
debug('error', process._errno);
// Error
self._destroy(errnoException(process._errno, 'read'));
} }
if (self.onend) self.once('end', self.onend);
// push a null to signal the end of data.
self.push(null);
// internal end event so that we know that the actual socket
// is no longer readable, and we can start the shutdown
// procedure. No need to wait for all the data to be consumed.
self.emit('_socketEnd');
} }
@ -558,10 +561,10 @@ Socket.prototype._getpeername = function() {
return {}; return {};
} }
if (!this._peername) { if (!this._peername) {
this._peername = this._handle.getpeername(); var out = {};
if (!this._peername) { var err = this._handle.getpeername(out);
return {}; if (err) return {}; // FIXME(bnoordhuis) Throw?
} this._peername = out;
} }
return this._peername; return this._peername;
}; };
@ -582,10 +585,10 @@ Socket.prototype._getsockname = function() {
return {}; return {};
} }
if (!this._sockname) { if (!this._sockname) {
this._sockname = this._handle.getsockname(); var out = {};
if (!this._sockname) { var err = this._handle.getsockname(out);
return {}; if (err) return {}; // FIXME(bnoordhuis) Throw?
} this._sockname = out;
} }
return this._sockname; return this._sockname;
}; };
@ -630,7 +633,9 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) {
return false; return false;
} }
var writeReq; var req = { oncomplete: afterWrite };
var err;
if (writev) { if (writev) {
var chunks = new Array(data.length << 1); var chunks = new Array(data.length << 1);
for (var i = 0; i < data.length; i++) { for (var i = 0; i < data.length; i++) {
@ -640,28 +645,26 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) {
chunks[i * 2] = chunk; chunks[i * 2] = chunk;
chunks[i * 2 + 1] = enc; chunks[i * 2 + 1] = enc;
} }
var writeReq = this._handle.writev(chunks); err = this._handle.writev(req, chunks);
// Retain chunks // Retain chunks
if (writeReq) if (err === 0) req._chunks = chunks;
writeReq._chunks = chunks;
} else { } else {
var enc = Buffer.isBuffer(data) ? 'buffer' : encoding; var enc = Buffer.isBuffer(data) ? 'buffer' : encoding;
var writeReq = createWriteReq(this._handle, data, enc); err = createWriteReq(req, this._handle, data, enc);
} }
if (!writeReq) if (err)
return this._destroy(errnoException(process._errno, 'write'), cb); return this._destroy(errnoException(err, 'write'), cb);
writeReq.oncomplete = afterWrite; this._bytesDispatched += req.bytes;
this._bytesDispatched += writeReq.bytes;
// If it was entirely flushed, we can write some more right now. // If it was entirely flushed, we can write some more right now.
// However, if more is left in the queue, then wait until that clears. // However, if more is left in the queue, then wait until that clears.
if (this._handle.writeQueueSize === 0) if (this._handle.writeQueueSize === 0)
cb(); cb();
else else
writeReq.cb = cb; req.cb = cb;
}; };
@ -698,26 +701,26 @@ function getEncodingId(encoding) {
} }
} }
function createWriteReq(handle, data, encoding) { function createWriteReq(req, handle, data, encoding) {
switch (encoding) { switch (encoding) {
case 'buffer': case 'buffer':
return handle.writeBuffer(data); return handle.writeBuffer(req, data);
case 'utf8': case 'utf8':
case 'utf-8': case 'utf-8':
return handle.writeUtf8String(data); return handle.writeUtf8String(req, data);
case 'ascii': case 'ascii':
return handle.writeAsciiString(data); return handle.writeAsciiString(req, data);
case 'ucs2': case 'ucs2':
case 'ucs-2': case 'ucs-2':
case 'utf16le': case 'utf16le':
case 'utf-16le': case 'utf-16le':
return handle.writeUcs2String(data); return handle.writeUcs2String(req, data);
default: default:
return handle.writeBuffer(new Buffer(data, encoding)); return handle.writeBuffer(req, new Buffer(data, encoding));
} }
} }
@ -758,9 +761,10 @@ function afterWrite(status, handle, req) {
return; return;
} }
if (status) { if (status < 0) {
debug('write failure', errnoException(process._errno, 'write')); var ex = errnoException(status, 'write');
self._destroy(errnoException(process._errno, 'write'), req.cb); debug('write failure', ex);
self._destroy(ex, req.cb);
return; return;
} }
@ -780,33 +784,31 @@ function connect(self, address, port, addressType, localAddress) {
assert.ok(self._connecting); assert.ok(self._connecting);
var err;
if (localAddress) { if (localAddress) {
var r;
if (addressType == 6) { if (addressType == 6) {
r = self._handle.bind6(localAddress); err = self._handle.bind6(localAddress);
} else { } else {
r = self._handle.bind(localAddress); err = self._handle.bind(localAddress);
} }
if (r) { if (err) {
self._destroy(errnoException(process._errno, 'bind')); self._destroy(errnoException(err, 'bind'));
return; return;
} }
} }
var connectReq; var req = { oncomplete: afterConnect };
if (addressType == 6) { if (addressType == 6) {
connectReq = self._handle.connect6(address, port); err = self._handle.connect6(req, address, port);
} else if (addressType == 4) { } else if (addressType == 4) {
connectReq = self._handle.connect(address, port); err = self._handle.connect(req, address, port);
} else { } else {
connectReq = self._handle.connect(address, afterConnect); err = self._handle.connect(req, address, afterConnect);
} }
if (connectReq !== null) { if (err) {
connectReq.oncomplete = afterConnect; self._destroy(errnoException(err, 'connect'));
} else {
self._destroy(errnoException(process._errno, 'connect'));
} }
} }
@ -937,7 +939,7 @@ function afterConnect(status, handle, req, readable, writable) {
} else { } else {
self._connecting = false; self._connecting = false;
self._destroy(errnoException(process._errno, 'connect')); self._destroy(errnoException(status, 'connect'));
} }
} }
@ -992,7 +994,7 @@ function toNumber(x) { return (x = Number(x)) >= 0 ? x : false; }
var createServerHandle = exports._createServerHandle = var createServerHandle = exports._createServerHandle =
function(address, port, addressType, fd) { function(address, port, addressType, fd) {
var r = 0; var err = 0;
// assign handle in listen, and clean up if bind or listen fails // assign handle in listen, and clean up if bind or listen fails
var handle; var handle;
@ -1003,8 +1005,7 @@ var createServerHandle = exports._createServerHandle =
catch (e) { catch (e) {
// Not a fd we can listen on. This will trigger an error. // Not a fd we can listen on. This will trigger an error.
debug('listen invalid fd=' + fd + ': ' + e.message); debug('listen invalid fd=' + fd + ': ' + e.message);
process._errno = 'EINVAL'; // hack, callers expect that errno is set return uv.UV_EINVAL;
return null;
} }
handle.open(fd); handle.open(fd);
handle.readable = true; handle.readable = true;
@ -1026,15 +1027,15 @@ var createServerHandle = exports._createServerHandle =
if (address || port) { if (address || port) {
debug('bind to ' + address); debug('bind to ' + address);
if (addressType == 6) { if (addressType == 6) {
r = handle.bind6(address, port); err = handle.bind6(address, port);
} else { } else {
r = handle.bind(address, port); err = handle.bind(address, port);
} }
} }
if (r) { if (err) {
handle.close(); handle.close();
handle = null; return err;
} }
return handle; return handle;
@ -1044,20 +1045,20 @@ var createServerHandle = exports._createServerHandle =
Server.prototype._listen2 = function(address, port, addressType, backlog, fd) { Server.prototype._listen2 = function(address, port, addressType, backlog, fd) {
debug('listen2', address, port, addressType, backlog); debug('listen2', address, port, addressType, backlog);
var self = this; var self = this;
var r = 0;
// If there is not yet a handle, we need to create one and bind. // If there is not yet a handle, we need to create one and bind.
// In the case of a server sent via IPC, we don't need to do this. // In the case of a server sent via IPC, we don't need to do this.
if (!self._handle) { if (!self._handle) {
debug('_listen2: create a handle'); debug('_listen2: create a handle');
self._handle = createServerHandle(address, port, addressType, fd); var rval = createServerHandle(address, port, addressType, fd);
if (!self._handle) { if (typeof rval === 'number') {
var error = errnoException(process._errno, 'listen'); var error = errnoException(rval, 'listen');
process.nextTick(function() { process.nextTick(function() {
self.emit('error', error); self.emit('error', error);
}); });
return; return;
} }
self._handle = rval;
} else { } else {
debug('_listen2: have a handle already'); debug('_listen2: have a handle already');
} }
@ -1068,10 +1069,10 @@ Server.prototype._listen2 = function(address, port, addressType, backlog, fd) {
// Use a backlog of 512 entries. We pass 511 to the listen() call because // Use a backlog of 512 entries. We pass 511 to the listen() call because
// the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1); // the kernel does: backlogsize = roundup_pow_of_two(backlogsize + 1);
// which will thus give us a backlog of 512 entries. // which will thus give us a backlog of 512 entries.
r = self._handle.listen(backlog || 511); var err = self._handle.listen(backlog || 511);
if (r) { if (err) {
var ex = errnoException(process._errno, 'listen'); var ex = errnoException(err, 'listen');
self._handle.close(); self._handle.close();
self._handle = null; self._handle = null;
process.nextTick(function() { process.nextTick(function() {
@ -1104,9 +1105,15 @@ function listen(self, address, port, addressType, backlog, fd) {
// not actually bound. That's why we check if the actual port matches what // not actually bound. That's why we check if the actual port matches what
// we requested and if not, raise an error. The exception is when port == 0 // we requested and if not, raise an error. The exception is when port == 0
// because that means "any random port". // because that means "any random port".
if (port && handle.getsockname && port != handle.getsockname().port) { if (port && handle.getsockname) {
self.emit('error', errnoException('EADDRINUSE', 'bind')); var out = {};
return; var err = handle.getsockname(out);
if (err === 0 && port !== out.port) {
err = uv.UV_EADDRINUSE;
}
if (err) {
return self.emit('error', errnoException(err, 'bind'));
}
} }
self._handle = handle; self._handle = handle;
@ -1176,7 +1183,10 @@ Server.prototype.listen = function() {
Server.prototype.address = function() { Server.prototype.address = function() {
if (this._handle && this._handle.getsockname) { if (this._handle && this._handle.getsockname) {
return this._handle.getsockname(); var out = {};
var err = this._handle.getsockname(out);
// TODO(bnoordhuis) Check err and throw?
return out;
} else if (this._pipeName) { } else if (this._pipeName) {
return this._pipeName; return this._pipeName;
} else { } else {
@ -1184,14 +1194,14 @@ Server.prototype.address = function() {
} }
}; };
function onconnection(clientHandle) { function onconnection(err, clientHandle) {
var handle = this; var handle = this;
var self = handle.owner; var self = handle.owner;
debug('onconnection'); debug('onconnection');
if (!clientHandle) { if (err) {
self.emit('error', errnoException(process._errno, 'accept')); self.emit('error', errnoException(err, 'accept'));
return; return;
} }

12
lib/tty.js

@ -79,8 +79,9 @@ function WriteStream(fd) {
writable: true writable: true
}); });
var winSize = this._handle.getWindowSize(); var winSize = [];
if (winSize) { var err = this._handle.getWindowSize(winSize);
if (!err) {
this.columns = winSize[0]; this.columns = winSize[0];
this.rows = winSize[1]; this.rows = winSize[1];
} }
@ -95,9 +96,10 @@ WriteStream.prototype.isTTY = true;
WriteStream.prototype._refreshSize = function() { WriteStream.prototype._refreshSize = function() {
var oldCols = this.columns; var oldCols = this.columns;
var oldRows = this.rows; var oldRows = this.rows;
var winSize = this._handle.getWindowSize(); var winSize = [];
if (!winSize) { var err = this._handle.getWindowSize(winSize);
this.emit('error', errnoException(process._errno, 'getWindowSize')); if (err) {
this.emit('error', errnoException(err, 'getWindowSize'));
return; return;
} }
var newCols = winSize[0]; var newCols = winSize[0];

260
src/cares_wrap.cc

@ -228,56 +228,11 @@ static Local<Array> HostentToNames(struct hostent* host) {
} }
static const char* AresErrnoString(int errorno) {
switch (errorno) {
#define ERRNO_CASE(e) case ARES_##e: return #e;
ERRNO_CASE(SUCCESS)
ERRNO_CASE(ENODATA)
ERRNO_CASE(EFORMERR)
ERRNO_CASE(ESERVFAIL)
ERRNO_CASE(ENOTFOUND)
ERRNO_CASE(ENOTIMP)
ERRNO_CASE(EREFUSED)
ERRNO_CASE(EBADQUERY)
ERRNO_CASE(EBADNAME)
ERRNO_CASE(EBADFAMILY)
ERRNO_CASE(EBADRESP)
ERRNO_CASE(ECONNREFUSED)
ERRNO_CASE(ETIMEOUT)
ERRNO_CASE(EOF)
ERRNO_CASE(EFILE)
ERRNO_CASE(ENOMEM)
ERRNO_CASE(EDESTRUCTION)
ERRNO_CASE(EBADSTR)
ERRNO_CASE(EBADFLAGS)
ERRNO_CASE(ENONAME)
ERRNO_CASE(EBADHINTS)
ERRNO_CASE(ENOTINITIALIZED)
ERRNO_CASE(ELOADIPHLPAPI)
ERRNO_CASE(EADDRGETNETWORKPARAMS)
ERRNO_CASE(ECANCELLED)
#undef ERRNO_CASE
default:
assert(0 && "Unhandled c-ares error");
return "(UNKNOWN)";
}
}
static void SetAresErrno(int errorno) {
HandleScope scope(node_isolate);
Local<Value> key = String::NewSymbol("_errno");
Local<Value> value = String::NewSymbol(AresErrnoString(errorno));
Local<Object> process = PersistentToLocal(process_p);
process->Set(key, value);
}
class QueryWrap { class QueryWrap {
public: public:
QueryWrap() { QueryWrap(Local<Object> req_wrap_obj) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
persistent().Reset(node_isolate, Object::New()); persistent().Reset(node_isolate, req_wrap_obj);
} }
virtual ~QueryWrap() { virtual ~QueryWrap() {
@ -355,10 +310,10 @@ class QueryWrap {
void ParseError(int status) { void ParseError(int status) {
assert(status != ARES_SUCCESS); assert(status != ARES_SUCCESS);
SetAresErrno(status);
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
Local<Value> argv[1] = { Integer::New(-1, node_isolate) }; Local<Value> argv[] = {
Integer::New(status, node_isolate)
};
MakeCallback(object(), oncomplete_sym, ARRAY_SIZE(argv), argv); MakeCallback(object(), oncomplete_sym, ARRAY_SIZE(argv), argv);
} }
@ -378,6 +333,9 @@ class QueryWrap {
class QueryAWrap: public QueryWrap { class QueryAWrap: public QueryWrap {
public: public:
QueryAWrap(Local<Object> req_wrap_obj) : QueryWrap(req_wrap_obj) {
}
int Send(const char* name) { int Send(const char* name) {
ares_query(ares_channel, name, ns_c_in, ns_t_a, Callback, GetQueryArg()); ares_query(ares_channel, name, ns_c_in, ns_t_a, Callback, GetQueryArg());
return 0; return 0;
@ -405,6 +363,9 @@ class QueryAWrap: public QueryWrap {
class QueryAaaaWrap: public QueryWrap { class QueryAaaaWrap: public QueryWrap {
public: public:
QueryAaaaWrap(Local<Object> req_wrap_obj) : QueryWrap(req_wrap_obj) {
}
int Send(const char* name) { int Send(const char* name) {
ares_query(ares_channel, ares_query(ares_channel,
name, name,
@ -437,6 +398,9 @@ class QueryAaaaWrap: public QueryWrap {
class QueryCnameWrap: public QueryWrap { class QueryCnameWrap: public QueryWrap {
public: public:
QueryCnameWrap(Local<Object> req_wrap_obj) : QueryWrap(req_wrap_obj) {
}
int Send(const char* name) { int Send(const char* name) {
ares_query(ares_channel, ares_query(ares_channel,
name, name,
@ -472,6 +436,9 @@ class QueryCnameWrap: public QueryWrap {
class QueryMxWrap: public QueryWrap { class QueryMxWrap: public QueryWrap {
public: public:
QueryMxWrap(Local<Object> req_wrap_obj) : QueryWrap(req_wrap_obj) {
}
int Send(const char* name) { int Send(const char* name) {
ares_query(ares_channel, name, ns_c_in, ns_t_mx, Callback, GetQueryArg()); ares_query(ares_channel, name, ns_c_in, ns_t_mx, Callback, GetQueryArg());
return 0; return 0;
@ -511,6 +478,9 @@ class QueryMxWrap: public QueryWrap {
class QueryNsWrap: public QueryWrap { class QueryNsWrap: public QueryWrap {
public: public:
QueryNsWrap(Local<Object> req_wrap_obj) : QueryWrap(req_wrap_obj) {
}
int Send(const char* name) { int Send(const char* name) {
ares_query(ares_channel, name, ns_c_in, ns_t_ns, Callback, GetQueryArg()); ares_query(ares_channel, name, ns_c_in, ns_t_ns, Callback, GetQueryArg());
return 0; return 0;
@ -536,6 +506,9 @@ class QueryNsWrap: public QueryWrap {
class QueryTxtWrap: public QueryWrap { class QueryTxtWrap: public QueryWrap {
public: public:
QueryTxtWrap(Local<Object> req_wrap_obj) : QueryWrap(req_wrap_obj) {
}
int Send(const char* name) { int Send(const char* name) {
ares_query(ares_channel, name, ns_c_in, ns_t_txt, Callback, GetQueryArg()); ares_query(ares_channel, name, ns_c_in, ns_t_txt, Callback, GetQueryArg());
return 0; return 0;
@ -568,6 +541,9 @@ class QueryTxtWrap: public QueryWrap {
class QuerySrvWrap: public QueryWrap { class QuerySrvWrap: public QueryWrap {
public: public:
QuerySrvWrap(Local<Object> req_wrap_obj) : QueryWrap(req_wrap_obj) {
}
int Send(const char* name) { int Send(const char* name) {
ares_query(ares_channel, ares_query(ares_channel,
name, name,
@ -617,6 +593,9 @@ class QuerySrvWrap: public QueryWrap {
class QueryNaptrWrap: public QueryWrap { class QueryNaptrWrap: public QueryWrap {
public: public:
QueryNaptrWrap(Local<Object> req_wrap_obj) : QueryWrap(req_wrap_obj) {
}
int Send(const char* name) { int Send(const char* name) {
ares_query(ares_channel, ares_query(ares_channel,
name, name,
@ -679,18 +658,21 @@ class QueryNaptrWrap: public QueryWrap {
class GetHostByAddrWrap: public QueryWrap { class GetHostByAddrWrap: public QueryWrap {
public: public:
GetHostByAddrWrap(Local<Object> req_wrap_obj) : QueryWrap(req_wrap_obj) {
}
int Send(const char* name) { int Send(const char* name) {
int length, family; int length, family;
char address_buffer[sizeof(struct in6_addr)]; char address_buffer[sizeof(struct in6_addr)];
if (uv_inet_pton(AF_INET, name, &address_buffer).code == UV_OK) { if (uv_inet_pton(AF_INET, name, &address_buffer) == 0) {
length = sizeof(struct in_addr); length = sizeof(struct in_addr);
family = AF_INET; family = AF_INET;
} else if (uv_inet_pton(AF_INET6, name, &address_buffer).code == UV_OK) { } else if (uv_inet_pton(AF_INET6, name, &address_buffer) == 0) {
length = sizeof(struct in6_addr); length = sizeof(struct in6_addr);
family = AF_INET6; family = AF_INET6;
} else { } else {
return ARES_ENOTIMP; return UV_EINVAL; // So errnoException() reports a proper error.
} }
ares_gethostbyaddr(ares_channel, ares_gethostbyaddr(ares_channel,
@ -713,6 +695,9 @@ class GetHostByAddrWrap: public QueryWrap {
class GetHostByNameWrap: public QueryWrap { class GetHostByNameWrap: public QueryWrap {
public: public:
GetHostByNameWrap(Local<Object> req_wrap_obj) : QueryWrap(req_wrap_obj) {
}
int Send(const char* name, int family) { int Send(const char* name, int family) {
ares_gethostbyname(ares_channel, name, family, Callback, GetQueryArg()); ares_gethostbyname(ares_channel, name, family, Callback, GetQueryArg());
return 0; return 0;
@ -735,26 +720,27 @@ static void Query(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
assert(!args.IsConstructCall()); assert(!args.IsConstructCall());
assert(args.Length() >= 2); assert(args[0]->IsObject());
assert(args[1]->IsFunction()); assert(args[1]->IsString());
assert(args[2]->IsFunction());
Wrap* wrap = new Wrap(); Local<Object> req_wrap_obj = args[0].As<Object>();
wrap->SetOnComplete(args[1]); Local<String> string = args[1].As<String>();
Local<Function> callback = args[2].As<Function>();
Wrap* wrap = new Wrap(req_wrap_obj);
wrap->SetOnComplete(callback);
// We must cache the wrap's js object here, because cares might make the // We must cache the wrap's js object here, because cares might make the
// callback from the wrap->Send stack. This will destroy the wrap's internal // callback from the wrap->Send stack. This will destroy the wrap's internal
// object reference, causing wrap->object() to return an empty handle. // object reference, causing wrap->object() to return an empty handle.
Local<Object> object = Local<Object>::New(node_isolate, wrap->persistent()); Local<Object> object = Local<Object>::New(node_isolate, wrap->persistent());
String::Utf8Value name(args[0]); String::Utf8Value name(string);
int err = wrap->Send(*name);
if (err) delete wrap;
int r = wrap->Send(*name); args.GetReturnValue().Set(err);
if (r) {
SetAresErrno(r);
delete wrap;
} else {
args.GetReturnValue().Set(object);
}
} }
@ -763,27 +749,29 @@ static void QueryWithFamily(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
assert(!args.IsConstructCall()); assert(!args.IsConstructCall());
assert(args.Length() >= 3); assert(args[0]->IsObject());
assert(args[2]->IsFunction()); assert(args[1]->IsString());
assert(args[2]->IsInt32());
assert(args[3]->IsFunction());
Local<Object> req_wrap_obj = args[0].As<Object>();
Local<String> string = args[1].As<String>();
int family = args[2]->Int32Value();
Local<Function> callback = args[3].As<Function>();
Wrap* wrap = new Wrap(); Wrap* wrap = new Wrap(req_wrap_obj);
wrap->SetOnComplete(args[2]); wrap->SetOnComplete(callback);
// We must cache the wrap's js object here, because cares might make the // We must cache the wrap's js object here, because cares might make the
// callback from the wrap->Send stack. This will destroy the wrap's internal // callback from the wrap->Send stack. This will destroy the wrap's internal
// object reference, causing wrap->object() to return an empty handle. // object reference, causing wrap->object() to return an empty handle.
Local<Object> object = Local<Object>::New(node_isolate, wrap->persistent()); Local<Object> object = Local<Object>::New(node_isolate, wrap->persistent());
String::Utf8Value name(args[0]); String::Utf8Value name(string);
int family = args[1]->Int32Value(); int err = wrap->Send(*name, family);
if (err) delete wrap;
int r = wrap->Send(*name, family); args.GetReturnValue().Set(err);
if (r) {
SetAresErrno(r);
delete wrap;
} else {
args.GetReturnValue().Set(object);
}
} }
@ -792,13 +780,12 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
GetAddrInfoReqWrap* req_wrap = (GetAddrInfoReqWrap*) req->data; GetAddrInfoReqWrap* req_wrap = (GetAddrInfoReqWrap*) req->data;
Local<Value> argv[1]; Local<Value> argv[] = {
Integer::New(status, node_isolate),
Null(node_isolate)
};
if (status) { if (status == 0) {
// Error
SetErrno(uv_last_error(uv_default_loop()));
argv[0] = Null(node_isolate);
} else {
// Success // Success
struct addrinfo *address; struct addrinfo *address;
int n = 0; int n = 0;
@ -826,11 +813,11 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
if (address->ai_family == AF_INET) { if (address->ai_family == AF_INET) {
// Juggle pointers // Juggle pointers
addr = (char*) &((struct sockaddr_in*) address->ai_addr)->sin_addr; addr = (char*) &((struct sockaddr_in*) address->ai_addr)->sin_addr;
uv_err_t err = uv_inet_ntop(address->ai_family, int err = uv_inet_ntop(address->ai_family,
addr, addr,
ip, ip,
INET6_ADDRSTRLEN); INET6_ADDRSTRLEN);
if (err.code != UV_OK) if (err)
continue; continue;
// Create JavaScript string // Create JavaScript string
@ -852,11 +839,11 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
if (address->ai_family == AF_INET6) { if (address->ai_family == AF_INET6) {
// Juggle pointers // Juggle pointers
addr = (char*) &((struct sockaddr_in6*) address->ai_addr)->sin6_addr; addr = (char*) &((struct sockaddr_in6*) address->ai_addr)->sin6_addr;
uv_err_t err = uv_inet_ntop(address->ai_family, int err = uv_inet_ntop(address->ai_family,
addr, addr,
ip, ip,
INET6_ADDRSTRLEN); INET6_ADDRSTRLEN);
if (err.code != UV_OK) if (err)
continue; continue;
// Create JavaScript string // Create JavaScript string
@ -870,7 +857,7 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
} }
argv[0] = results; argv[1] = results;
} }
uv_freeaddrinfo(res); uv_freeaddrinfo(res);
@ -889,9 +876,9 @@ static void IsIP(const FunctionCallbackInfo<Value>& args) {
char address_buffer[sizeof(struct in6_addr)]; char address_buffer[sizeof(struct in6_addr)];
int rc = 0; int rc = 0;
if (uv_inet_pton(AF_INET, *ip, &address_buffer).code == UV_OK) if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0)
rc = 4; rc = 4;
else if (uv_inet_pton(AF_INET6, *ip, &address_buffer).code == UV_OK) else if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0)
rc = 6; rc = 6;
args.GetReturnValue().Set(rc); args.GetReturnValue().Set(rc);
@ -901,42 +888,45 @@ static void IsIP(const FunctionCallbackInfo<Value>& args) {
static void GetAddrInfo(const FunctionCallbackInfo<Value>& args) { static void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
String::Utf8Value hostname(args[0]); assert(args[0]->IsObject());
assert(args[1]->IsString());
int fam = AF_UNSPEC; assert(args[2]->IsInt32());
if (args[1]->IsInt32()) { Local<Object> req_wrap_obj = args[0].As<Object>();
switch (args[1]->Int32Value()) { String::Utf8Value hostname(args[1]);
case 6:
fam = AF_INET6; int family;
break; switch (args[2]->Int32Value()) {
case 0:
case 4: family = AF_UNSPEC;
fam = AF_INET; break;
break; case 4:
} family = AF_INET;
break;
case 6:
family = AF_INET6;
break;
default:
assert(0 && "bad address family");
abort();
} }
GetAddrInfoReqWrap* req_wrap = new GetAddrInfoReqWrap(); GetAddrInfoReqWrap* req_wrap = new GetAddrInfoReqWrap(req_wrap_obj);
struct addrinfo hints; struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo)); memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = fam; hints.ai_family = family;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
int r = uv_getaddrinfo(uv_default_loop(), int err = uv_getaddrinfo(uv_default_loop(),
&req_wrap->req_, &req_wrap->req_,
AfterGetAddrInfo, AfterGetAddrInfo,
*hostname, *hostname,
NULL, NULL,
&hints); &hints);
req_wrap->Dispatched(); req_wrap->Dispatched();
if (err) delete req_wrap;
if (r) { args.GetReturnValue().Set(err);
SetErrno(uv_last_error(uv_default_loop()));
delete req_wrap;
} else {
args.GetReturnValue().Set(req_wrap->persistent());
}
} }
@ -956,8 +946,8 @@ static void GetServers(const FunctionCallbackInfo<Value>& args) {
char ip[INET6_ADDRSTRLEN]; char ip[INET6_ADDRSTRLEN];
const void* caddr = static_cast<const void*>(&cur->addr); const void* caddr = static_cast<const void*>(&cur->addr);
uv_err_t err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip)); int err = uv_inet_ntop(cur->family, caddr, ip, sizeof(ip));
assert(err.code == UV_OK); assert(err == 0);
Local<String> addr = String::New(ip); Local<String> addr = String::New(ip);
server_array->Set(i, addr); server_array->Set(i, addr);
@ -986,7 +976,7 @@ static void SetServers(const FunctionCallbackInfo<Value>& args) {
ares_addr_node* servers = new ares_addr_node[len]; ares_addr_node* servers = new ares_addr_node[len];
ares_addr_node* last = NULL; ares_addr_node* last = NULL;
uv_err_t uv_ret; int err;
for (uint32_t i = 0; i < len; i++) { for (uint32_t i = 0; i < len; i++) {
assert(arr->Get(i)->IsArray()); assert(arr->Get(i)->IsArray());
@ -1004,18 +994,18 @@ static void SetServers(const FunctionCallbackInfo<Value>& args) {
switch (fam) { switch (fam) {
case 4: case 4:
cur->family = AF_INET; cur->family = AF_INET;
uv_ret = uv_inet_pton(AF_INET, *ip, &cur->addr); err = uv_inet_pton(AF_INET, *ip, &cur->addr);
break; break;
case 6: case 6:
cur->family = AF_INET6; cur->family = AF_INET6;
uv_ret = uv_inet_pton(AF_INET6, *ip, &cur->addr); err = uv_inet_pton(AF_INET6, *ip, &cur->addr);
break; break;
default: default:
assert(0 && "Bad address family."); assert(0 && "Bad address family.");
abort(); abort();
} }
if (uv_ret.code != UV_OK) if (err)
break; break;
cur->next = NULL; cur->next = NULL;
@ -1026,16 +1016,14 @@ static void SetServers(const FunctionCallbackInfo<Value>& args) {
last = cur; last = cur;
} }
int r; if (err == 0)
err = ares_set_servers(ares_channel, &servers[0]);
if (uv_ret.code == UV_OK)
r = ares_set_servers(ares_channel, &servers[0]);
else else
r = ARES_EBADSTR; err = ARES_EBADSTR;
delete[] servers; delete[] servers;
args.GetReturnValue().Set(r); args.GetReturnValue().Set(err);
} }

13
src/fs_event_wrap.cc

@ -108,18 +108,20 @@ void FSEventWrap::Start(const FunctionCallbackInfo<Value>& args) {
String::Utf8Value path(args[0]); String::Utf8Value path(args[0]);
int r = uv_fs_event_init(uv_default_loop(), &wrap->handle_, *path, OnEvent, 0); int err = uv_fs_event_init(uv_default_loop(),
if (r == 0) { &wrap->handle_,
*path,
OnEvent,
0);
if (err == 0) {
// Check for persistent argument // Check for persistent argument
if (!args[1]->IsTrue()) { if (!args[1]->IsTrue()) {
uv_unref(reinterpret_cast<uv_handle_t*>(&wrap->handle_)); uv_unref(reinterpret_cast<uv_handle_t*>(&wrap->handle_));
} }
wrap->initialized_ = true; wrap->initialized_ = true;
} else {
SetErrno(uv_last_error(uv_default_loop()));
} }
args.GetReturnValue().Set(r); args.GetReturnValue().Set(err);
} }
@ -144,7 +146,6 @@ void FSEventWrap::OnEvent(uv_fs_event_t* handle, const char* filename,
// assumption that a rename implicitly means an attribute change. Not too // assumption that a rename implicitly means an attribute change. Not too
// unreasonable, right? Still, we should revisit this before v1.0. // unreasonable, right? Still, we should revisit this before v1.0.
if (status) { if (status) {
SetErrno(uv_last_error(uv_default_loop()));
eventStr = String::Empty(node_isolate); eventStr = String::Empty(node_isolate);
} }
else if (events & UV_RENAME) { else if (events & UV_RENAME) {

70
src/node.cc

@ -774,22 +774,6 @@ Local<Value> ErrnoException(int errorno,
} }
static const char* get_uv_errno_string(int errorno) {
uv_err_t err;
memset(&err, 0, sizeof err);
err.code = (uv_err_code)errorno;
return uv_err_name(err);
}
static const char* get_uv_errno_message(int errorno) {
uv_err_t err;
memset(&err, 0, sizeof err);
err.code = (uv_err_code)errorno;
return uv_strerror(err);
}
// hack alert! copy of ErrnoException, tuned for uv errors // hack alert! copy of ErrnoException, tuned for uv errors
Local<Value> UVException(int errorno, Local<Value> UVException(int errorno,
const char *syscall, const char *syscall,
@ -803,9 +787,9 @@ Local<Value> UVException(int errorno,
} }
if (!msg || !msg[0]) if (!msg || !msg[0])
msg = get_uv_errno_message(errorno); msg = uv_strerror(errorno);
Local<String> estring = String::NewSymbol(get_uv_errno_string(errorno)); Local<String> estring = String::NewSymbol(uv_err_name(errorno));
Local<String> message = String::NewSymbol(msg); Local<String> message = String::NewSymbol(msg);
Local<String> cons1 = String::Concat(estring, String::NewSymbol(", ")); Local<String> cons1 = String::Concat(estring, String::NewSymbol(", "));
Local<String> cons2 = String::Concat(cons1, message); Local<String> cons2 = String::Concat(cons1, message);
@ -1080,25 +1064,6 @@ MakeCallback(const Handle<Object> object,
} }
void SetErrno(uv_err_t err) {
HandleScope scope(node_isolate);
Local<Object> process = PersistentToLocal(process_p);
static Cached<String> errno_symbol;
if (errno_symbol.IsEmpty()) {
errno_symbol = String::New("_errno");
}
if (err.code == UV_UNKNOWN) {
char errno_buf[100];
snprintf(errno_buf, 100, "Unknown system errno %d", err.sys_errno_);
process->Set(errno_symbol, String::New(errno_buf));
} else {
process->Set(errno_symbol, String::NewSymbol(uv_err_name(err)));
}
}
enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) { enum encoding ParseEncoding(Handle<Value> encoding_v, enum encoding _default) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
@ -1356,11 +1321,9 @@ static void Chdir(const FunctionCallbackInfo<Value>& args) {
} }
String::Utf8Value path(args[0]); String::Utf8Value path(args[0]);
int err = uv_chdir(*path);
uv_err_t r = uv_chdir(*path); if (err) {
return ThrowUVException(err, "uv_chdir");
if (r.code != UV_OK) {
return ThrowUVException(r.code, "uv_chdir");
} }
} }
@ -1374,9 +1337,9 @@ static void Cwd(const FunctionCallbackInfo<Value>& args) {
char buf[PATH_MAX + 1]; char buf[PATH_MAX + 1];
#endif #endif
uv_err_t r = uv_cwd(buf, ARRAY_SIZE(buf) - 1); int err = uv_cwd(buf, ARRAY_SIZE(buf) - 1);
if (r.code != UV_OK) { if (err) {
return ThrowUVException(r.code, "uv_cwd"); return ThrowUVException(err, "uv_cwd");
} }
buf[ARRAY_SIZE(buf) - 1] = '\0'; buf[ARRAY_SIZE(buf) - 1] = '\0';
@ -1698,7 +1661,7 @@ void Exit(const FunctionCallbackInfo<Value>& args) {
static void Uptime(const FunctionCallbackInfo<Value>& args) { static void Uptime(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
double uptime; double uptime;
if (uv_uptime(&uptime).code != UV_OK) return; if (uv_uptime(&uptime)) return;
args.GetReturnValue().Set(uptime - prog_start_time); args.GetReturnValue().Set(uptime - prog_start_time);
} }
@ -1708,10 +1671,9 @@ void MemoryUsage(const FunctionCallbackInfo<Value>& args) {
size_t rss; size_t rss;
uv_err_t err = uv_resident_set_memory(&rss); int err = uv_resident_set_memory(&rss);
if (err) {
if (err.code != UV_OK) { return ThrowUVException(err, "uv_resident_set_memory");
return ThrowUVException(err.code, "uv_resident_set_memory");
} }
Local<Object> info = Object::New(); Local<Object> info = Object::New();
@ -1747,12 +1709,8 @@ void Kill(const FunctionCallbackInfo<Value>& args) {
int pid = args[0]->IntegerValue(); int pid = args[0]->IntegerValue();
int sig = args[1]->Int32Value(); int sig = args[1]->Int32Value();
uv_err_t err = uv_kill(pid, sig); int err = uv_kill(pid, sig);
args.GetReturnValue().Set(err);
if (err.code != UV_OK) {
SetErrno(err);
args.GetReturnValue().Set(-1);
}
} }
// used in Hrtime() below // used in Hrtime() below

2
src/node.h

@ -239,8 +239,6 @@ node_module_struct* get_builtin_module(const char *name);
*/ */
NODE_EXTERN void AtExit(void (*cb)(void* arg), void* arg = 0); NODE_EXTERN void AtExit(void (*cb)(void* arg), void* arg = 0);
NODE_EXTERN void SetErrno(uv_err_t err);
} // namespace node } // namespace node
#endif // SRC_NODE_H_ #endif // SRC_NODE_H_

16
src/node.js

@ -626,23 +626,23 @@
}; };
process.kill = function(pid, sig) { process.kill = function(pid, sig) {
var r; var err;
// preserve null signal // preserve null signal
if (0 === sig) { if (0 === sig) {
r = process._kill(pid, 0); err = process._kill(pid, 0);
} else { } else {
sig = sig || 'SIGTERM'; sig = sig || 'SIGTERM';
if (startup.lazyConstants()[sig]) { if (startup.lazyConstants()[sig]) {
r = process._kill(pid, startup.lazyConstants()[sig]); err = process._kill(pid, startup.lazyConstants()[sig]);
} else { } else {
throw new Error('Unknown signal: ' + sig); throw new Error('Unknown signal: ' + sig);
} }
} }
if (r) { if (err) {
var errnoException = NativeModule.require('util')._errnoException; var errnoException = NativeModule.require('util')._errnoException;
throw errnoException(process._errno, 'kill'); throw errnoException(err, 'kill');
} }
return true; return true;
@ -673,11 +673,11 @@
wrap.onsignal = function() { process.emit(type); }; wrap.onsignal = function() { process.emit(type); };
var signum = startup.lazyConstants()[type]; var signum = startup.lazyConstants()[type];
var r = wrap.start(signum); var err = wrap.start(signum);
if (r) { if (err) {
wrap.close(); wrap.close();
var errnoException = NativeModule.require('util')._errnoException; var errnoException = NativeModule.require('util')._errnoException;
throw errnoException(process._errno, 'uv_signal_start'); throw errnoException(err, 'uv_signal_start');
} }
signalWraps[type] = wrap; signalWraps[type] = wrap;

32
src/node_file.cc

@ -104,17 +104,12 @@ static void After(uv_fs_t *req) {
// (Feel free to increase this if you need more) // (Feel free to increase this if you need more)
Local<Value> argv[2]; Local<Value> argv[2];
// NOTE: This may be needed to be changed if something returns a -1 if (req->result < 0) {
// for a success, which is possible.
if (req->result == -1) {
// If the request doesn't have a path parameter set. // If the request doesn't have a path parameter set.
if (req->path == NULL) {
if (!req->path) { argv[0] = UVException(req->result, NULL, req_wrap->syscall());
argv[0] = UVException(req->errorno,
NULL,
req_wrap->syscall());
} else { } else {
argv[0] = UVException(req->errorno, argv[0] = UVException(req->result,
NULL, NULL,
req_wrap->syscall(), req_wrap->syscall(),
static_cast<const char*>(req->path)); static_cast<const char*>(req->path));
@ -225,30 +220,29 @@ struct fs_req_wrap {
#define ASYNC_CALL(func, callback, ...) \ #define ASYNC_CALL(func, callback, ...) \
FSReqWrap* req_wrap = new FSReqWrap(#func); \ FSReqWrap* req_wrap = new FSReqWrap(#func); \
int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_, \ int err = uv_fs_ ## func(uv_default_loop(), &req_wrap->req_, \
__VA_ARGS__, After); \ __VA_ARGS__, After); \
req_wrap->object()->Set(oncomplete_sym, callback); \ req_wrap->object()->Set(oncomplete_sym, callback); \
req_wrap->Dispatched(); \ req_wrap->Dispatched(); \
if (r < 0) { \ if (err < 0) { \
uv_fs_t* req = &req_wrap->req_; \ uv_fs_t* req = &req_wrap->req_; \
req->result = r; \ req->result = err; \
req->path = NULL; \ req->path = NULL; \
req->errorno = uv_last_error(uv_default_loop()).code; \
After(req); \ After(req); \
} \ } \
args.GetReturnValue().Set(req_wrap->persistent()); args.GetReturnValue().Set(req_wrap->persistent());
#define SYNC_CALL(func, path, ...) \ #define SYNC_CALL(func, path, ...) \
fs_req_wrap req_wrap; \ fs_req_wrap req_wrap; \
int result = uv_fs_##func(uv_default_loop(), &req_wrap.req, __VA_ARGS__, NULL); \ int err = uv_fs_ ## func(uv_default_loop(), \
if (result < 0) { \ &req_wrap.req, \
int code = uv_last_error(uv_default_loop()).code; \ __VA_ARGS__, \
return ThrowUVException(code, #func, "", path); \ NULL); \
} if (err < 0) return ThrowUVException(err, #func, NULL, path); \
#define SYNC_REQ req_wrap.req #define SYNC_REQ req_wrap.req
#define SYNC_RESULT result #define SYNC_RESULT err
static void Close(const FunctionCallbackInfo<Value>& args) { static void Close(const FunctionCallbackInfo<Value>& args) {

15
src/node_os.cc

@ -131,8 +131,8 @@ static void GetCPUInfo(const FunctionCallbackInfo<Value>& args) {
uv_cpu_info_t* cpu_infos; uv_cpu_info_t* cpu_infos;
int count, i; int count, i;
uv_err_t err = uv_cpu_info(&cpu_infos, &count); int err = uv_cpu_info(&cpu_infos, &count);
if (err.code != UV_OK) return; if (err) return;
Local<Array> cpus = Array::New(); Local<Array> cpus = Array::New();
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
@ -180,9 +180,8 @@ static void GetTotalMemory(const FunctionCallbackInfo<Value>& args) {
static void GetUptime(const FunctionCallbackInfo<Value>& args) { static void GetUptime(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
double uptime; double uptime;
uv_err_t err = uv_uptime(&uptime); int err = uv_uptime(&uptime);
if (err.code != UV_OK) return; if (err == 0) args.GetReturnValue().Set(uptime);
args.GetReturnValue().Set(uptime);
} }
@ -208,9 +207,9 @@ static void GetInterfaceAddresses(const FunctionCallbackInfo<Value>& args) {
Local<String> name, family; Local<String> name, family;
Local<Array> ifarr; Local<Array> ifarr;
uv_err_t err = uv_interface_addresses(&interfaces, &count); int err = uv_interface_addresses(&interfaces, &count);
if (err.code != UV_OK) { if (err) {
return ThrowUVException(err.code, "uv_interface_addresses"); return ThrowUVException(err, "uv_interface_addresses");
} }
ret = Object::New(); ret = Object::New();

3
src/node_stat_watcher.cc

@ -86,9 +86,6 @@ void StatWatcher::Callback(uv_fs_poll_t* handle,
argv[0] = BuildStatsObject(curr); argv[0] = BuildStatsObject(curr);
argv[1] = BuildStatsObject(prev); argv[1] = BuildStatsObject(prev);
argv[2] = Integer::New(status, node_isolate); argv[2] = Integer::New(status, node_isolate);
if (status == -1) {
SetErrno(uv_last_error(wrap->watcher_->loop));
}
if (onchange_sym.IsEmpty()) { if (onchange_sym.IsEmpty()) {
onchange_sym = String::New("onchange"); onchange_sym = String::New("onchange");
} }

44
src/pipe_wrap.cc

@ -41,6 +41,7 @@ using v8::Object;
using v8::Persistent; using v8::Persistent;
using v8::PropertyAttribute; using v8::PropertyAttribute;
using v8::String; using v8::String;
using v8::Undefined;
using v8::Value; using v8::Value;
static Persistent<Function> pipeConstructor; static Persistent<Function> pipeConstructor;
@ -145,13 +146,8 @@ void PipeWrap::Bind(const FunctionCallbackInfo<Value>& args) {
UNWRAP(PipeWrap) UNWRAP(PipeWrap)
String::AsciiValue name(args[0]); String::AsciiValue name(args[0]);
int err = uv_pipe_bind(&wrap->handle_, *name);
int r = uv_pipe_bind(&wrap->handle_, *name); args.GetReturnValue().Set(err);
// Error starting the pipe.
if (r) SetErrno(uv_last_error(uv_default_loop()));
args.GetReturnValue().Set(r);
} }
@ -174,15 +170,10 @@ void PipeWrap::Listen(const FunctionCallbackInfo<Value>& args) {
UNWRAP(PipeWrap) UNWRAP(PipeWrap)
int backlog = args[0]->Int32Value(); int backlog = args[0]->Int32Value();
int err = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_),
int r = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_), backlog,
backlog, OnConnection);
OnConnection); args.GetReturnValue().Set(err);
// Error starting the pipe.
if (r) SetErrno(uv_last_error(uv_default_loop()));
args.GetReturnValue().Set(r);
} }
@ -197,9 +188,13 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) {
// uv_close() on the handle. // uv_close() on the handle.
assert(wrap->persistent().IsEmpty() == false); assert(wrap->persistent().IsEmpty() == false);
Local<Value> argv[] = {
Integer::New(status, node_isolate),
Undefined()
};
if (status != 0) { if (status != 0) {
SetErrno(uv_last_error(uv_default_loop())); MakeCallback(wrap->object(), "onconnection", ARRAY_SIZE(argv), argv);
MakeCallback(wrap->object(), "onconnection", 0, NULL);
return; return;
} }
@ -215,7 +210,7 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) {
if (uv_accept(handle, client_handle)) return; if (uv_accept(handle, client_handle)) return;
// Successful accept. Call the onconnection callback in JavaScript land. // Successful accept. Call the onconnection callback in JavaScript land.
Local<Value> argv[1] = { client_obj }; argv[1] = client_obj;
if (onconnection_sym.IsEmpty()) { if (onconnection_sym.IsEmpty()) {
onconnection_sym = String::New("onconnection"); onconnection_sym = String::New("onconnection");
} }
@ -236,7 +231,6 @@ void PipeWrap::AfterConnect(uv_connect_t* req, int status) {
bool readable, writable; bool readable, writable;
if (status) { if (status) {
SetErrno(uv_last_error(uv_default_loop()));
readable = writable = 0; readable = writable = 0;
} else { } else {
readable = uv_is_readable(req->handle) != 0; readable = uv_is_readable(req->handle) != 0;
@ -277,18 +271,20 @@ void PipeWrap::Connect(const FunctionCallbackInfo<Value>& args) {
UNWRAP(PipeWrap) UNWRAP(PipeWrap)
String::AsciiValue name(args[0]); assert(args[0]->IsObject());
assert(args[1]->IsString());
ConnectWrap* req_wrap = new ConnectWrap(); Local<Object> req_wrap_obj = args[0].As<Object>();
String::AsciiValue name(args[1]);
ConnectWrap* req_wrap = new ConnectWrap(req_wrap_obj);
uv_pipe_connect(&req_wrap->req_, uv_pipe_connect(&req_wrap->req_,
&wrap->handle_, &wrap->handle_,
*name, *name,
AfterConnect); AfterConnect);
req_wrap->Dispatched(); req_wrap->Dispatched();
args.GetReturnValue().Set(req_wrap->persistent()); args.GetReturnValue().Set(0); // uv_pipe_connect() doesn't return errors.
} }

20
src/process_wrap.cc

@ -217,12 +217,9 @@ class ProcessWrap : public HandleWrap {
options.flags |= UV_PROCESS_DETACHED; options.flags |= UV_PROCESS_DETACHED;
} }
int r = uv_spawn(uv_default_loop(), &wrap->process_, options); int err = uv_spawn(uv_default_loop(), &wrap->process_, options);
if (r) { if (err == 0) {
SetErrno(uv_last_error(uv_default_loop()));
}
else {
assert(wrap->process_.data == wrap); assert(wrap->process_.data == wrap);
wrap->object()->Set(String::New("pid"), wrap->object()->Set(String::New("pid"),
Integer::New(wrap->process_.pid, node_isolate)); Integer::New(wrap->process_.pid, node_isolate));
@ -240,7 +237,7 @@ class ProcessWrap : public HandleWrap {
delete[] options.stdio; delete[] options.stdio;
args.GetReturnValue().Set(r); args.GetReturnValue().Set(err);
} }
static void Kill(const FunctionCallbackInfo<Value>& args) { static void Kill(const FunctionCallbackInfo<Value>& args) {
@ -248,9 +245,8 @@ class ProcessWrap : public HandleWrap {
UNWRAP(ProcessWrap) UNWRAP(ProcessWrap)
int signal = args[0]->Int32Value(); int signal = args[0]->Int32Value();
int r = uv_process_kill(&wrap->process_, signal); int err = uv_process_kill(&wrap->process_, signal);
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(r);
} }
static void OnExit(uv_process_t* handle, int exit_status, int term_signal) { static void OnExit(uv_process_t* handle, int exit_status, int term_signal) {
@ -260,15 +256,11 @@ class ProcessWrap : public HandleWrap {
assert(wrap); assert(wrap);
assert(&wrap->process_ == handle); assert(&wrap->process_ == handle);
Local<Value> argv[2] = { Local<Value> argv[] = {
Integer::New(exit_status, node_isolate), Integer::New(exit_status, node_isolate),
String::New(signo_string(term_signal)) String::New(signo_string(term_signal))
}; };
if (exit_status == -1) {
SetErrno(uv_last_error(uv_default_loop()));
}
if (onexit_sym.IsEmpty()) { if (onexit_sym.IsEmpty()) {
onexit_sym = String::New("onexit"); onexit_sym = String::New("onexit");
} }

10
src/signal_wrap.cc

@ -86,18 +86,16 @@ class SignalWrap : public HandleWrap {
UNWRAP(SignalWrap) UNWRAP(SignalWrap)
int signum = args[0]->Int32Value(); int signum = args[0]->Int32Value();
int r = uv_signal_start(&wrap->handle_, OnSignal, signum); int err = uv_signal_start(&wrap->handle_, OnSignal, signum);
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(r);
} }
static void Stop(const FunctionCallbackInfo<Value>& args) { static void Stop(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
UNWRAP(SignalWrap) UNWRAP(SignalWrap)
int r = uv_signal_stop(&wrap->handle_); int err = uv_signal_stop(&wrap->handle_);
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(r);
} }
static void OnSignal(uv_signal_t* handle, int signum) { static void OnSignal(uv_signal_t* handle, int signum) {

183
src/stream_wrap.cc

@ -45,6 +45,7 @@ using v8::Number;
using v8::Object; using v8::Object;
using v8::PropertyCallbackInfo; using v8::PropertyCallbackInfo;
using v8::String; using v8::String;
using v8::Undefined;
using v8::Value; using v8::Value;
@ -106,17 +107,14 @@ void StreamWrap::ReadStart(const FunctionCallbackInfo<Value>& args) {
bool ipc_pipe = wrap->stream_->type == UV_NAMED_PIPE && bool ipc_pipe = wrap->stream_->type == UV_NAMED_PIPE &&
reinterpret_cast<uv_pipe_t*>(wrap->stream_)->ipc; reinterpret_cast<uv_pipe_t*>(wrap->stream_)->ipc;
int r; int err;
if (ipc_pipe) { if (ipc_pipe) {
r = uv_read2_start(wrap->stream_, OnAlloc, OnRead2); err = uv_read2_start(wrap->stream_, OnAlloc, OnRead2);
} else { } else {
r = uv_read_start(wrap->stream_, OnAlloc, OnRead); err = uv_read_start(wrap->stream_, OnAlloc, OnRead);
} }
// Error starting the tcp. args.GetReturnValue().Set(err);
if (r) SetErrno(uv_last_error(uv_default_loop()));
args.GetReturnValue().Set(r);
} }
@ -125,12 +123,8 @@ void StreamWrap::ReadStop(const FunctionCallbackInfo<Value>& args) {
UNWRAP(StreamWrap) UNWRAP(StreamWrap)
int r = uv_read_stop(wrap->stream_); int err = uv_read_stop(wrap->stream_);
args.GetReturnValue().Set(err);
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()));
args.GetReturnValue().Set(r);
} }
@ -215,48 +209,50 @@ void StreamWrap::WriteBuffer(const FunctionCallbackInfo<Value>& args) {
UNWRAP(StreamWrap) UNWRAP(StreamWrap)
// The first argument is a buffer. assert(args[0]->IsObject());
assert(args.Length() >= 1 && Buffer::HasInstance(args[0])); assert(Buffer::HasInstance(args[1]));
size_t length = Buffer::Length(args[0]);
Local<Object> req_wrap_obj = args[0].As<Object>();
Local<Object> buf_obj = args[1].As<Object>();
size_t length = Buffer::Length(buf_obj);
char* storage = new char[sizeof(WriteWrap)]; char* storage = new char[sizeof(WriteWrap)];
WriteWrap* req_wrap = new (storage) WriteWrap(wrap); WriteWrap* req_wrap = new (storage) WriteWrap(req_wrap_obj, wrap);
Local<Object> req_wrap_obj = req_wrap->object(); req_wrap_obj->SetHiddenValue(buffer_sym, buf_obj);
req_wrap_obj->SetHiddenValue(buffer_sym, args[0]);
uv_buf_t buf; uv_buf_t buf;
WriteBuffer(args[0], &buf); WriteBuffer(buf_obj, &buf);
int r = wrap->callbacks_->DoWrite(req_wrap,
&buf,
1,
NULL,
StreamWrap::AfterWrite);
int err = wrap->callbacks_->DoWrite(req_wrap,
&buf,
1,
NULL,
StreamWrap::AfterWrite);
req_wrap->Dispatched(); req_wrap->Dispatched();
req_wrap_obj->Set(bytes_sym, Integer::NewFromUnsigned(length, node_isolate)); req_wrap_obj->Set(bytes_sym, Integer::NewFromUnsigned(length, node_isolate));
if (r) { if (err) {
SetErrno(uv_last_error(uv_default_loop()));
req_wrap->~WriteWrap(); req_wrap->~WriteWrap();
delete[] storage; delete[] storage;
} else {
args.GetReturnValue().Set(req_wrap->persistent());
} }
args.GetReturnValue().Set(err);
} }
template <enum encoding encoding> template <enum encoding encoding>
void StreamWrap::WriteStringImpl(const FunctionCallbackInfo<Value>& args) { void StreamWrap::WriteStringImpl(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
int r; int err;
UNWRAP(StreamWrap) UNWRAP(StreamWrap)
if (args.Length() < 1) assert(args[0]->IsObject());
return ThrowTypeError("Not enough arguments"); assert(args[1]->IsString());
Local<String> string = args[0]->ToString(); Local<Object> req_wrap_obj = args[0].As<Object>();
Local<String> string = args[1].As<String>();
// Compute the size of the storage that the string will be flattened into. // Compute the size of the storage that the string will be flattened into.
// For UTF8 strings that are very long, go ahead and take the hit for // For UTF8 strings that are very long, go ahead and take the hit for
@ -268,14 +264,12 @@ void StreamWrap::WriteStringImpl(const FunctionCallbackInfo<Value>& args) {
storage_size = StringBytes::StorageSize(string, encoding); storage_size = StringBytes::StorageSize(string, encoding);
if (storage_size > INT_MAX) { if (storage_size > INT_MAX) {
uv_err_t err; args.GetReturnValue().Set(UV_ENOBUFS);
err.code = UV_ENOBUFS;
SetErrno(err);
return; return;
} }
char* storage = new char[sizeof(WriteWrap) + storage_size + 15]; char* storage = new char[sizeof(WriteWrap) + storage_size + 15];
WriteWrap* req_wrap = new (storage) WriteWrap(wrap); WriteWrap* req_wrap = new (storage) WriteWrap(req_wrap_obj, wrap);
char* data = reinterpret_cast<char*>(ROUND_UP( char* data = reinterpret_cast<char*>(ROUND_UP(
reinterpret_cast<uintptr_t>(storage) + sizeof(WriteWrap), 16)); reinterpret_cast<uintptr_t>(storage) + sizeof(WriteWrap), 16));
@ -294,16 +288,16 @@ void StreamWrap::WriteStringImpl(const FunctionCallbackInfo<Value>& args) {
reinterpret_cast<uv_pipe_t*>(wrap->stream_)->ipc; reinterpret_cast<uv_pipe_t*>(wrap->stream_)->ipc;
if (!ipc_pipe) { if (!ipc_pipe) {
r = wrap->callbacks_->DoWrite(req_wrap, err = wrap->callbacks_->DoWrite(req_wrap,
&buf, &buf,
1, 1,
NULL, NULL,
StreamWrap::AfterWrite); StreamWrap::AfterWrite);
} else { } else {
uv_handle_t* send_handle = NULL; uv_handle_t* send_handle = NULL;
if (args[1]->IsObject()) { if (args[2]->IsObject()) {
Local<Object> send_handle_obj = args[1]->ToObject(); Local<Object> send_handle_obj = args[2]->ToObject();
assert(send_handle_obj->InternalFieldCount() > 0); assert(send_handle_obj->InternalFieldCount() > 0);
HandleWrap* send_handle_wrap = static_cast<HandleWrap*>( HandleWrap* send_handle_wrap = static_cast<HandleWrap*>(
send_handle_obj->GetAlignedPointerFromInternalField(0)); send_handle_obj->GetAlignedPointerFromInternalField(0));
@ -318,23 +312,22 @@ void StreamWrap::WriteStringImpl(const FunctionCallbackInfo<Value>& args) {
req_wrap->object()->Set(handle_sym, send_handle_obj); req_wrap->object()->Set(handle_sym, send_handle_obj);
} }
r = wrap->callbacks_->DoWrite(req_wrap, err = wrap->callbacks_->DoWrite(req_wrap,
&buf, &buf,
1, 1,
reinterpret_cast<uv_stream_t*>(send_handle), reinterpret_cast<uv_stream_t*>(send_handle),
StreamWrap::AfterWrite); StreamWrap::AfterWrite);
} }
req_wrap->Dispatched(); req_wrap->Dispatched();
req_wrap->object()->Set(bytes_sym, Number::New(node_isolate, data_size)); req_wrap->object()->Set(bytes_sym, Number::New(node_isolate, data_size));
if (r) { if (err) {
SetErrno(uv_last_error(uv_default_loop()));
req_wrap->~WriteWrap(); req_wrap->~WriteWrap();
delete[] storage; delete[] storage;
} else {
args.GetReturnValue().Set(req_wrap->persistent());
} }
args.GetReturnValue().Set(err);
} }
@ -343,13 +336,11 @@ void StreamWrap::Writev(const FunctionCallbackInfo<Value>& args) {
UNWRAP(StreamWrap) UNWRAP(StreamWrap)
if (args.Length() < 1) assert(args[0]->IsObject());
return ThrowTypeError("Not enough arguments"); assert(args[1]->IsArray());
if (!args[0]->IsArray())
return ThrowTypeError("Argument should be array");
Handle<Array> chunks = args[0].As<Array>(); Local<Object> req_wrap_obj = args[0].As<Object>();
Local<Array> chunks = args[1].As<Array>();
size_t count = chunks->Length() >> 1; size_t count = chunks->Length() >> 1;
uv_buf_t bufs_[16]; uv_buf_t bufs_[16];
@ -377,9 +368,7 @@ void StreamWrap::Writev(const FunctionCallbackInfo<Value>& args) {
} }
if (storage_size > INT_MAX) { if (storage_size > INT_MAX) {
uv_err_t err; args.GetReturnValue().Set(UV_ENOBUFS);
err.code = UV_ENOBUFS;
SetErrno(err);
return; return;
} }
@ -388,7 +377,7 @@ void StreamWrap::Writev(const FunctionCallbackInfo<Value>& args) {
storage_size += sizeof(WriteWrap); storage_size += sizeof(WriteWrap);
char* storage = new char[storage_size]; char* storage = new char[storage_size];
WriteWrap* req_wrap = new (storage) WriteWrap(wrap); WriteWrap* req_wrap = new (storage) WriteWrap(req_wrap_obj, wrap);
uint32_t bytes = 0; uint32_t bytes = 0;
size_t offset = sizeof(WriteWrap); size_t offset = sizeof(WriteWrap);
@ -418,11 +407,11 @@ void StreamWrap::Writev(const FunctionCallbackInfo<Value>& args) {
bytes += str_size; bytes += str_size;
} }
int r = wrap->callbacks_->DoWrite(req_wrap, int err = wrap->callbacks_->DoWrite(req_wrap,
bufs, bufs,
count, count,
NULL, NULL,
StreamWrap::AfterWrite); StreamWrap::AfterWrite);
// Deallocate space // Deallocate space
if (bufs != bufs_) if (bufs != bufs_)
@ -431,13 +420,12 @@ void StreamWrap::Writev(const FunctionCallbackInfo<Value>& args) {
req_wrap->Dispatched(); req_wrap->Dispatched();
req_wrap->object()->Set(bytes_sym, Number::New(node_isolate, bytes)); req_wrap->object()->Set(bytes_sym, Number::New(node_isolate, bytes));
if (r) { if (err) {
SetErrno(uv_last_error(uv_default_loop()));
req_wrap->~WriteWrap(); req_wrap->~WriteWrap();
delete[] storage; delete[] storage;
} else {
args.GetReturnValue().Set(req_wrap->persistent());
} }
args.GetReturnValue().Set(err);
} }
@ -472,10 +460,6 @@ void StreamWrap::AfterWrite(uv_write_t* req, int status) {
req_wrap_obj->Delete(handle_sym); req_wrap_obj->Delete(handle_sym);
} }
if (status) {
SetErrno(uv_last_error(uv_default_loop()));
}
wrap->callbacks_->AfterWrite(req_wrap); wrap->callbacks_->AfterWrite(req_wrap);
Local<Value> argv[] = { Local<Value> argv[] = {
@ -496,24 +480,20 @@ void StreamWrap::Shutdown(const FunctionCallbackInfo<Value>& args) {
UNWRAP(StreamWrap) UNWRAP(StreamWrap)
ShutdownWrap* req_wrap = new ShutdownWrap(); assert(args[0]->IsObject());
Local<Object> req_wrap_obj = args[0].As<Object>();
int r = wrap->callbacks_->DoShutdown(req_wrap, AfterShutdown);
ShutdownWrap* req_wrap = new ShutdownWrap(req_wrap_obj);
int err = wrap->callbacks_->DoShutdown(req_wrap, AfterShutdown);
req_wrap->Dispatched(); req_wrap->Dispatched();
if (err) delete req_wrap;
if (r) { args.GetReturnValue().Set(err);
SetErrno(uv_last_error(uv_default_loop()));
delete req_wrap;
} else {
args.GetReturnValue().Set(req_wrap->persistent());
}
} }
void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) { void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) {
ReqWrap<uv_shutdown_t>* req_wrap = (ReqWrap<uv_shutdown_t>*) req->data; ShutdownWrap* req_wrap = static_cast<ShutdownWrap*>(req->data);
StreamWrap* wrap = (StreamWrap*) req->handle->data; StreamWrap* wrap = static_cast<StreamWrap*>(req->handle->data);
// The wrap and request objects should still be there. // The wrap and request objects should still be there.
assert(req_wrap->persistent().IsEmpty() == false); assert(req_wrap->persistent().IsEmpty() == false);
@ -521,10 +501,6 @@ void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
if (status) {
SetErrno(uv_last_error(uv_default_loop()));
}
Local<Object> req_wrap_obj = req_wrap->object(); Local<Object> req_wrap_obj = req_wrap->object();
Local<Value> argv[3] = { Local<Value> argv[3] = {
Integer::New(status, node_isolate), Integer::New(status, node_isolate),
@ -589,11 +565,16 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle,
uv_handle_type pending) { uv_handle_type pending) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
Local<Value> argv[] = {
Integer::New(nread, node_isolate),
Undefined(),
Undefined()
};
if (nread < 0) { if (nread < 0) {
if (buf.base != NULL) if (buf.base != NULL)
free(buf.base); free(buf.base);
SetErrno(uv_last_error(uv_default_loop())); MakeCallback(Self(), onread_sym, ARRAY_SIZE(argv), argv);
MakeCallback(Self(), onread_sym, 0, NULL);
return; return;
} }
@ -604,13 +585,8 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle,
} }
buf.base = static_cast<char*>(realloc(buf.base, nread)); buf.base = static_cast<char*>(realloc(buf.base, nread));
assert(static_cast<size_t>(nread) <= buf.len); assert(static_cast<size_t>(nread) <= buf.len);
argv[1] = Buffer::Use(buf.base, nread);
int argc = 1;
Local<Value> argv[2] = {
Buffer::Use(buf.base, nread)
};
Local<Object> pending_obj; Local<Object> pending_obj;
if (pending == UV_TCP) { if (pending == UV_TCP) {
@ -624,11 +600,10 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle,
} }
if (!pending_obj.IsEmpty()) { if (!pending_obj.IsEmpty()) {
argv[1] = pending_obj; argv[2] = pending_obj;
argc++;
} }
MakeCallback(wrap_->object(), onread_sym, argc, argv); MakeCallback(wrap_->object(), onread_sym, ARRAY_SIZE(argv), argv);
} }

3
src/stream_wrap.h

@ -37,7 +37,8 @@ typedef class ReqWrap<uv_shutdown_t> ShutdownWrap;
class WriteWrap: public ReqWrap<uv_write_t> { class WriteWrap: public ReqWrap<uv_write_t> {
public: public:
explicit WriteWrap(StreamWrap* wrap) { explicit WriteWrap(v8::Local<v8::Object> obj, StreamWrap* wrap)
: ReqWrap<uv_write_t>(obj) {
wrap_ = wrap; wrap_ = wrap;
} }

141
src/tcp_wrap.cc

@ -39,11 +39,11 @@ using v8::Handle;
using v8::HandleScope; using v8::HandleScope;
using v8::Integer; using v8::Integer;
using v8::Local; using v8::Local;
using v8::Null;
using v8::Object; using v8::Object;
using v8::Persistent; using v8::Persistent;
using v8::PropertyAttribute; using v8::PropertyAttribute;
using v8::String; using v8::String;
using v8::Undefined;
using v8::Value; using v8::Value;
static Persistent<Function> tcpConstructor; static Persistent<Function> tcpConstructor;
@ -168,14 +168,19 @@ void TCPWrap::GetSockName(const FunctionCallbackInfo<Value>& args) {
UNWRAP(TCPWrap) UNWRAP(TCPWrap)
assert(args[0]->IsObject());
Local<Object> out = args[0].As<Object>();
int addrlen = sizeof(address); int addrlen = sizeof(address);
int r = uv_tcp_getsockname(&wrap->handle_, int err = uv_tcp_getsockname(&wrap->handle_,
reinterpret_cast<sockaddr*>(&address), reinterpret_cast<sockaddr*>(&address),
&addrlen); &addrlen);
if (r) return SetErrno(uv_last_error(uv_default_loop())); if (err == 0) {
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
AddressToJS(addr, out);
}
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(AddressToJS(addr));
} }
@ -185,14 +190,19 @@ void TCPWrap::GetPeerName(const FunctionCallbackInfo<Value>& args) {
UNWRAP(TCPWrap) UNWRAP(TCPWrap)
assert(args[0]->IsObject());
Local<Object> out = args[0].As<Object>();
int addrlen = sizeof(address); int addrlen = sizeof(address);
int r = uv_tcp_getpeername(&wrap->handle_, int err = uv_tcp_getpeername(&wrap->handle_,
reinterpret_cast<sockaddr*>(&address), reinterpret_cast<sockaddr*>(&address),
&addrlen); &addrlen);
if (r) return SetErrno(uv_last_error(uv_default_loop())); if (err == 0) {
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
AddressToJS(addr, out);
}
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(AddressToJS(addr));
} }
@ -202,8 +212,8 @@ void TCPWrap::SetNoDelay(const FunctionCallbackInfo<Value>& args) {
UNWRAP(TCPWrap) UNWRAP(TCPWrap)
int enable = static_cast<int>(args[0]->BooleanValue()); int enable = static_cast<int>(args[0]->BooleanValue());
int r = uv_tcp_nodelay(&wrap->handle_, enable); int err = uv_tcp_nodelay(&wrap->handle_, enable);
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
} }
@ -215,8 +225,8 @@ void TCPWrap::SetKeepAlive(const FunctionCallbackInfo<Value>& args) {
int enable = args[0]->Int32Value(); int enable = args[0]->Int32Value();
unsigned int delay = args[1]->Uint32Value(); unsigned int delay = args[1]->Uint32Value();
int r = uv_tcp_keepalive(&wrap->handle_, enable, delay); int err = uv_tcp_keepalive(&wrap->handle_, enable, delay);
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
} }
@ -227,8 +237,8 @@ void TCPWrap::SetSimultaneousAccepts(const FunctionCallbackInfo<Value>& args) {
UNWRAP(TCPWrap) UNWRAP(TCPWrap)
bool enable = args[0]->BooleanValue(); bool enable = args[0]->BooleanValue();
int r = uv_tcp_simultaneous_accepts(&wrap->handle_, enable ? 1 : 0); int err = uv_tcp_simultaneous_accepts(&wrap->handle_, enable);
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
} }
#endif #endif
@ -250,12 +260,9 @@ void TCPWrap::Bind(const FunctionCallbackInfo<Value>& args) {
int port = args[1]->Int32Value(); int port = args[1]->Int32Value();
struct sockaddr_in address = uv_ip4_addr(*ip_address, port); struct sockaddr_in address = uv_ip4_addr(*ip_address, port);
int r = uv_tcp_bind(&wrap->handle_, address); int err = uv_tcp_bind(&wrap->handle_, address);
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()));
args.GetReturnValue().Set(r); args.GetReturnValue().Set(err);
} }
@ -268,12 +275,9 @@ void TCPWrap::Bind6(const FunctionCallbackInfo<Value>& args) {
int port = args[1]->Int32Value(); int port = args[1]->Int32Value();
struct sockaddr_in6 address = uv_ip6_addr(*ip6_address, port); struct sockaddr_in6 address = uv_ip6_addr(*ip6_address, port);
int r = uv_tcp_bind6(&wrap->handle_, address); int err = uv_tcp_bind6(&wrap->handle_, address);
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()));
args.GetReturnValue().Set(r); args.GetReturnValue().Set(err);
} }
@ -283,15 +287,10 @@ void TCPWrap::Listen(const FunctionCallbackInfo<Value>& args) {
UNWRAP(TCPWrap) UNWRAP(TCPWrap)
int backlog = args[0]->Int32Value(); int backlog = args[0]->Int32Value();
int err = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_),
int r = uv_listen(reinterpret_cast<uv_stream_t*>(&wrap->handle_), backlog,
backlog, OnConnection);
OnConnection); args.GetReturnValue().Set(err);
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()));
args.GetReturnValue().Set(r);
} }
@ -305,7 +304,10 @@ void TCPWrap::OnConnection(uv_stream_t* handle, int status) {
// uv_close() on the handle. // uv_close() on the handle.
assert(wrap->persistent().IsEmpty() == false); assert(wrap->persistent().IsEmpty() == false);
Local<Value> argv[1]; Local<Value> argv[2] = {
Integer::New(status, node_isolate),
Undefined()
};
if (status == 0) { if (status == 0) {
// Instantiate the client javascript object and handle. // Instantiate the client javascript object and handle.
@ -321,10 +323,7 @@ void TCPWrap::OnConnection(uv_stream_t* handle, int status) {
if (uv_accept(handle, client_handle)) return; if (uv_accept(handle, client_handle)) return;
// Successful accept. Call the onconnection callback in JavaScript land. // Successful accept. Call the onconnection callback in JavaScript land.
argv[0] = client_obj; argv[1] = client_obj;
} else {
SetErrno(uv_last_error(uv_default_loop()));
argv[0] = Null(node_isolate);
} }
MakeCallback(wrap->object(), onconnection_sym, ARRAY_SIZE(argv), argv); MakeCallback(wrap->object(), onconnection_sym, ARRAY_SIZE(argv), argv);
@ -341,10 +340,6 @@ void TCPWrap::AfterConnect(uv_connect_t* req, int status) {
assert(req_wrap->persistent().IsEmpty() == false); assert(req_wrap->persistent().IsEmpty() == false);
assert(wrap->persistent().IsEmpty() == false); assert(wrap->persistent().IsEmpty() == false);
if (status) {
SetErrno(uv_last_error(uv_default_loop()));
}
Local<Object> req_wrap_obj = req_wrap->object(); Local<Object> req_wrap_obj = req_wrap->object();
Local<Value> argv[5] = { Local<Value> argv[5] = {
Integer::New(status, node_isolate), Integer::New(status, node_isolate),
@ -364,27 +359,29 @@ void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
UNWRAP(TCPWrap) UNWRAP(TCPWrap)
String::AsciiValue ip_address(args[0]); assert(args[0]->IsObject());
int port = args[1]->Int32Value(); assert(args[1]->IsString());
assert(args[2]->Uint32Value());
Local<Object> req_wrap_obj = args[0].As<Object>();
String::AsciiValue ip_address(args[1]);
int port = args[2]->Uint32Value();
struct sockaddr_in address = uv_ip4_addr(*ip_address, port); struct sockaddr_in address = uv_ip4_addr(*ip_address, port);
// I hate when people program C++ like it was C, and yet I do it too. // I hate when people program C++ like it was C, and yet I do it too.
// I'm too lazy to come up with the perfect class hierarchy here. Let's // I'm too lazy to come up with the perfect class hierarchy here. Let's
// just do some type munging. // just do some type munging.
ConnectWrap* req_wrap = new ConnectWrap(); ConnectWrap* req_wrap = new ConnectWrap(req_wrap_obj);
int r = uv_tcp_connect(&req_wrap->req_, &wrap->handle_, address,
AfterConnect);
int err = uv_tcp_connect(&req_wrap->req_,
&wrap->handle_,
address,
AfterConnect);
req_wrap->Dispatched(); req_wrap->Dispatched();
if (err) delete req_wrap;
if (r) { args.GetReturnValue().Set(err);
SetErrno(uv_last_error(uv_default_loop()));
delete req_wrap;
} else {
args.GetReturnValue().Set(req_wrap->persistent());
}
} }
@ -393,24 +390,26 @@ void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
UNWRAP(TCPWrap) UNWRAP(TCPWrap)
String::AsciiValue ip_address(args[0]); assert(args[0]->IsObject());
int port = args[1]->Int32Value(); assert(args[1]->IsString());
assert(args[2]->Uint32Value());
struct sockaddr_in6 address = uv_ip6_addr(*ip_address, port); Local<Object> req_wrap_obj = args[0].As<Object>();
String::AsciiValue ip_address(args[1]);
int port = args[2]->Int32Value();
ConnectWrap* req_wrap = new ConnectWrap(); struct sockaddr_in6 address = uv_ip6_addr(*ip_address, port);
int r = uv_tcp_connect6(&req_wrap->req_, &wrap->handle_, address, ConnectWrap* req_wrap = new ConnectWrap(req_wrap_obj);
AfterConnect);
int err = uv_tcp_connect6(&req_wrap->req_,
&wrap->handle_,
address,
AfterConnect);
req_wrap->Dispatched(); req_wrap->Dispatched();
if (err) delete req_wrap;
if (r) { args.GetReturnValue().Set(err);
SetErrno(uv_last_error(uv_default_loop()));
delete req_wrap;
} else {
args.GetReturnValue().Set(req_wrap->persistent());
}
} }

16
src/timer_wrap.cc

@ -90,27 +90,24 @@ class TimerWrap : public HandleWrap {
int64_t timeout = args[0]->IntegerValue(); int64_t timeout = args[0]->IntegerValue();
int64_t repeat = args[1]->IntegerValue(); int64_t repeat = args[1]->IntegerValue();
int r = uv_timer_start(&wrap->handle_, OnTimeout, timeout, repeat); int err = uv_timer_start(&wrap->handle_, OnTimeout, timeout, repeat);
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(r);
} }
static void Stop(const FunctionCallbackInfo<Value>& args) { static void Stop(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
UNWRAP(TimerWrap) UNWRAP(TimerWrap)
int r = uv_timer_stop(&wrap->handle_); int err = uv_timer_stop(&wrap->handle_);
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(r);
} }
static void Again(const FunctionCallbackInfo<Value>& args) { static void Again(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
UNWRAP(TimerWrap) UNWRAP(TimerWrap)
int r = uv_timer_again(&wrap->handle_); int err = uv_timer_again(&wrap->handle_);
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(r);
} }
static void SetRepeat(const FunctionCallbackInfo<Value>& args) { static void SetRepeat(const FunctionCallbackInfo<Value>& args) {
@ -127,7 +124,6 @@ class TimerWrap : public HandleWrap {
UNWRAP(TimerWrap) UNWRAP(TimerWrap)
int64_t repeat = uv_timer_get_repeat(&wrap->handle_); int64_t repeat = uv_timer_get_repeat(&wrap->handle_);
if (repeat < 0) SetErrno(uv_last_error(uv_default_loop()));
args.GetReturnValue().Set(static_cast<double>(repeat)); args.GetReturnValue().Set(static_cast<double>(repeat));
} }

14
src/tls_wrap.cc

@ -418,7 +418,6 @@ void TLSCallbacks::EncOutCb(uv_write_t* req, int status) {
return; return;
// Notify about error // Notify about error
SetErrno(uv_last_error(uv_default_loop()));
Local<Value> arg = String::Concat( Local<Value> arg = String::Concat(
String::New("write cb error, status: "), String::New("write cb error, status: "),
Integer::New(status, node_isolate)->ToString()); Integer::New(status, node_isolate)->ToString());
@ -483,8 +482,11 @@ void TLSCallbacks::ClearOut() {
do { do {
read = SSL_read(ssl_, out, sizeof(out)); read = SSL_read(ssl_, out, sizeof(out));
if (read > 0) { if (read > 0) {
Handle<Value> buf = Buffer::New(out, read); Local<Value> argv[] = {
MakeCallback(Self(), onread_sym, 1, &buf); Integer::New(read, node_isolate),
Buffer::New(out, read)
};
MakeCallback(Self(), onread_sym, ARRAY_SIZE(argv), argv);
} }
} while (read > 0); } while (read > 0);
@ -621,12 +623,10 @@ void TLSCallbacks::DoRead(uv_stream_t* handle,
uv_buf_t buf, uv_buf_t buf,
uv_handle_type pending) { uv_handle_type pending) {
if (nread < 0) { if (nread < 0) {
uv_err_t err = uv_last_error(uv_default_loop());
SetErrno(err);
// Error should be emitted only after all data was read // Error should be emitted only after all data was read
ClearOut(); ClearOut();
MakeCallback(Self(), onread_sym, 0, NULL); Local<Value> arg = Integer::New(nread, node_isolate);
MakeCallback(Self(), onread_sym, 1, &arg);
return; return;
} }

21
src/tty_wrap.cc

@ -29,6 +29,7 @@
namespace node { namespace node {
using v8::Array;
using v8::Function; using v8::Function;
using v8::FunctionCallbackInfo; using v8::FunctionCallbackInfo;
using v8::FunctionTemplate; using v8::FunctionTemplate;
@ -131,15 +132,18 @@ void TTYWrap::GetWindowSize(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
UNWRAP(TTYWrap) UNWRAP(TTYWrap)
assert(args[0]->IsArray());
int width, height; int width, height;
int r = uv_tty_get_winsize(&wrap->handle_, &width, &height); int err = uv_tty_get_winsize(&wrap->handle_, &width, &height);
if (r) return SetErrno(uv_last_error(uv_default_loop()));
Local<v8::Array> a = v8::Array::New(2); if (err == 0) {
a->Set(0, Integer::New(width, node_isolate)); Local<v8::Array> a = args[0].As<Array>();
a->Set(1, Integer::New(height, node_isolate)); a->Set(0, Integer::New(width, node_isolate));
args.GetReturnValue().Set(a); a->Set(1, Integer::New(height, node_isolate));
}
args.GetReturnValue().Set(err);
} }
@ -148,9 +152,8 @@ void TTYWrap::SetRawMode(const FunctionCallbackInfo<Value>& args) {
UNWRAP(TTYWrap) UNWRAP(TTYWrap)
int r = uv_tty_set_mode(&wrap->handle_, args[0]->IsTrue()); int err = uv_tty_set_mode(&wrap->handle_, args[0]->IsTrue());
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(r);
} }

142
src/udp_wrap.cc

@ -43,6 +43,7 @@ using v8::PropertyAttribute;
using v8::PropertyCallbackInfo; using v8::PropertyCallbackInfo;
using v8::String; using v8::String;
using v8::Uint32; using v8::Uint32;
using v8::Undefined;
using v8::Value; using v8::Value;
typedef ReqWrap<uv_udp_send_t> SendWrap; typedef ReqWrap<uv_udp_send_t> SendWrap;
@ -128,7 +129,7 @@ void UDPWrap::GetFD(Local<String>, const PropertyCallbackInfo<Value>& args) {
void UDPWrap::DoBind(const FunctionCallbackInfo<Value>& args, int family) { void UDPWrap::DoBind(const FunctionCallbackInfo<Value>& args, int family) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
int r; int err;
UNWRAP(UDPWrap) UNWRAP(UDPWrap)
@ -141,18 +142,17 @@ void UDPWrap::DoBind(const FunctionCallbackInfo<Value>& args, int family) {
switch (family) { switch (family) {
case AF_INET: case AF_INET:
r = uv_udp_bind(&wrap->handle_, uv_ip4_addr(*address, port), flags); err = uv_udp_bind(&wrap->handle_, uv_ip4_addr(*address, port), flags);
break; break;
case AF_INET6: case AF_INET6:
r = uv_udp_bind6(&wrap->handle_, uv_ip6_addr(*address, port), flags); err = uv_udp_bind6(&wrap->handle_, uv_ip6_addr(*address, port), flags);
break; break;
default: default:
assert(0 && "unexpected address family"); assert(0 && "unexpected address family");
abort(); abort();
} }
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(r);
} }
@ -172,9 +172,8 @@ void UDPWrap::Bind6(const FunctionCallbackInfo<Value>& args) {
UNWRAP(UDPWrap) \ UNWRAP(UDPWrap) \
assert(args.Length() == 1); \ assert(args.Length() == 1); \
int flag = args[0]->Int32Value(); \ int flag = args[0]->Int32Value(); \
int r = fn(&wrap->handle_, flag); \ int err = fn(&wrap->handle_, flag); \
if (r) SetErrno(uv_last_error(uv_default_loop())); \ args.GetReturnValue().Set(err); \
args.GetReturnValue().Set(r); \
} }
X(SetTTL, uv_udp_set_ttl) X(SetTTL, uv_udp_set_ttl)
@ -200,12 +199,11 @@ void UDPWrap::SetMembership(const FunctionCallbackInfo<Value>& args,
iface_cstr = NULL; iface_cstr = NULL;
} }
int r = uv_udp_set_membership(&wrap->handle_, int err = uv_udp_set_membership(&wrap->handle_,
*address, *address,
iface_cstr, iface_cstr,
membership); membership);
if (r) SetErrno(uv_last_error(uv_default_loop())); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(r);
} }
@ -221,38 +219,50 @@ void UDPWrap::DropMembership(const FunctionCallbackInfo<Value>& args) {
void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) { void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
int r; int err;
// send(buffer, offset, length, port, address)
assert(args.Length() == 5);
UNWRAP(UDPWrap) UNWRAP(UDPWrap)
assert(Buffer::HasInstance(args[0])); // send(req, buffer, offset, length, port, address)
Local<Object> buffer_obj = args[0]->ToObject(); assert(args[0]->IsObject());
assert(Buffer::HasInstance(args[1]));
assert(args[2]->IsUint32());
assert(args[3]->IsUint32());
assert(args[4]->IsUint32());
assert(args[5]->IsString());
Local<Object> req_wrap_obj = args[0].As<Object>();
Local<Object> buffer_obj = args[1].As<Object>();
size_t offset = args[2]->Uint32Value();
size_t length = args[3]->Uint32Value();
const unsigned short port = args[4]->Uint32Value();
String::Utf8Value address(args[5]);
size_t offset = args[1]->Uint32Value();
size_t length = args[2]->Uint32Value();
assert(offset < Buffer::Length(buffer_obj)); assert(offset < Buffer::Length(buffer_obj));
assert(length <= Buffer::Length(buffer_obj) - offset); assert(length <= Buffer::Length(buffer_obj) - offset);
SendWrap* req_wrap = new SendWrap(); SendWrap* req_wrap = new SendWrap(req_wrap_obj);
req_wrap->object()->SetHiddenValue(buffer_sym, buffer_obj); req_wrap->object()->SetHiddenValue(buffer_sym, buffer_obj);
uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset, uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset,
length); length);
const unsigned short port = args[3]->Uint32Value();
String::Utf8Value address(args[4]);
switch (family) { switch (family) {
case AF_INET: case AF_INET:
r = uv_udp_send(&req_wrap->req_, &wrap->handle_, &buf, 1, err = uv_udp_send(&req_wrap->req_,
uv_ip4_addr(*address, port), OnSend); &wrap->handle_,
&buf,
1,
uv_ip4_addr(*address, port),
OnSend);
break; break;
case AF_INET6: case AF_INET6:
r = uv_udp_send6(&req_wrap->req_, &wrap->handle_, &buf, 1, err = uv_udp_send6(&req_wrap->req_,
uv_ip6_addr(*address, port), OnSend); &wrap->handle_,
&buf,
1,
uv_ip6_addr(*address, port),
OnSend);
break; break;
default: default:
assert(0 && "unexpected address family"); assert(0 && "unexpected address family");
@ -260,14 +270,9 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
} }
req_wrap->Dispatched(); req_wrap->Dispatched();
if (err) delete req_wrap;
if (r) { args.GetReturnValue().Set(err);
SetErrno(uv_last_error(uv_default_loop()));
delete req_wrap;
}
else {
args.GetReturnValue().Set(req_wrap->persistent());
}
} }
@ -285,11 +290,10 @@ void UDPWrap::RecvStart(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate); HandleScope scope(node_isolate);
UNWRAP(UDPWrap) UNWRAP(UDPWrap)
int err = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv);
// UV_EALREADY means that the socket is already bound but that's okay // UV_EALREADY means that the socket is already bound but that's okay
int r = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv); if (err == UV_EALREADY) err = 0;
bool ok = r == 0 || uv_last_error(uv_default_loop()).code == UV_EALREADY; args.GetReturnValue().Set(err);
if (ok == false) SetErrno(uv_last_error(uv_default_loop()));
args.GetReturnValue().Set(ok);
} }
@ -307,14 +311,20 @@ void UDPWrap::GetSockName(const FunctionCallbackInfo<Value>& args) {
struct sockaddr_storage address; struct sockaddr_storage address;
UNWRAP(UDPWrap) UNWRAP(UDPWrap)
assert(args[0]->IsObject());
Local<Object> obj = args[0].As<Object>();
int addrlen = sizeof(address); int addrlen = sizeof(address);
int r = uv_udp_getsockname(&wrap->handle_, int err = uv_udp_getsockname(&wrap->handle_,
reinterpret_cast<sockaddr*>(&address), reinterpret_cast<sockaddr*>(&address),
&addrlen); &addrlen);
if (r) return SetErrno(uv_last_error(uv_default_loop()));
if (err == 0) {
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
AddressToJS(addr, obj);
}
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address); args.GetReturnValue().Set(err);
args.GetReturnValue().Set(AddressToJS(addr));
} }
@ -330,12 +340,8 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
assert(req_wrap->persistent().IsEmpty() == false); assert(req_wrap->persistent().IsEmpty() == false);
assert(wrap->persistent().IsEmpty() == false); assert(wrap->persistent().IsEmpty() == false);
if (status) {
SetErrno(uv_last_error(uv_default_loop()));
}
Local<Object> req_wrap_obj = req_wrap->object(); Local<Object> req_wrap_obj = req_wrap->object();
Local<Value> argv[4] = { Local<Value> argv[] = {
Integer::New(status, node_isolate), Integer::New(status, node_isolate),
wrap->object(), wrap->object(),
req_wrap_obj, req_wrap_obj,
@ -362,34 +368,34 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
uv_buf_t buf, uv_buf_t buf,
struct sockaddr* addr, struct sockaddr* addr,
unsigned flags) { unsigned flags) {
HandleScope scope(node_isolate); if (nread == 0) {
UDPWrap* wrap = reinterpret_cast<UDPWrap*>(handle->data);
if (nread < 0) {
if (buf.base != NULL) if (buf.base != NULL)
free(buf.base); free(buf.base);
Local<Object> wrap_obj = wrap->object();
Local<Value> argv[] = { wrap_obj };
SetErrno(uv_last_error(uv_default_loop()));
MakeCallback(wrap_obj, onmessage_sym, ARRAY_SIZE(argv), argv);
return; return;
} }
if (nread == 0) { UDPWrap* wrap = reinterpret_cast<UDPWrap*>(handle->data);
HandleScope scope(node_isolate);
Local<Object> wrap_obj = wrap->object();
Local<Value> argv[] = {
Integer::New(nread, node_isolate),
wrap_obj,
Undefined(),
Undefined()
};
if (nread < 0) {
if (buf.base != NULL) if (buf.base != NULL)
free(buf.base); free(buf.base);
MakeCallback(wrap_obj, onmessage_sym, ARRAY_SIZE(argv), argv);
return; return;
} }
buf.base = static_cast<char*>(realloc(buf.base, nread)); buf.base = static_cast<char*>(realloc(buf.base, nread));
Local<Object> wrap_obj = wrap->object(); argv[2] = Buffer::Use(buf.base, nread);
Local<Value> argv[] = { argv[3] = AddressToJS(addr);
wrap_obj,
Buffer::Use(buf.base, nread),
AddressToJS(addr)
};
MakeCallback(wrap_obj, onmessage_sym, ARRAY_SIZE(argv), argv); MakeCallback(wrap_obj, onmessage_sym, ARRAY_SIZE(argv), argv);
} }

Loading…
Cancel
Save