Browse Source

more lint

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
e232f6e735
  1. 135
      lib/http.js
  2. 83
      lib/net.js
  3. 44
      lib/path.js
  4. 46
      lib/querystring.js
  5. 53
      lib/readline.js
  6. 194
      lib/repl.js
  7. 39
      lib/securepair.js

135
lib/http.js

@ -107,7 +107,7 @@ var parsers = new FreeList('parsers', 1000, function () {
} }
if (!parser.incoming.upgrade) { if (!parser.incoming.upgrade) {
// For upgraded connections, also emit this after parser.execute // For upgraded connections, also emit this after parser.execute
parser.incoming.emit("end"); parser.incoming.emit('end');
} }
}; };
@ -116,7 +116,7 @@ var parsers = new FreeList('parsers', 1000, function () {
exports.parsers = parsers; exports.parsers = parsers;
var CRLF = "\r\n"; var CRLF = '\r\n';
var STATUS_CODES = exports.STATUS_CODES = { var STATUS_CODES = exports.STATUS_CODES = {
100 : 'Continue', 100 : 'Continue',
101 : 'Switching Protocols', 101 : 'Switching Protocols',
@ -198,7 +198,7 @@ function IncomingMessage (socket) {
this.readable = true; this.readable = true;
// request (server) only // request (server) only
this.url = ""; this.url = '';
this.method = null; this.method = null;
@ -218,7 +218,7 @@ IncomingMessage.prototype.destroy = function (error) {
IncomingMessage.prototype.setEncoding = function(encoding) { IncomingMessage.prototype.setEncoding = function(encoding) {
var StringDecoder = require("string_decoder").StringDecoder; // lazy load var StringDecoder = require('string_decoder').StringDecoder; // lazy load
this._decoder = new StringDecoder(encoding); this._decoder = new StringDecoder(encoding);
}; };
@ -241,12 +241,8 @@ IncomingMessage.prototype.resume = function () {
// and drop the second. Extended header fields (those beginning with 'x-') are // and drop the second. Extended header fields (those beginning with 'x-') are
// always joined. // always joined.
IncomingMessage.prototype._addHeaderLine = function(field, value) { IncomingMessage.prototype._addHeaderLine = function(field, value) {
var dest; var dest = this.complete ? this.trailers : this.headers;
if (this.complete) {
dest = this.trailers;
} else {
dest = this.headers;
}
switch (field) { switch (field) {
// Array headers: // Array headers:
case 'set-cookie': case 'set-cookie':
@ -369,7 +365,7 @@ OutgoingMessage.prototype._buffer = function (data, encoding) {
if (length === 0 || typeof data != 'string') { if (length === 0 || typeof data != 'string') {
this.output.push(data); this.output.push(data);
encoding = encoding || "ascii"; encoding = encoding || 'ascii';
this.outputEncodings.push(encoding); this.outputEncodings.push(encoding);
return false; return false;
} }
@ -384,7 +380,7 @@ OutgoingMessage.prototype._buffer = function (data, encoding) {
} }
this.output.push(data); this.output.push(data);
encoding = encoding || "ascii"; encoding = encoding || 'ascii';
this.outputEncodings.push(encoding); this.outputEncodings.push(encoding);
return false; return false;
@ -397,14 +393,14 @@ OutgoingMessage.prototype._storeHeader = function (firstLine, headers) {
var sentTransferEncodingHeader = false; var sentTransferEncodingHeader = false;
var sentExpect = false; var sentExpect = false;
// firstLine in the case of request is: "GET /index.html HTTP/1.1\r\n" // firstLine in the case of request is: 'GET /index.html HTTP/1.1\r\n'
// in the case of response it is: "HTTP/1.1 200 OK\r\n" // in the case of response it is: 'HTTP/1.1 200 OK\r\n'
var messageHeader = firstLine; var messageHeader = firstLine;
var field, value; var field, value;
var self = this; var self = this;
function store(field, value) { function store(field, value) {
messageHeader += field + ": " + value + CRLF; messageHeader += field + ': ' + value + CRLF;
if (connectionExpression.test(field)) { if (connectionExpression.test(field)) {
sentConnectionHeader = true; sentConnectionHeader = true;
@ -455,17 +451,17 @@ OutgoingMessage.prototype._storeHeader = function (firstLine, headers) {
if (sentConnectionHeader == false) { if (sentConnectionHeader == false) {
if (this.shouldKeepAlive && if (this.shouldKeepAlive &&
(sentContentLengthHeader || this.useChunkedEncodingByDefault)) { (sentContentLengthHeader || this.useChunkedEncodingByDefault)) {
messageHeader += "Connection: keep-alive\r\n"; messageHeader += 'Connection: keep-alive\r\n';
} else { } else {
this._last = true; this._last = true;
messageHeader += "Connection: close\r\n"; messageHeader += 'Connection: close\r\n';
} }
} }
if (sentContentLengthHeader == false && sentTransferEncodingHeader == false) { if (sentContentLengthHeader == false && sentTransferEncodingHeader == false) {
if (this._hasBody) { if (this._hasBody) {
if (this.useChunkedEncodingByDefault) { if (this.useChunkedEncodingByDefault) {
messageHeader += "Transfer-Encoding: chunked\r\n"; messageHeader += 'Transfer-Encoding: chunked\r\n';
this.chunkedEncoding = true; this.chunkedEncoding = true;
} else { } else {
this._last = true; this._last = true;
@ -481,23 +477,24 @@ OutgoingMessage.prototype._storeHeader = function (firstLine, headers) {
// wait until the first body chunk, or close(), is sent to flush, // wait until the first body chunk, or close(), is sent to flush,
// UNLESS we're sending Expect: 100-continue. // UNLESS we're sending Expect: 100-continue.
if (sentExpect) this._send(""); if (sentExpect) this._send('');
}; };
OutgoingMessage.prototype.write = function(chunk, encoding) { OutgoingMessage.prototype.write = function(chunk, encoding) {
if (!this._header) { if (!this._header) {
throw new Error("You have to call writeHead() before write()"); throw new Error('You have to call writeHead() before write()');
} }
if (!this._hasBody) { if (!this._hasBody) {
console.error("This type of response MUST NOT have a body. Ignoring write() calls."); console.error('This type of response MUST NOT have a body. ' +
'Ignoring write() calls.');
return true; return true;
} }
if (typeof chunk !== "string" && !Buffer.isBuffer(chunk) && if (typeof chunk !== 'string' && !Buffer.isBuffer(chunk) &&
!Array.isArray(chunk)) { !Array.isArray(chunk)) {
throw new TypeError("first argument must be a string, Array, or Buffer"); throw new TypeError('first argument must be a string, Array, or Buffer');
} }
if (chunk.length === 0) return false; if (chunk.length === 0) return false;
@ -526,7 +523,7 @@ OutgoingMessage.prototype.write = function (chunk, encoding) {
OutgoingMessage.prototype.addTrailers = function(headers) { OutgoingMessage.prototype.addTrailers = function(headers) {
this._trailer = ""; this._trailer = '';
var keys = Object.keys(headers); var keys = Object.keys(headers);
var isArray = (Array.isArray(headers)); var isArray = (Array.isArray(headers));
for (var i = 0, l = keys.length; i < l; i++) { for (var i = 0, l = keys.length; i < l; i++) {
@ -539,7 +536,7 @@ OutgoingMessage.prototype.addTrailers = function (headers) {
value = headers[key]; value = headers[key];
} }
this._trailer += field + ": " + value + CRLF; this._trailer += field + ': ' + value + CRLF;
} }
}; };
@ -548,7 +545,7 @@ OutgoingMessage.prototype.end = function (data, encoding) {
var ret; var ret;
var hot = this._headerSent === false && var hot = this._headerSent === false &&
typeof(data) === "string" && typeof(data) === 'string' &&
data.length > 0 && data.length > 0 &&
this.output.length === 0 && this.output.length === 0 &&
this.connection.writable && this.connection.writable &&
@ -562,8 +559,8 @@ OutgoingMessage.prototype.end = function (data, encoding) {
if (this.chunkedEncoding) { if (this.chunkedEncoding) {
var l = Buffer.byteLength(data, encoding).toString(16); var l = Buffer.byteLength(data, encoding).toString(16);
ret = this.connection.write(this._header + l + CRLF + ret = this.connection.write(this._header + l + CRLF +
data + "\r\n0\r\n" + data + '\r\n0\r\n' +
this._trailer + "\r\n", encoding); this._trailer + '\r\n', encoding);
} else { } else {
ret = this.connection.write(this._header + data, encoding); ret = this.connection.write(this._header + data, encoding);
} }
@ -613,7 +610,7 @@ exports.ServerResponse = ServerResponse;
ServerResponse.prototype.writeContinue = function() { ServerResponse.prototype.writeContinue = function() {
this._writeRaw("HTTP/1.1 100 Continue" + CRLF + CRLF, 'ascii'); this._writeRaw('HTTP/1.1 100 Continue' + CRLF + CRLF, 'ascii');
this._sent100 = true; this._sent100 = true;
}; };
@ -625,7 +622,7 @@ ServerResponse.prototype.writeHead = function (statusCode) {
reasonPhrase = arguments[1]; reasonPhrase = arguments[1];
headerIndex = 2; headerIndex = 2;
} else { } else {
reasonPhrase = STATUS_CODES[statusCode] || "unknown"; reasonPhrase = STATUS_CODES[statusCode] || 'unknown';
headerIndex = 1; headerIndex = 1;
} }
@ -635,7 +632,7 @@ ServerResponse.prototype.writeHead = function (statusCode) {
headers = {}; headers = {};
} }
var statusLine = "HTTP/1.1 " + statusCode.toString() + " " + var statusLine = 'HTTP/1.1 ' + statusCode.toString() + ' ' +
reasonPhrase + CRLF; reasonPhrase + CRLF;
if (statusCode === 204 || statusCode === 304 || if (statusCode === 204 || statusCode === 304 ||
@ -673,14 +670,14 @@ function ClientRequest (socket, method, url, headers) {
this.method = method = method.toUpperCase(); this.method = method = method.toUpperCase();
this.shouldKeepAlive = false; this.shouldKeepAlive = false;
if (method === "GET" || method === "HEAD") { if (method === 'GET' || method === 'HEAD') {
this.useChunkedEncodingByDefault = false; this.useChunkedEncodingByDefault = false;
} else { } else {
this.useChunkedEncodingByDefault = true; this.useChunkedEncodingByDefault = true;
} }
this._last = true; this._last = true;
this._storeHeader(method + " " + url + " HTTP/1.1\r\n", headers); this._storeHeader(method + ' ' + url + ' HTTP/1.1\r\n', headers);
} }
util.inherits(ClientRequest, OutgoingMessage); util.inherits(ClientRequest, OutgoingMessage);
@ -700,7 +697,7 @@ function outgoingFlush (socket) {
// //
// When the user does // When the user does
// //
// req2.write("hello world\n"); // req2.write('hello world\n');
// //
// it's possible that the first request has not been completely flushed to // it's possible that the first request has not been completely flushed to
// the socket yet. Thus the outgoing messages need to be prepared to queue // the socket yet. Thus the outgoing messages need to be prepared to queue
@ -751,10 +748,10 @@ function Server (requestListener) {
net.Server.call(this, { allowHalfOpen: true }); net.Server.call(this, { allowHalfOpen: true });
if (requestListener) { if (requestListener) {
this.addListener("request", requestListener); this.addListener('request', requestListener);
} }
this.addListener("connection", connectionListener); this.addListener('connection', connectionListener);
} }
util.inherits(Server, net.Server); util.inherits(Server, net.Server);
@ -770,7 +767,7 @@ exports.createServer = function (requestListener) {
function connectionListener(socket) { function connectionListener(socket) {
var self = this; var self = this;
debug("SERVER new http connection"); debug('SERVER new http connection');
httpSocketSetup(socket); httpSocketSetup(socket);
@ -790,7 +787,7 @@ function connectionListener (socket) {
socket.ondata = function(d, start, end) { socket.ondata = function(d, start, end) {
var ret = parser.execute(d, start, end - start); var ret = parser.execute(d, start, end - start);
if (ret instanceof Error) { if (ret instanceof Error) {
debug("parse error"); debug('parse error');
socket.destroy(ret); socket.destroy(ret);
} else if (parser.incoming && parser.incoming.upgrade) { } else if (parser.incoming && parser.incoming.upgrade) {
var bytesParsed = ret; var bytesParsed = ret;
@ -803,7 +800,7 @@ function connectionListener (socket) {
// in the upgradeHead from the closing lines of the headers // in the upgradeHead from the closing lines of the headers
var upgradeHead = d.slice(start + bytesParsed + 1, end); var upgradeHead = d.slice(start + bytesParsed + 1, end);
if (self.listeners("upgrade").length) { if (self.listeners('upgrade').length) {
self.emit('upgrade', req, req.socket, upgradeHead); self.emit('upgrade', req, req.socket, upgradeHead);
} else { } else {
// Got upgrade header, but have no handler. // Got upgrade header, but have no handler.
@ -861,8 +858,8 @@ function connectionListener (socket) {
(req.httpVersionMajor == 1 && req.httpVersionMinor == 1) && (req.httpVersionMajor == 1 && req.httpVersionMinor == 1) &&
continueExpression.test(req.headers['expect'])) { continueExpression.test(req.headers['expect'])) {
res._expect_continue = true; res._expect_continue = true;
if (self.listeners("checkContinue").length) { if (self.listeners('checkContinue').length) {
self.emit("checkContinue", req, res); self.emit('checkContinue', req, res);
} else { } else {
res.writeContinue(); res.writeContinue();
self.emit('request', req, res); self.emit('request', req, res);
@ -890,7 +887,7 @@ function Client ( ) {
function onData(d, start, end) { function onData(d, start, end) {
if (!self.parser) { if (!self.parser) {
throw new Error("parser not initialized prior to Client.ondata call"); throw new Error('parser not initialized prior to Client.ondata call');
} }
var ret = self.parser.execute(d, start, end - start); var ret = self.parser.execute(d, start, end - start);
if (ret instanceof Error) { if (ret instanceof Error) {
@ -912,30 +909,29 @@ function Client ( ) {
} }
}; };
self.addListener("connect", function () { self.addListener('connect', function() {
debug('CLIENT connected'); debug('CLIENT connected');
self.ondata = onData; self.ondata = onData;
self.onend = onEnd; self.onend = onEnd;
self._state = "connected"; self._state = 'connected';
self._initParser(); self._initParser();
debug('CLIENT requests: ' + util.inspect(self._outgoing.map(function (r) { return r.method; })));
outgoingFlush(self); outgoingFlush(self);
}); });
function onEnd() { function onEnd() {
if (self.parser) self.parser.finish(); if (self.parser) self.parser.finish();
debug("CLIENT got end closing. state = " + self._state); debug('CLIENT got end closing. state = ' + self._state);
self.end(); self.end();
}; };
self.addListener("close", function (e) { self.addListener('close', function(e) {
self._state = "disconnected"; self._state = 'disconnected';
if (e) return; if (e) return;
debug("CLIENT onClose. state = " + self._state); debug('CLIENT onClose. state = ' + self._state);
// finally done with the request // finally done with the request
self._outgoing.shift(); self._outgoing.shift();
@ -948,7 +944,7 @@ function Client ( ) {
self.parser = null; self.parser = null;
} }
}); });
}; }
util.inherits(Client, net.Stream); util.inherits(Client, net.Stream);
@ -971,18 +967,18 @@ Client.prototype._initParser = function () {
self.parser.reinitialize('response'); self.parser.reinitialize('response');
self.parser.socket = self; self.parser.socket = self;
self.parser.onIncoming = function(res) { self.parser.onIncoming = function(res) {
debug("CLIENT incoming response!"); debug('CLIENT incoming response!');
var req = self._outgoing[0]; var req = self._outgoing[0];
// Responses to HEAD requests are AWFUL. Ask Ryan. // Responses to HEAD requests are AWFUL. Ask Ryan.
// A major oversight in HTTP. Hence this nastiness. // A major oversight in HTTP. Hence this nastiness.
var isHeadResponse = req.method == "HEAD"; var isHeadResponse = req.method == 'HEAD';
debug('CLIENT isHeadResponse ' + isHeadResponse); debug('CLIENT isHeadResponse ' + isHeadResponse);
if (res.statusCode == 100) { if (res.statusCode == 100) {
// restart the parser, as this is a continue message. // restart the parser, as this is a continue message.
req.emit("continue"); req.emit('continue');
return true; return true;
} }
@ -991,7 +987,7 @@ Client.prototype._initParser = function () {
} }
res.addListener('end', function() { res.addListener('end', function() {
debug("CLIENT request complete disconnecting. state = " + self._state); debug('CLIENT request complete disconnecting. state = ' + self._state);
// For the moment we reconnect for every request. FIXME! // For the moment we reconnect for every request. FIXME!
// All that should be required for keep-alive is to not reconnect, // All that should be required for keep-alive is to not reconnect,
// but outgoingFlush instead. // but outgoingFlush instead.
@ -1004,7 +1000,7 @@ Client.prototype._initParser = function () {
} }
}); });
req.emit("response", res); req.emit('response', res);
return isHeadResponse; return isHeadResponse;
}; };
@ -1030,7 +1026,7 @@ Client.prototype._onOutgoingSent = function (message) {
// Instead, we just check if the connection is closed, and if so // Instead, we just check if the connection is closed, and if so
// reconnect if we have pending messages. // reconnect if we have pending messages.
if (this._outgoing.length) { if (this._outgoing.length) {
debug("CLIENT request flush. ensure connection. state = " + this._state); debug('CLIENT request flush. ensure connection. state = ' + this._state);
this._ensureConnection(); this._ensureConnection();
} }
}; };
@ -1038,19 +1034,19 @@ Client.prototype._onOutgoingSent = function (message) {
Client.prototype._ensureConnection = function() { Client.prototype._ensureConnection = function() {
if (this._state == 'disconnected') { if (this._state == 'disconnected') {
debug("CLIENT reconnecting state = " + this._state); debug('CLIENT reconnecting state = ' + this._state);
this.connect(this.port, this.host); this.connect(this.port, this.host);
this._state = "connecting"; this._state = 'connecting';
} }
}; };
Client.prototype.request = function(method, url, headers) { Client.prototype.request = function(method, url, headers) {
if (typeof(url) != "string") { if (typeof(url) != 'string') {
// assume method was omitted, shift arguments // assume method was omitted, shift arguments
headers = url; headers = url;
url = method; url = method;
method = "GET"; method = 'GET';
} }
var req = new ClientRequest(this, method, url, headers); var req = new ClientRequest(this, method, url, headers);
this._outgoing.push(req); this._outgoing.push(req);
@ -1083,7 +1079,7 @@ exports.cat = function (url, encoding_, headers_) {
} }
} }
var url = require("url").parse(url); var url = require('url').parse(url);
var hasHost = false; var hasHost = false;
if (Array.isArray(headers)) { if (Array.isArray(headers)) {
@ -1093,7 +1089,7 @@ exports.cat = function (url, encoding_, headers_) {
break; break;
} }
} }
} else if (typeof headers === "Object") { } else if (typeof headers === 'Object') {
var keys = Object.keys(headers); var keys = Object.keys(headers);
for (var i = 0, l = keys.length; i < l; i++) { for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i]; var key = keys[i];
@ -1103,14 +1099,17 @@ exports.cat = function (url, encoding_, headers_) {
} }
} }
} }
if (!hasHost) headers["Host"] = url.hostname; if (!hasHost) headers['Host'] = url.hostname;
var content = ""; var content = '';
var client = exports.createClient(url.port || 80, url.hostname); var client = exports.createClient(url.port || 80, url.hostname);
var req = client.request((url.pathname || "/")+(url.search || "")+(url.hash || ""), headers); var req = client.request((url.pathname || '/') +
(url.search || '') +
(url.hash || ''),
headers);
if (url.protocol=="https:") { if (url.protocol == 'https:') {
client.https = true; client.https = true;
} }
@ -1135,14 +1134,14 @@ exports.cat = function (url, encoding_, headers_) {
}); });
}); });
client.addListener("error", function (err) { client.addListener('error', function(err) {
if (callback && !callbackSent) { if (callback && !callbackSent) {
callback(err); callback(err);
callbackSent = true; callbackSent = true;
} }
}); });
client.addListener("close", function () { client.addListener('close', function() {
if (callback && !callbackSent) { if (callback && !callbackSent) {
callback(new Error('Connection closed unexpectedly')); callback(new Error('Connection closed unexpectedly'));
callbackSent = true; callbackSent = true;

83
lib/net.js

@ -1,14 +1,19 @@
var util = require("util"); var util = require('util');
var events = require("events"); var events = require('events');
var stream = require("stream"); var stream = require('stream');
var kMinPoolSpace = 128; var kMinPoolSpace = 128;
var kPoolSize = 40 * 1024; var kPoolSize = 40 * 1024;
var debugLevel = parseInt(process.env.NODE_DEBUG, 16); var debugLevel = parseInt(process.env.NODE_DEBUG, 16);
function debug () { var debug;
if (debugLevel & 0x2) util.error.apply(this, arguments); if (debugLevel & 0x2) {
debug = function(x) { util.error.apply(this, arguments); };
} else {
debug = function() { };
} }
var binding = process.binding('net'); var binding = process.binding('net');
// Note about Buffer interface: // Note about Buffer interface:
@ -50,7 +55,7 @@ var EMFILE = constants.EMFILE;
var END_OF_FILE = 42; var END_OF_FILE = 42;
var ioWatchers = new FreeList("iowatcher", 100, function () { var ioWatchers = new FreeList('iowatcher', 100, function() {
return new IOWatcher(); return new IOWatcher();
}); });
@ -142,7 +147,7 @@ function setImplmentationMethods (self) {
shutdown(self.fd, 'write'); shutdown(self.fd, 'write');
}; };
}; }
function onReadable(readable, writable) { function onReadable(readable, writable) {
@ -181,7 +186,7 @@ function initStream (self) {
} }
// Deprecated API: Stream(fd, type) // Deprecated API: Stream(fd, type)
// New API: Stream({ fd: 10, type: "unix", allowHalfOpen: true }) // New API: Stream({ fd: 10, type: 'unix', allowHalfOpen: true })
function Stream(options) { function Stream(options) {
if (!(this instanceof Stream)) return new Stream(arguments[0], arguments[1]); if (!(this instanceof Stream)) return new Stream(arguments[0], arguments[1]);
stream.Stream.call(this); stream.Stream.call(this);
@ -190,11 +195,11 @@ function Stream (options) {
this.type = null; this.type = null;
this.allowHalfOpen = false; this.allowHalfOpen = false;
if (typeof options == "object") { if (typeof options == 'object') {
this.fd = options.fd !== undefined ? parseInt(options.fd, 10) : null; this.fd = options.fd !== undefined ? parseInt(options.fd, 10) : null;
this.type = options.type || null; this.type = options.type || null;
this.allowHalfOpen = options.allowHalfOpen || false; this.allowHalfOpen = options.allowHalfOpen || false;
} else if (typeof options == "number") { } else if (typeof options == 'number') {
this.fd = arguments[0]; this.fd = arguments[0];
this.type = arguments[1]; this.type = arguments[1];
} }
@ -204,7 +209,7 @@ function Stream (options) {
} else { } else {
setImplmentationMethods(this); setImplmentationMethods(this);
} }
}; }
util.inherits(Stream, stream.Stream); util.inherits(Stream, stream.Stream);
exports.Stream = Stream; exports.Stream = Stream;
@ -257,7 +262,7 @@ Object.defineProperty(Stream.prototype, 'readyState', {
// Returns true if all the data was flushed to socket. Returns false if // Returns true if all the data was flushed to socket. Returns false if
// something was queued. If data was queued, then the "drain" event will // something was queued. If data was queued, then the 'drain' event will
// signal when it has been finally flushed to socket. // signal when it has been finally flushed to socket.
Stream.prototype.write = function(data, encoding, fd) { Stream.prototype.write = function(data, encoding, fd) {
if (this._connecting || (this._writeQueue && this._writeQueue.length)) { if (this._connecting || (this._writeQueue && this._writeQueue.length)) {
@ -272,12 +277,14 @@ Stream.prototype.write = function (data, encoding, fd) {
throw new Error('Stream.end() called already; cannot write.'); throw new Error('Stream.end() called already; cannot write.');
} }
var last = this._writeQueue.length - 1;
if (typeof data == 'string' && if (typeof data == 'string' &&
this._writeQueue.length && this._writeQueue.length &&
typeof this._writeQueue[this._writeQueue.length-1] === 'string' && typeof this._writeQueue[last] === 'string' &&
this._writeQueueEncoding[this._writeQueueEncoding.length-1] === encoding) { this._writeQueueEncoding[last] === encoding) {
// optimization - concat onto last // optimization - concat onto last
this._writeQueue[this._writeQueue.length-1] += data; this._writeQueue[last] += data;
} else { } else {
this._writeQueue.push(data); this._writeQueue.push(data);
this._writeQueueEncoding.push(encoding); this._writeQueueEncoding.push(encoding);
@ -349,7 +356,9 @@ Stream.prototype._writeOut = function (data, encoding, fd) {
debug('wrote ' + bytesWritten + ' bytes to pool'); debug('wrote ' + bytesWritten + ' bytes to pool');
if (charsWritten != data.length) { if (charsWritten != data.length) {
//debug("couldn't fit " + (data.length - charsWritten) + " bytes into the pool\n"); // debug('couldn't fit ' +
// (data.length - charsWritten) +
// ' bytes into the pool\n');
// Unshift whatever didn't fit onto the buffer // Unshift whatever didn't fit onto the buffer
this._writeQueue.unshift(data.slice(charsWritten)); this._writeQueue.unshift(data.slice(charsWritten));
this._writeQueueEncoding.unshift(encoding); this._writeQueueEncoding.unshift(encoding);
@ -365,7 +374,8 @@ Stream.prototype._writeOut = function (data, encoding, fd) {
return false; return false;
} }
debug('wrote ' + bytesWritten + ' to socket. [fd, off, len] = ' + JSON.stringify([this.fd, off, len]) + "\n"); debug('wrote ' + bytesWritten + ' to socket. [fd, off, len] = ' +
JSON.stringify([this.fd, off, len]) + '\n');
require('timers').active(this); require('timers').active(this);
@ -430,13 +440,13 @@ Stream.prototype.flush = function () {
Stream.prototype._writeQueueLast = function() { Stream.prototype._writeQueueLast = function() {
return this._writeQueue.length > 0 ? this._writeQueue[this._writeQueue.length-1] return this._writeQueue.length > 0 ?
: null; this._writeQueue[this._writeQueue.length - 1] : null;
}; };
Stream.prototype.setEncoding = function(encoding) { Stream.prototype.setEncoding = function(encoding) {
var StringDecoder = require("string_decoder").StringDecoder; // lazy load var StringDecoder = require('string_decoder').StringDecoder; // lazy load
this._decoder = new StringDecoder(encoding); this._decoder = new StringDecoder(encoding);
}; };
@ -498,7 +508,7 @@ Stream.prototype._onWritable = function () {
// Stream becomes writable on connect() but don't flush if there's // Stream becomes writable on connect() but don't flush if there's
// nothing actually to write // nothing actually to write
if (this.flush()) { if (this.flush()) {
if (this._events && this._events['drain']) this.emit("drain"); if (this._events && this._events['drain']) this.emit('drain');
if (this.ondrain) this.ondrain(); // Optimization if (this.ondrain) this.ondrain(); // Optimization
} }
}; };
@ -730,13 +740,13 @@ function Server (/* [ options, ] listener */) {
var self = this; var self = this;
var options = {}; var options = {};
if (typeof arguments[0] == "object") { if (typeof arguments[0] == 'object') {
options = arguments[0]; options = arguments[0];
} }
// listener: find the last argument that is a function // listener: find the last argument that is a function
for (var l = arguments.length - 1; l >= 0; l--) { for (var l = arguments.length - 1; l >= 0; l--) {
if (typeof arguments[l] == "function") { if (typeof arguments[l] == 'function') {
self.addListener('connection', arguments[l]); self.addListener('connection', arguments[l]);
} }
if (arguments[l] !== undefined) break; if (arguments[l] !== undefined) break;
@ -783,9 +793,10 @@ function Server (/* [ options, ] listener */) {
self.connections++; self.connections++;
var s = new Stream({ fd: peerInfo.fd, var options = { fd: peerInfo.fd,
type: self.type, type: self.type,
allowHalfOpen: self.allowHalfOpen }); allowHalfOpen: self.allowHalfOpen };
var s = new Stream(options);
s.remoteAddress = peerInfo.address; s.remoteAddress = peerInfo.address;
s.remotePort = peerInfo.port; s.remotePort = peerInfo.port;
s.type = self.type; s.type = self.type;
@ -856,13 +867,13 @@ Server.prototype._rejectPending = function () {
// Listen on a UNIX socket // Listen on a UNIX socket
// server.listen("/tmp/socket"); // server.listen('/tmp/socket');
// //
// Listen on port 8000, accept connections from INADDR_ANY. // Listen on port 8000, accept connections from INADDR_ANY.
// server.listen(8000); // server.listen(8000);
// //
// Listen on port 8000, accept connections to "192.168.1.2" // Listen on port 8000, accept connections to '192.168.1.2'
// server.listen(8000, "192.168.1.2"); // server.listen(8000, '192.168.1.2');
Server.prototype.listen = function() { Server.prototype.listen = function() {
var self = this; var self = this;
if (self.fd) throw new Error('Server already opened'); if (self.fd) throw new Error('Server already opened');
@ -896,7 +907,7 @@ Server.prototype.listen = function () {
} }
} else { } else {
if (!r.isSocket()) { if (!r.isSocket()) {
throw new Error("Non-socket exists at " + path); throw new Error('Non-socket exists at ' + path);
} else { } else {
require('fs').unlink(path, function(err) { require('fs').unlink(path, function(err) {
if (err) throw err; if (err) throw err;
@ -932,7 +943,7 @@ Server.prototype.listenFD = function (fd, type) {
Server.prototype._startWatcher = function() { Server.prototype._startWatcher = function() {
this.watcher.set(this.fd, true, false); this.watcher.set(this.fd, true, false);
this.watcher.start(); this.watcher.start();
this.emit("listening"); this.emit('listening');
}; };
Server.prototype._doListen = function() { Server.prototype._doListen = function() {
@ -965,7 +976,7 @@ Server.prototype._doListen = function () {
self._startWatcher(); self._startWatcher();
}); });
} };
Server.prototype.address = function() { Server.prototype.address = function() {
@ -987,12 +998,12 @@ Server.prototype.close = function () {
self._pauseTimer = null; self._pauseTimer = null;
} }
if (self.type === "unix") { if (self.type === 'unix') {
require('fs').unlink(self.path, function() { require('fs').unlink(self.path, function() {
self.emit("close"); self.emit('close');
}); });
} else { } else {
self.emit("close"); self.emit('close');
} }
}; };
@ -1005,7 +1016,7 @@ function rescueEMFILE(callback) {
// Output a warning, but only at most every 5 seconds. // Output a warning, but only at most every 5 seconds.
var now = new Date(); var now = new Date();
if (now - lastEMFILEWarning > 5000) { if (now - lastEMFILEWarning > 5000) {
console.error("(node) Hit max file limit. Increase 'ulimit -n'."); console.error('(node) Hit max file limit. Increase "ulimit - n"');
lastEMFILEWarning = now; lastEMFILEWarning = now;
} }
@ -1020,7 +1031,7 @@ function rescueEMFILE(callback) {
function getDummyFD() { function getDummyFD() {
if (!dummyFD) { if (!dummyFD) {
try { try {
dummyFD = socket("tcp"); dummyFD = socket('tcp');
} catch (e) { } catch (e) {
dummyFD = null; dummyFD = null;
} }

44
lib/path.js

@ -1,5 +1,5 @@
function validPathPart(p, keepBlanks) { function validPathPart(p, keepBlanks) {
return typeof p === "string" && (p || keepBlanks); return typeof p === 'string' && (p || keepBlanks);
} }
@ -11,7 +11,7 @@ exports.join = function () {
keepBlanks = args.pop(); keepBlanks = args.pop();
} }
// return exports.split(args.join("/"), keepBlanks).join("/"); // return exports.split(args.join("/"), keepBlanks).join("/");
var joined = exports.normalizeArray(args, keepBlanks).join("/"); var joined = exports.normalizeArray(args, keepBlanks).join('/');
return joined; return joined;
}; };
@ -52,16 +52,16 @@ function cleanArray (parts, keepBlanks) {
exports.normalizeArray = function(original, keepBlanks) { exports.normalizeArray = function(original, keepBlanks) {
var parts = cleanArray(original, keepBlanks); var parts = cleanArray(original, keepBlanks);
if (!parts.length || (parts.length === 1 && !parts[0])) return ["."]; if (!parts.length || (parts.length === 1 && !parts[0])) return ['.'];
// now we're fully ready to rock. // now we're fully ready to rock.
// leading/trailing invalids have been stripped off. // leading/trailing invalids have been stripped off.
// if it comes in starting with a slash, or ending with a slash, // if it comes in starting with a slash, or ending with a slash,
var leadingSlash = (parts[0].charAt(0) === "/"); var leadingSlash = (parts[0].charAt(0) === '/');
if (leadingSlash) parts[0] = parts[0].substr(1); if (leadingSlash) parts[0] = parts[0].substr(1);
var last = parts.slice(-1)[0]; var last = parts.slice(-1)[0];
var tailingSlash = (last.substr(-1) === "/"); var tailingSlash = (last.substr(-1) === '/');
if (tailingSlash) parts[parts.length - 1] = last.slice(0, -1); if (tailingSlash) parts[parts.length - 1] = last.slice(0, -1);
var directories = []; var directories = [];
var prev; var prev;
@ -69,27 +69,21 @@ exports.normalizeArray = function (original, keepBlanks) {
var directory = parts[i]; var directory = parts[i];
// if it's blank, and we're not keeping blanks, then skip it. // if it's blank, and we're not keeping blanks, then skip it.
if (directory === "" && !keepBlanks) continue; if (directory === '' && !keepBlanks) continue;
// if it's a dot, then skip it // if it's a dot, then skip it
if (directory === "." && ( if (directory === '.' && (directories.length ||
directories.length (i === 0 && !(tailingSlash && i === l)) ||
|| (i === 0 && !(tailingSlash && i === l)) (i === 0 && leadingSlash))) continue;
|| (i === 0 && leadingSlash)
)) continue;
// if we're dealing with an absolute path, then discard ..s that go // if we're dealing with an absolute path, then discard ..s that go
// above that the base. // above that the base.
if (leadingSlash && directories.length === 0 && directory === "..") { if (leadingSlash && directories.length === 0 && directory === '..') {
continue; continue;
} }
// trying to go up a dir // trying to go up a dir
if ( if (directory === '..' && directories.length && prev !== '..' &&
directory === ".." prev !== undefined) {
&& directories.length
&& prev !== ".."
&& prev !== undefined
) {
directories.pop(); directories.pop();
prev = directories.slice(-1)[0]; prev = directories.slice(-1)[0];
} else { } else {
@ -98,15 +92,15 @@ exports.normalizeArray = function (original, keepBlanks) {
} }
} }
if (!directories.length) { if (!directories.length) {
directories = [ leadingSlash || tailingSlash ? "" : "." ]; directories = [leadingSlash || tailingSlash ? '' : '.'];
} }
var last = directories.slice(-1)[0]; var last = directories.slice(-1)[0];
if (tailingSlash && last.substr(-1) !== "/") { if (tailingSlash && last.substr(-1) !== '/') {
directories[directories.length-1] += "/"; directories[directories.length - 1] += '/';
} }
if (leadingSlash && directories[0].charAt(0) !== "/") { if (leadingSlash && directories[0].charAt(0) !== '/') {
if (directories[0] === ".") directories[0] = ""; if (directories[0] === '.') directories[0] = '';
directories[0] = "/" + directories[0]; directories[0] = '/' + directories[0];
} }
return directories; return directories;
}; };
@ -134,7 +128,7 @@ exports.dirname = function (path) {
exports.basename = function(path, ext) { exports.basename = function(path, ext) {
var f = path.substr(path.lastIndexOf("/") + 1); var f = path.substr(path.lastIndexOf('/') + 1);
if (ext && f.substr(-1 * ext.length) === ext) { if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length); f = f.substr(0, f.length - ext.length);
} }

46
lib/querystring.js

@ -1,7 +1,7 @@
// Query String Utilities // Query String Utilities
var QueryString = exports; var QueryString = exports;
var urlDecode = process.binding("http_parser").urlDecode; var urlDecode = process.binding('http_parser').urlDecode;
function charCode(c) { function charCode(c) {
@ -12,7 +12,7 @@ function charCode (c) {
// a safe fast alternative to decodeURIComponent // a safe fast alternative to decodeURIComponent
QueryString.unescapeBuffer = function(s, decodeSpaces) { QueryString.unescapeBuffer = function(s, decodeSpaces) {
var out = new Buffer(s.length); var out = new Buffer(s.length);
var state = "CHAR"; // states: CHAR, HEX0, HEX1 var state = 'CHAR'; // states: CHAR, HEX0, HEX1
var n, m, hexchar; var n, m, hexchar;
for (var inIndex = 0, outIndex = 0; inIndex <= s.length; inIndex++) { for (var inIndex = 0, outIndex = 0; inIndex <= s.length; inIndex++) {
@ -87,39 +87,28 @@ QueryString.escape = function (str) {
var stringifyPrimitive = function(v) { var stringifyPrimitive = function(v) {
switch (typeof v) { switch (typeof v) {
case "string": case 'string':
return v; return v;
case "boolean": case 'boolean':
return v ? "true" : "false"; return v ? 'true' : 'false';
case "number": case 'number':
return isFinite(v) ? v : ""; return isFinite(v) ? v : '';
default: default:
return ""; return '';
} }
}; };
/**
* <p>Converts an arbitrary value to a Query String representation.</p>
*
* <p>Objects with cyclical references will trigger an exception.</p>
*
* @method stringify
* @param obj {Variant} any arbitrary value to convert to query string
* @param sep {String} (optional) Character that should join param k=v pairs together. Default: "&"
* @param eq {String} (optional) Character that should join keys to their values. Default: "="
* @param name {String} (optional) Name of the current key, for handling children recursively.
* @static
*/
QueryString.stringify = QueryString.encode = function(obj, sep, eq, name) { QueryString.stringify = QueryString.encode = function(obj, sep, eq, name) {
sep = sep || "&"; sep = sep || '&';
eq = eq || "="; eq = eq || '=';
obj = (obj === null) ? undefined : obj; obj = (obj === null) ? undefined : obj;
switch (typeof obj) { switch (typeof obj) {
case "object": case 'object':
return Object.keys(obj).map(function(k) { return Object.keys(obj).map(function(k) {
if (Array.isArray(obj[k])) { if (Array.isArray(obj[k])) {
return obj[k].map(function(v) { return obj[k].map(function(v) {
@ -135,17 +124,16 @@ QueryString.stringify = QueryString.encode = function (obj, sep, eq, name) {
}).join(sep); }).join(sep);
default: default:
return (name) ? if (!name) return '';
QueryString.escape(stringifyPrimitive(name)) + eq + return QueryString.escape(stringifyPrimitive(name)) + eq +
QueryString.escape(stringifyPrimitive(obj)) : QueryString.escape(stringifyPrimitive(obj));
"";
} }
}; };
// Parse a key=val string. // Parse a key=val string.
QueryString.parse = QueryString.decode = function(qs, sep, eq) { QueryString.parse = QueryString.decode = function(qs, sep, eq) {
sep = sep || "&"; sep = sep || '&';
eq = eq || "="; eq = eq || '=';
var obj = {}; var obj = {};
if (typeof qs !== 'string') { if (typeof qs !== 'string') {

53
lib/readline.js

@ -38,7 +38,7 @@ function Interface (output, completer) {
this.output = output; this.output = output;
this.completer = completer; this.completer = completer;
this.setPrompt("> "); this.setPrompt('> ');
this.enabled = stdio.isatty(output.fd); this.enabled = stdio.isatty(output.fd);
@ -53,7 +53,7 @@ function Interface (output, completer) {
writeFilter(process.stdout); writeFilter(process.stdout);
// Current line // Current line
this.line = ""; this.line = '';
// Check process.env.TERM ? // Check process.env.TERM ?
stdio.setRawMode(true); stdio.setRawMode(true);
@ -67,8 +67,8 @@ function Interface (output, completer) {
exports.columns = process.binding('stdio').getColumns(); exports.columns = process.binding('stdio').getColumns();
if (process.listeners("SIGWINCH").length === 0) { if (process.listeners('SIGWINCH').length === 0) {
process.on("SIGWINCH", function () { process.on('SIGWINCH', function() {
exports.columns = process.binding('stdio').getColumns(); exports.columns = process.binding('stdio').getColumns();
}); });
} }
@ -77,7 +77,7 @@ function Interface (output, completer) {
inherits(Interface, EventEmitter); inherits(Interface, EventEmitter);
Interface.prototype.__defineGetter__("columns", function () { Interface.prototype.__defineGetter__('columns', function() {
return exports.columns; return exports.columns;
}); });
@ -98,10 +98,10 @@ Interface.prototype.prompt = function () {
Interface.prototype._addHistory = function() { Interface.prototype._addHistory = function() {
if (this.line.length === 0) return ""; if (this.line.length === 0) return '';
this.history.unshift(this.line); this.history.unshift(this.line);
this.line = ""; this.line = '';
this.historyIndex = -1; this.historyIndex = -1;
this.cursor = 0; this.cursor = 0;
@ -181,7 +181,7 @@ Interface.prototype._tabComplete = function () {
self._insertString(completions[0].slice(completeOn.length)); self._insertString(completions[0].slice(completeOn.length));
self._refreshLine(); self._refreshLine();
} else { } else {
self.output.write("\r\n"); self.output.write('\r\n');
var width = completions.reduce(function(a, b) { var width = completions.reduce(function(a, b) {
return a.length > b.length ? a : b; return a.length > b.length ? a : b;
}).length + 2; // 2 space padding }).length + 2; // 2 space padding
@ -214,7 +214,7 @@ Interface.prototype._tabComplete = function () {
var group = [], c; var group = [], c;
for (var i = 0, compLen = completions.length; i < compLen; i++) { for (var i = 0, compLen = completions.length; i < compLen; i++) {
c = completions[i]; c = completions[i];
if (c === "") { if (c === '') {
handleGroup(group); handleGroup(group);
group = []; group = [];
} else { } else {
@ -225,8 +225,8 @@ Interface.prototype._tabComplete = function () {
// If there is a common prefix to all matches, then apply that // If there is a common prefix to all matches, then apply that
// portion. // portion.
var prefix = commonPrefix( var f = completions.filter(function(e) { if (e) return e; });
completions.filter(function(e) { if (e) return e; })); var prefix = commonPrefix(f);
if (prefix.length > completeOn.length) { if (prefix.length > completeOn.length) {
self._insertString(prefix.slice(completeOn.length)); self._insertString(prefix.slice(completeOn.length));
} }
@ -238,7 +238,7 @@ Interface.prototype._tabComplete = function () {
function commonPrefix(strings) { function commonPrefix(strings) {
if (!strings || strings.length == 0) { if (!strings || strings.length == 0) {
return ""; return '';
} }
var sorted = strings.slice().sort(); var sorted = strings.slice().sort();
var min = sorted[0]; var min = sorted[0];
@ -294,9 +294,9 @@ Interface.prototype._ttyWrite = function (b) {
if (this.cursor === 0 && this.line.length === 0) { if (this.cursor === 0 && this.line.length === 0) {
this.close(); this.close();
} else if (this.cursor < this.line.length) { } else if (this.cursor < this.line.length) {
this.line = this.line.slice(0, this.cursor) this.line = this.line.slice(0, this.cursor) +
+ this.line.slice(this.cursor+1, this.line.length) this.line.slice(this.cursor + 1, this.line.length);
;
this._refreshLine(); this._refreshLine();
} }
break; break;
@ -310,9 +310,9 @@ Interface.prototype._ttyWrite = function (b) {
case 127: /* backspace */ case 127: /* backspace */
case 8: /* ctrl+h */ case 8: /* ctrl+h */
if (this.cursor > 0 && this.line.length > 0) { if (this.cursor > 0 && this.line.length > 0) {
this.line = this.line.slice(0, this.cursor-1) this.line = this.line.slice(0, this.cursor - 1) +
+ this.line.slice(this.cursor, this.line.length) this.line.slice(this.cursor, this.line.length);
;
this.cursor--; this.cursor--;
this._refreshLine(); this._refreshLine();
} }
@ -379,7 +379,7 @@ Interface.prototype._ttyWrite = function (b) {
break; break;
case 26: /* ctrl+z */ case 26: /* ctrl+z */
process.kill(process.pid, "SIGTSTP"); process.kill(process.pid, 'SIGTSTP');
return; return;
case 27: /* escape sequence */ case 27: /* escape sequence */
@ -407,9 +407,8 @@ Interface.prototype._ttyWrite = function (b) {
// meta-f - forward word // meta-f - forward word
next_word = this.line.slice(this.cursor, this.line.length).search(/\w/); next_word = this.line.slice(this.cursor, this.line.length).search(/\w/);
if (next_word !== -1) { if (next_word !== -1) {
next_non_word = next_non_word = this.line.slice(this.cursor + next_word,
this.line.slice(this.cursor + next_word, this.line.length) this.line.length).search(/\W/);
.search(/\W/);
if (next_non_word !== -1) { if (next_non_word !== -1) {
this.cursor += next_word + next_non_word; this.cursor += next_word + next_non_word;
this._refreshLine(); this._refreshLine();
@ -423,12 +422,12 @@ Interface.prototype._ttyWrite = function (b) {
// meta-d delete forward word // meta-d delete forward word
next_word = this.line.slice(this.cursor, this.line.length).search(/\w/); next_word = this.line.slice(this.cursor, this.line.length).search(/\w/);
if (next_word !== -1) { if (next_word !== -1) {
next_non_word = next_non_word = this.line.slice(this.cursor + next_word,
this.line.slice(this.cursor + next_word, this.line.length) this.line.length).search(/\W/);
.search(/\W/);
if (next_non_word !== -1) { if (next_non_word !== -1) {
this.line = this.line = this.line.slice(this.cursor +
this.line.slice(this.cursor + next_word + next_non_word); next_word +
next_non_word);
this.cursor = 0; this.cursor = 0;
this._refreshLine(); this._refreshLine();
break; break;

194
lib/repl.js

@ -1,29 +1,36 @@
// A repl library that you can include in your own code to get a runtime /* A repl library that you can include in your own code to get a runtime
// interface to your program. * interface to your program.
// *
// var repl = require("/repl.js"); * var repl = require("/repl.js");
// repl.start("prompt> "); // start repl on stdin * // start repl on stdin
// net.createServer(function (socket) { // listen for unix socket connections and start repl on them * repl.start("prompt> ");
// repl.start("node via Unix socket> ", socket); *
// }).listen("/tmp/node-repl-sock"); * // listen for unix socket connections and start repl on them
// net.createServer(function (socket) { // listen for TCP socket connections and start repl on them * net.createServer(function (socket) {
// repl.start("node via TCP socket> ", socket); * repl.start("node via Unix socket> ", socket);
// }).listen(5001); * }).listen("/tmp/node-repl-sock");
*
// repl.start("node > ").context.foo = "stdin is fun"; // expose foo to repl context * // listen for TCP socket connections and start repl on them
* net.createServer(function (socket) {
* repl.start("node via TCP socket> ", socket);
* }).listen(5001);
*
* // expose foo to repl context
* repl.start("node > ").context.foo = "stdin is fun";
*/
var util = require('util'); var util = require('util');
var Script = process.binding('evals').Script; var Script = process.binding('evals').Script;
var evalcx = Script.runInContext; var evalcx = Script.runInContext;
var path = require("path"); var path = require('path');
var fs = require("fs"); var fs = require('fs');
var rl = require('readline'); var rl = require('readline');
var context; var context;
var disableColors = process.env.NODE_DISABLE_COLORS ? true : false; var disableColors = process.env.NODE_DISABLE_COLORS ? true : false;
// hack for require.resolve("./relative") to work properly. // hack for require.resolve("./relative") to work properly.
module.filename = process.cwd() + "/repl"; module.filename = process.cwd() + '/repl';
function resetContext() { function resetContext() {
context = Script.createContext(); context = Script.createContext();
@ -44,7 +51,7 @@ function REPLServer(prompt, stream) {
self.buffered_cmd = ''; self.buffered_cmd = '';
self.stream = stream || process.openStdin(); self.stream = stream || process.openStdin();
self.prompt = prompt || "> "; self.prompt = prompt || '> ';
var rli = self.rli = rl.createInterface(self.stream, function(text) { var rli = self.rli = rl.createInterface(self.stream, function(text) {
return self.complete(text); return self.complete(text);
@ -62,9 +69,9 @@ function REPLServer(prompt, stream) {
rli.setPrompt(self.prompt); rli.setPrompt(self.prompt);
rli.on("SIGINT", function () { rli.on('SIGINT', function() {
if (self.buffered_cmd && self.buffered_cmd.length > 0) { if (self.buffered_cmd && self.buffered_cmd.length > 0) {
rli.write("\n"); rli.write('\n');
self.buffered_cmd = ''; self.buffered_cmd = '';
self.displayPrompt(); self.displayPrompt();
} else { } else {
@ -72,7 +79,7 @@ function REPLServer(prompt, stream) {
} }
}); });
self.stream.addListener("data", function (chunk) { self.stream.addListener('data', function(chunk) {
rli.write(chunk); rli.write(chunk);
}); });
@ -95,30 +102,31 @@ function REPLServer(prompt, stream) {
// continue onto the next line. // continue onto the next line.
try { try {
// Use evalcx to supply the global context // Use evalcx to supply the global context
var ret = evalcx(self.buffered_cmd, context, "repl"); var ret = evalcx(self.buffered_cmd, context, 'repl');
if (ret !== undefined) { if (ret !== undefined) {
context._ = ret; context._ = ret;
self.stream.write(exports.writer(ret) + "\n"); self.stream.write(exports.writer(ret) + '\n');
} }
self.buffered_cmd = ''; self.buffered_cmd = '';
} catch (e) { } catch (e) {
// instanceof doesn't work across context switches. // instanceof doesn't work across context switches.
if (!(e && e.constructor && e.constructor.name === "SyntaxError")) { if (!(e && e.constructor && e.constructor.name === 'SyntaxError')) {
throw e; throw e;
// It could also be an error from JSON.parse // It could also be an error from JSON.parse
} else if(e && e.stack } else if (e &&
&& e.stack.match('Unexpected token ILLEGAL') e.stack &&
&& e.stack.match(/Object.parse \(native\)/)) { e.stack.match('Unexpected token ILLEGAL') &&
e.stack.match(/Object.parse \(native\)/)) {
throw e; throw e;
} }
} }
} catch (e) { } catch (e) {
// On error: Print the error and clear the buffer // On error: Print the error and clear the buffer
if (e.stack) { if (e.stack) {
self.stream.write(e.stack + "\n"); self.stream.write(e.stack + '\n');
} else { } else {
self.stream.write(e.toString() + "\n"); self.stream.write(e.toString() + '\n');
} }
self.buffered_cmd = ''; self.buffered_cmd = '';
} }
@ -149,28 +157,23 @@ REPLServer.prototype.displayPrompt = function () {
REPLServer.prototype.readline = function(cmd) { REPLServer.prototype.readline = function(cmd) {
}; };
/** // Provide a list of completions for the given leading text. This is
* Provide a list of completions for the given leading text. This is // given to the readline interface for handling tab completion.
* given to the readline interface for handling tab completion. //
* // Example:
* @param {line} The text (preceding the cursor) to complete // complete('var foo = util.')
* @returns {Array} Two elements: (1) an array of completions; and // -> [['util.print', 'util.debug', 'util.log', 'util.inspect', 'util.pump'],
* (2) the leading text completed. // 'util.' ]
* //
* Example: // Warning: This eval's code like "foo.bar.baz", so it will run property
* complete('var foo = util.') // getter code.
* -> [['util.print', 'util.debug', 'util.log', 'util.inspect', 'util.pump'],
* 'util.' ]
*
* Warning: This eval's code like "foo.bar.baz", so it will run property
* getter code.
*/
REPLServer.prototype.complete = function(line) { REPLServer.prototype.complete = function(line) {
var completions, var completions;
completionGroups = [], // list of completion lists, one for each inheritance "level"
completeOn, // list of completion lists, one for each inheritance "level"
match, filter, i, j, group, c; var completionGroups = [];
var completeOn, match, filter, i, j, group, c;
// REPL commands (e.g. ".break"). // REPL commands (e.g. ".break").
var match = null; var match = null;
@ -181,17 +184,19 @@ REPLServer.prototype.complete = function (line) {
if (match[1].length > 1) { if (match[1].length > 1) {
filter = match[1]; filter = match[1];
} }
} } else if (match =
line.match(/\brequire\s*\(['"](([\w\.\/-]+\/)?([\w\.\/-]*))/)) {
// require('...<Tab>') // require('...<Tab>')
else if (match = line.match(/\brequire\s*\(['"](([\w\.\/-]+\/)?([\w\.\/-]*))/)) { //TODO: suggest require.exts be exposed to be introspec registered
//TODO: suggest require.exts be exposed to be introspec registered extensions? //extensions?
//TODO: suggest include the '.' in exts in internal repr: parity with `path.extname`. //TODO: suggest include the '.' in exts in internal repr: parity with
var exts = [".js", ".node"]; //`path.extname`.
var indexRe = new RegExp('^index(' + exts.map(regexpEscape).join('|') + ')$'); var exts = ['.js', '.node'];
var indexRe = new RegExp('^index(' + exts.map(regexpEscape).join('|') +
')$');
completeOn = match[1]; completeOn = match[1];
var subdir = match[2] || ""; var subdir = match[2] || '';
var filter = match[1]; var filter = match[1];
var dir, files, f, name, base, ext, abs, subfiles, s; var dir, files, f, name, base, ext, abs, subfiles, s;
group = []; group = [];
@ -211,12 +216,12 @@ REPLServer.prototype.complete = function (line) {
name = files[f]; name = files[f];
ext = path.extname(name); ext = path.extname(name);
base = name.slice(0, -ext.length); base = name.slice(0, -ext.length);
if (base.match(/-\d+\.\d+(\.\d+)?/) || name === ".npm") { if (base.match(/-\d+\.\d+(\.\d+)?/) || name === '.npm') {
// Exclude versioned names that 'npm' installs. // Exclude versioned names that 'npm' installs.
continue; continue;
} }
if (exts.indexOf(ext) !== -1) { if (exts.indexOf(ext) !== -1) {
if (!subdir || base !== "index") { if (!subdir || base !== 'index') {
group.push(subdir + base); group.push(subdir + base);
} }
} else { } else {
@ -244,7 +249,8 @@ REPLServer.prototype.complete = function (line) {
// Intentionally excluding moved modules: posix, utils. // Intentionally excluding moved modules: posix, utils.
var builtinLibs = ['assert', 'buffer', 'child_process', 'crypto', 'dgram', var builtinLibs = ['assert', 'buffer', 'child_process', 'crypto', 'dgram',
'dns', 'events', 'file', 'freelist', 'fs', 'http', 'net', 'path', 'dns', 'events', 'file', 'freelist', 'fs', 'http', 'net', 'path',
'querystring', 'readline', 'repl', 'string_decoder', 'util', 'tcp', 'url']; 'querystring', 'readline', 'repl', 'string_decoder', 'util', 'tcp',
'url'];
completionGroups.push(builtinLibs); completionGroups.push(builtinLibs);
} }
} }
@ -260,23 +266,26 @@ REPLServer.prototype.complete = function (line) {
// foo<|> # all scope vars with filter 'foo' // foo<|> # all scope vars with filter 'foo'
// foo.<|> # completions for 'foo' with filter '' // foo.<|> # completions for 'foo' with filter ''
else if (line.length === 0 || line[line.length - 1].match(/\w|\.|\$/)) { else if (line.length === 0 || line[line.length - 1].match(/\w|\.|\$/)) {
var simpleExpressionPat = /(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/; var simpleExpressionPat =
/(([a-zA-Z_$](?:\w|\$)*)\.)*([a-zA-Z_$](?:\w|\$)*)\.?$/;
match = simpleExpressionPat.exec(line); match = simpleExpressionPat.exec(line);
if (line.length === 0 || match) { if (line.length === 0 || match) {
var expr; var expr;
completeOn = (match ? match[0] : ""); completeOn = (match ? match[0] : '');
if (line.length === 0) { if (line.length === 0) {
filter = ""; filter = '';
expr = ""; expr = '';
} else if (line[line.length - 1] === '.') { } else if (line[line.length - 1] === '.') {
filter = ""; filter = '';
expr = match[0].slice(0, match[0].length - 1); expr = match[0].slice(0, match[0].length - 1);
} else { } else {
var bits = match[0].split('.'); var bits = match[0].split('.');
filter = bits.pop(); filter = bits.pop();
expr = bits.join('.'); expr = bits.join('.');
} }
//console.log("expression completion: completeOn='"+completeOn+"' expr='"+expr+"'");
// console.log("expression completion: completeOn='" + completeOn +
// "' expr='" + expr + "'");
// Resolve expr and get its completions. // Resolve expr and get its completions.
var obj, memberGroups = []; var obj, memberGroups = [];
@ -284,31 +293,31 @@ REPLServer.prototype.complete = function (line) {
completionGroups.push(Object.getOwnPropertyNames(this.context)); completionGroups.push(Object.getOwnPropertyNames(this.context));
// Global object properties // Global object properties
// (http://www.ecma-international.org/publications/standards/Ecma-262.htm) // (http://www.ecma-international.org/publications/standards/Ecma-262.htm)
completionGroups.push(["NaN", "Infinity", "undefined", completionGroups.push(['NaN', 'Infinity', 'undefined',
"eval", "parseInt", "parseFloat", "isNaN", "isFinite", "decodeURI", 'eval', 'parseInt', 'parseFloat', 'isNaN', 'isFinite', 'decodeURI',
"decodeURIComponent", "encodeURI", "encodeURIComponent", 'decodeURIComponent', 'encodeURI', 'encodeURIComponent',
"Object", "Function", "Array", "String", "Boolean", "Number", 'Object', 'Function', 'Array', 'String', 'Boolean', 'Number',
"Date", "RegExp", "Error", "EvalError", "RangeError", 'Date', 'RegExp', 'Error', 'EvalError', 'RangeError',
"ReferenceError", "SyntaxError", "TypeError", "URIError", 'ReferenceError', 'SyntaxError', 'TypeError', 'URIError',
"Math", "JSON"]); 'Math', 'JSON']);
// Common keywords. Exclude for completion on the empty string, b/c // Common keywords. Exclude for completion on the empty string, b/c
// they just get in the way. // they just get in the way.
if (filter) { if (filter) {
completionGroups.push(["break", "case", "catch", "const", completionGroups.push(['break', 'case', 'catch', 'const',
"continue", "debugger", "default", "delete", "do", "else", "export", 'continue', 'debugger', 'default', 'delete', 'do', 'else', 'export',
"false", "finally", "for", "function", "if", "import", "in", 'false', 'finally', 'for', 'function', 'if', 'import', 'in',
"instanceof", "let", "new", "null", "return", "switch", "this", 'instanceof', 'let', 'new', 'null', 'return', 'switch', 'this',
"throw", "true", "try", "typeof", "undefined", "var", "void", 'throw', 'true', 'try', 'typeof', 'undefined', 'var', 'void',
"while", "with", "yield"]); 'while', 'with', 'yield']);
} }
} else { } else {
try { try {
obj = evalcx(expr, this.context, "repl"); obj = evalcx(expr, this.context, 'repl');
} catch (e) { } catch (e) {
//console.log("completion eval error, expr='"+expr+"': "+e); //console.log("completion eval error, expr='"+expr+"': "+e);
} }
if (obj != null) { if (obj != null) {
if (typeof obj === "object" || typeof obj === "function") { if (typeof obj === 'object' || typeof obj === 'function') {
memberGroups.push(Object.getOwnPropertyNames(obj)); memberGroups.push(Object.getOwnPropertyNames(obj));
} }
// works for non-objects // works for non-objects
@ -371,9 +380,9 @@ REPLServer.prototype.complete = function (line) {
uniq[c] = true; uniq[c] = true;
} }
} }
completions.push(""); // separator btwn groups completions.push(''); // separator btwn groups
} }
while (completions.length && completions[completions.length-1] === "") { while (completions.length && completions[completions.length - 1] === '') {
completions.pop(); completions.pop();
} }
} }
@ -384,8 +393,8 @@ REPLServer.prototype.complete = function (line) {
/** /**
* Used to parse and execute the Node REPL commands. * Used to parse and execute the Node REPL commands.
* *
* @param {cmd} cmd The command entered to check * @param {keyword} keyword The command entered to check.
* @returns {Boolean} If true it means don't continue parsing the command * @return {Boolean} If true it means don't continue parsing the command.
*/ */
REPLServer.prototype.parseREPLKeyword = function(keyword, rest) { REPLServer.prototype.parseREPLKeyword = function(keyword, rest) {
@ -418,7 +427,7 @@ function defineDefaultCommands(repl) {
repl.defineCommand('clear', { repl.defineCommand('clear', {
help: 'Break, and also clear the local context', help: 'Break, and also clear the local context',
action: function() { action: function() {
this.stream.write("Clearing context...\n"); this.stream.write('Clearing context...\n');
this.buffered_cmd = ''; this.buffered_cmd = '';
resetContext(); resetContext();
this.displayPrompt(); this.displayPrompt();
@ -438,7 +447,7 @@ function defineDefaultCommands(repl) {
var self = this; var self = this;
Object.keys(this.commands).sort().forEach(function(name) { Object.keys(this.commands).sort().forEach(function(name) {
var cmd = self.commands[name]; var cmd = self.commands[name];
self.stream.write(name + "\t" + (cmd.help || '') + "\n"); self.stream.write(name + '\t' + (cmd.help || '') + '\n');
}); });
this.displayPrompt(); this.displayPrompt();
} }
@ -455,16 +464,17 @@ function trimWhitespace (cmd) {
} }
function regexpEscape(s) { function regexpEscape(s) {
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
} }
/** /**
* Converts commands that use var and function <name>() to use the * Converts commands that use var and function <name>() to use the
* local exports.context when evaled. This provides a local context * local exports.context when evaled. This provides a local context
* on the REPL. * on the REPL.
* *
* @param {String} cmd The cmd to convert * @param {String} cmd The cmd to convert.
* @returns {String} The converted command * @return {String} The converted command.
*/ */
REPLServer.prototype.convertToContext = function(cmd) { REPLServer.prototype.convertToContext = function(cmd) {
var self = this, matches, var self = this, matches,
@ -474,13 +484,13 @@ REPLServer.prototype.convertToContext = function (cmd) {
// Replaces: var foo = "bar"; with: self.context.foo = bar; // Replaces: var foo = "bar"; with: self.context.foo = bar;
matches = scopeVar.exec(cmd); matches = scopeVar.exec(cmd);
if (matches && matches.length === 3) { if (matches && matches.length === 3) {
return "self.context." + matches[1] + matches[2]; return 'self.context.' + matches[1] + matches[2];
} }
// Replaces: function foo() {}; with: foo = function foo() {}; // Replaces: function foo() {}; with: foo = function foo() {};
matches = scopeFunc.exec(self.buffered_cmd); matches = scopeFunc.exec(self.buffered_cmd);
if (matches && matches.length === 2) { if (matches && matches.length === 2) {
return matches[1] + " = " + self.buffered_cmd; return matches[1] + ' = ' + self.buffered_cmd;
} }
return cmd; return cmd;

39
lib/securepair.js

@ -5,10 +5,11 @@ var assert = process.assert;
var debugLevel = parseInt(process.env.NODE_DEBUG, 16); var debugLevel = parseInt(process.env.NODE_DEBUG, 16);
function debug () { var debug;
if (debugLevel & 0x2) { if (debugLevel & 0x2) {
util.error.apply(this, arguments); debug = function() { util.error.apply(this, arguments); };
} } else {
debug = function() { };
} }
@ -41,7 +42,7 @@ function SecurePair(credentials, isServer, shouldVerifyPeer) {
this._clearWriteState = true; this._clearWriteState = true;
this._done = false; this._done = false;
var crypto = require("crypto"); var crypto = require('crypto');
if (!credentials) { if (!credentials) {
this.credentials = crypto.createCredentials(); this.credentials = crypto.createCredentials();
@ -50,7 +51,8 @@ function SecurePair(credentials, isServer, shouldVerifyPeer) {
} }
if (!this._isServer) { if (!this._isServer) {
/* For clients, we will always have either a given ca list or be using default one */ // For clients, we will always have either a given ca list or be using
// default one
shouldVerifyPeer = true; shouldVerifyPeer = true;
} }
@ -144,13 +146,15 @@ function SecurePair(credentials, isServer, shouldVerifyPeer) {
this.encrypted.on('end', function() { this.encrypted.on('end', function() {
if (!self._done) { if (!self._done) {
self._error(new Error('Encrypted stream ended before secure pair was done')); self._error(
new Error('Encrypted stream ended before secure pair was done'));
} }
}); });
this.encrypted.on('close', function() { this.encrypted.on('close', function() {
if (!self._done) { if (!self._done) {
self._error(new Error('Encrypted stream closed before secure pair was done')); self._error(
new Error('Encrypted stream closed before secure pair was done'));
} }
}); });
@ -180,6 +184,7 @@ exports.createSecurePair = function (credentials, isServer, shouldVerifyPeer) {
return pair; return pair;
}; };
/** /**
* Attempt to cycle OpenSSLs buffers in various directions. * Attempt to cycle OpenSSLs buffers in various directions.
* *
@ -189,22 +194,24 @@ exports.createSecurePair = function (credentials, isServer, shouldVerifyPeer) {
* but consider things like mid-stream renegotiation of * but consider things like mid-stream renegotiation of
* the ciphers. * the ciphers.
* *
* The four pipelines, using terminology of the client (server is just reversed): * The four pipelines, using terminology of the client (server is just
* reversed):
* (1) Encrypted Output stream (Writing encrypted data to peer) * (1) Encrypted Output stream (Writing encrypted data to peer)
* (2) Encrypted Input stream (Reading encrypted data from peer) * (2) Encrypted Input stream (Reading encrypted data from peer)
* (3) Cleartext Output stream (Decrypted content from the peer) * (3) Cleartext Output stream (Decrypted content from the peer)
* (4) Cleartext Input stream (Cleartext content to send to the peer) * (4) Cleartext Input stream (Cleartext content to send to the peer)
* *
* This function attempts to pull any available data out of the Cleartext * This function attempts to pull any available data out of the Cleartext
* input stream (4), and the Encrypted input stream (2). Then it pushes * input stream (4), and the Encrypted input stream (2). Then it pushes any
* any data available from the cleartext output stream (3), and finally * data available from the cleartext output stream (3), and finally from the
* from the Encrypted output stream (1) * Encrypted output stream (1)
* *
* It is called whenever we do something with OpenSSL -- post reciving content, * It is called whenever we do something with OpenSSL -- post reciving
* trying to flush, trying to change ciphers, or shutting down the connection. * content, trying to flush, trying to change ciphers, or shutting down the
* connection.
* *
* Because it is also called everywhere, we also check if the connection * Because it is also called everywhere, we also check if the connection has
* has completed negotiation and emit 'secure' from here if it has. * completed negotiation and emit 'secure' from here if it has.
*/ */
SecurePair.prototype._cycle = function() { SecurePair.prototype._cycle = function() {
if (this._done) { if (this._done) {
@ -281,7 +288,7 @@ SecurePair.prototype._cycle = function () {
try { try {
chunkBytes = reader(pool, chunkBytes = reader(pool,
pool.used + bytesRead, pool.used + bytesRead,
pool.length - pool.used - bytesRead) pool.length - pool.used - bytesRead);
} catch (e) { } catch (e) {
return self._error(e); return self._error(e);
} }

Loading…
Cancel
Save