diff --git a/CPP_STYLE_GUIDE.md b/CPP_STYLE_GUIDE.md index 62c96a8fd12..6266ee03b7c 100644 --- a/CPP_STYLE_GUIDE.md +++ b/CPP_STYLE_GUIDE.md @@ -4,6 +4,7 @@ * [Formatting](#formatting) * [Left-leaning (C++ style) asterisks for pointer declarations](#left-leaning-c-style-asterisks-for-pointer-declarations) + * [C++ style comments](#c-style-comments) * [2 spaces of indentation for blocks or bodies of conditionals](#2-spaces-of-indentation-for-blocks-or-bodies-of-conditionals) * [4 spaces of indentation for statement continuations](#4-spaces-of-indentation-for-statement-continuations) * [Align function arguments vertically](#align-function-arguments-vertically) @@ -33,6 +34,26 @@ these rules: `char* buffer;` instead of `char *buffer;` +## C++ style comments + +Use C++ style comments (`//`) for both single-line and multi-line comments. +Comments should also start with uppercase and finish with a dot. + +Examples: + +```c++ +// A single-line comment. + +// Multi-line comments +// should also use C++ +// style comments. +``` + +The codebase may contain old C style comments (`/* */`) from before this was the +preferred style. Feel free to update old comments to the preferred style when +working on code in the immediate vicinity or when changing/improving those +comments. + ## 2 spaces of indentation for blocks or bodies of conditionals ```c++ diff --git a/benchmark/http/upgrade.js b/benchmark/http/upgrade.js new file mode 100644 index 00000000000..0feaecc8ff1 --- /dev/null +++ b/benchmark/http/upgrade.js @@ -0,0 +1,53 @@ +'use strict'; + +const common = require('../common.js'); +const PORT = common.PORT; +const net = require('net'); + +const bench = common.createBenchmark(main, { + n: [5, 1000] +}); + +const reqData = 'GET / HTTP/1.1\r\n' + + 'Upgrade: WebSocket\r\n' + + 'Connection: Upgrade\r\n' + + '\r\n' + + 'WjN}|M(6'; + +const resData = 'HTTP/1.1 101 Web Socket Protocol Handshake\r\n' + + 'Upgrade: WebSocket\r\n' + + 'Connection: Upgrade\r\n' + + '\r\n\r\n'; + +function main({ n }) { + process.env.PORT = PORT; + var server = require('../fixtures/simple-http-server.js') + .listen(common.PORT) + .on('listening', function() { + bench.start(); + doBench(server.address(), n, function() { + bench.end(n); + server.close(); + }); + }) + .on('upgrade', function(req, socket, upgradeHead) { + socket.resume(); + socket.write(resData); + socket.end(); + }); +} + +function doBench(address, count, done) { + if (count === 0) { + done(); + return; + } + + const conn = net.createConnection(address.port); + conn.write(reqData); + conn.resume(); + + conn.on('end', function() { + doBench(address, count - 1, done); + }); +} diff --git a/doc/api/stream.md b/doc/api/stream.md index f3780ee4c49..dc74df7720e 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -63,8 +63,8 @@ object mode is not safe. Both [Writable][] and [Readable][] streams will store data in an internal -buffer that can be retrieved using `writable._writableState.getBuffer()` or -`readable._readableState.buffer`, respectively. +buffer that can be retrieved using `writable.writableBuffer` or +`readable.readableBuffer`, respectively. The amount of data potentially buffered depends on the `highWaterMark` option passed into the streams constructor. For normal streams, the `highWaterMark` @@ -602,22 +602,22 @@ Readable stream implementation. Specifically, at any given point in time, every Readable is in one of three possible states: -* `readable._readableState.flowing = null` -* `readable._readableState.flowing = false` -* `readable._readableState.flowing = true` +* `readable.readableFlowing = null` +* `readable.readableFlowing = false` +* `readable.readableFlowing = true` -When `readable._readableState.flowing` is `null`, no mechanism for consuming the +When `readable.readableFlowing` is `null`, no mechanism for consuming the streams data is provided so the stream will not generate its data. While in this state, attaching a listener for the `'data'` event, calling the `readable.pipe()` method, or calling the `readable.resume()` method will switch -`readable._readableState.flowing` to `true`, causing the Readable to begin +`readable.readableFlowing` to `true`, causing the Readable to begin actively emitting events as data is generated. Calling `readable.pause()`, `readable.unpipe()`, or receiving "back pressure" -will cause the `readable._readableState.flowing` to be set as `false`, +will cause the `readable.readableFlowing` to be set as `false`, temporarily halting the flowing of events but *not* halting the generation of data. While in this state, attaching a listener for the `'data'` event -would not cause `readable._readableState.flowing` to switch to `true`. +would not cause `readable.readableFlowing` to switch to `true`. ```js const { PassThrough, Writable } = require('stream'); @@ -626,14 +626,14 @@ const writable = new Writable(); pass.pipe(writable); pass.unpipe(writable); -// flowing is now false +// readableFlowing is now false pass.on('data', (chunk) => { console.log(chunk.toString()); }); pass.write('ok'); // will not emit 'data' pass.resume(); // must be called to make 'data' being emitted ``` -While `readable._readableState.flowing` is `false`, data may be accumulating +While `readable.readableFlowing` is `false`, data may be accumulating within the streams internal buffer. #### Choose One diff --git a/doc/api/url.md b/doc/api/url.md index 00211095627..5f504a5bc89 100644 --- a/doc/api/url.md +++ b/doc/api/url.md @@ -1107,12 +1107,15 @@ forward slash (`/`) character is encoded as `%3C`. The [WHATWG URL Standard][] uses a more selective and fine grained approach to selecting encoded characters than that used by the Legacy API. -The WHATWG algorithm defines three "percent-encode sets" that describe ranges +The WHATWG algorithm defines four "percent-encode sets" that describe ranges of characters that must be percent-encoded: * The *C0 control percent-encode set* includes code points in range U+0000 to U+001F (inclusive) and all code points greater than U+007E. +* The *fragment percent-encode set* includes the *C0 control percent-encode set* + and code points U+0020, U+0022, U+003C, U+003E, and U+0060. + * The *path percent-encode set* includes the *C0 control percent-encode set* and code points U+0020, U+0022, U+0023, U+003C, U+003E, U+003F, U+0060, U+007B, and U+007D. @@ -1123,9 +1126,9 @@ of characters that must be percent-encoded: The *userinfo percent-encode set* is used exclusively for username and passwords encoded within the URL. The *path percent-encode set* is used for the -path of most URLs. The *C0 control percent-encode set* is used for all -other cases, including URL fragments in particular, but also host and path -under certain specific conditions. +path of most URLs. The *fragment percent-encode set* is used for URL fragments. +The *C0 control percent-encode set* is used for host and path under certain +specific conditions, in addition to all other cases. When non-ASCII characters appear within a hostname, the hostname is encoded using the [Punycode][] algorithm. Note, however, that a hostname *may* contain diff --git a/doc/api/util.md b/doc/api/util.md index 8e3befcebf6..1e729541265 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -104,6 +104,19 @@ FOO 3245: hello from foo [123] where `3245` is the process id. If it is not run with that environment variable set, then it will not print anything. +The `section` supports wildcard also, for example: +```js +const util = require('util'); +const debuglog = util.debuglog('foo-bar'); + +debuglog('hi there, it\'s foo-bar [%d]', 2333); +``` + +if it is run with `NODE_DEBUG=foo*` in the environment, then it will output something like: +```txt +FOO-BAR 3257: hi there, it's foo-bar [2333] +``` + Multiple comma-separated `section` names may be specified in the `NODE_DEBUG` environment variable. For example: `NODE_DEBUG=fs,net,tls`. diff --git a/lib/_http_client.js b/lib/_http_client.js index bdda708493a..d9a2d10ae24 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -432,9 +432,7 @@ function socketOnData(d) { socket.removeListener('close', socketCloseListener); socket.removeListener('error', socketErrorListener); - // TODO(isaacs): Need a way to reset a stream to fresh state - // IE, not flowing, and not explicitly paused. - socket._readableState.flowing = null; + socket.readableFlowing = null; req.emit(eventName, res, socket, bodyHead); req.emit('close'); diff --git a/lib/_http_server.js b/lib/_http_server.js index 7315a266b89..cab48245010 100644 --- a/lib/_http_server.js +++ b/lib/_http_server.js @@ -449,7 +449,7 @@ function socketOnData(server, socket, parser, state, d) { onParserExecuteCommon(server, socket, parser, state, ret, d); } -function onParserExecute(server, socket, parser, state, ret, d) { +function onParserExecute(server, socket, parser, state, ret) { socket._unrefTimer(); debug('SERVER socketOnParserExecute %d', ret); onParserExecuteCommon(server, socket, parser, state, ret, undefined); @@ -502,9 +502,7 @@ function onParserExecuteCommon(server, socket, parser, state, ret, d) { debug('SERVER have listener for %s', eventName); var bodyHead = d.slice(bytesParsed, d.length); - // TODO(isaacs): Need a way to reset a stream to fresh state - // IE, not flowing, and not explicitly paused. - socket._readableState.flowing = null; + socket.readableFlowing = null; server.emit(eventName, req, socket, bodyHead); } else { // Got upgrade header or CONNECT method, but have no handler. diff --git a/lib/_stream_duplex.js b/lib/_stream_duplex.js index 05f64934084..e99d246396f 100644 --- a/lib/_stream_duplex.js +++ b/lib/_stream_duplex.js @@ -74,6 +74,16 @@ Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { } }); +Object.defineProperty(Duplex.prototype, 'writableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function() { + return this._writableState && this._writableState.getBuffer(); + } +}); + // the no-half-open enforcer function onend() { // if we allow half-open state, or if the writable side ended, diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 01d886e6cab..2653d3835d8 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -925,6 +925,31 @@ Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { } }); +Object.defineProperty(Readable.prototype, 'readableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function() { + return this._readableState && this._readableState.buffer; + } +}); + +Object.defineProperty(Readable.prototype, 'readableFlowing', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function() { + return this._readableState.flowing; + }, + set: function(state) { + if (this._readableState) { + this._readableState.flowing = state; + } + } +}); + // exposed for testing purposes only. Readable._fromList = fromList; diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index 02481739250..97fbebdd66d 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -249,9 +249,7 @@ function validChunk(stream, state, chunk, cb) { if (chunk === null) { er = new errors.TypeError('ERR_STREAM_NULL_VALUES'); - } else if (typeof chunk !== 'string' && - chunk !== undefined && - !state.objectMode) { + } else if (typeof chunk !== 'string' && !state.objectMode) { er = new errors.TypeError('ERR_INVALID_ARG_TYPE', 'chunk', ['string', 'Buffer']); } @@ -326,6 +324,16 @@ Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { return this; }; +Object.defineProperty(Writable.prototype, 'writableBuffer', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function() { + return this._writableState && this._writableState.getBuffer(); + } +}); + function decodeChunk(state, chunk, encoding) { if (!state.objectMode && state.decodeStrings !== false && diff --git a/lib/assert.js b/lib/assert.js index 7af74c1da95..9a1ded0e102 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -38,19 +38,13 @@ const assert = module.exports = ok; // both the actual and expected values to the assertion error for // display purposes. -function innerFail(actual, expected, message, operator, stackStartFunction) { - if (message instanceof Error) throw message; +function innerFail(obj) { + if (obj.message instanceof Error) throw obj.message; - throw new errors.AssertionError({ - message, - actual, - expected, - operator, - stackStartFunction - }); + throw new errors.AssertionError(obj); } -function fail(actual, expected, message, operator, stackStartFunction) { +function fail(actual, expected, message, operator, stackStartFn) { trace_mgr.emitTrace('emitOnAssert'); //ENABLE_TTD const argsLen = arguments.length; @@ -64,7 +58,13 @@ function fail(actual, expected, message, operator, stackStartFunction) { operator = '!='; } - innerFail(actual, expected, message, operator, stackStartFunction || fail); + innerFail({ + actual, + expected, + message, + operator, + stackStartFn: stackStartFn || fail + }); } assert.fail = fail; @@ -79,7 +79,15 @@ assert.AssertionError = errors.AssertionError; // Pure assertion tests whether a value is truthy, as determined // by !!value. function ok(value, message) { - if (!value) innerFail(value, true, message, '==', ok); + if (!value) { + innerFail({ + actual: value, + expected: true, + message, + operator: '==', + stackStartFn: ok + }); + } } assert.ok = ok; @@ -87,7 +95,15 @@ assert.ok = ok; /* eslint-disable no-restricted-properties */ assert.equal = function equal(actual, expected, message) { // eslint-disable-next-line eqeqeq - if (actual != expected) innerFail(actual, expected, message, '==', equal); + if (actual != expected) { + innerFail({ + actual, + expected, + message, + operator: '==', + stackStartFn: equal + }); + } }; // The non-equality assertion tests for whether two objects are not @@ -95,48 +111,89 @@ assert.equal = function equal(actual, expected, message) { assert.notEqual = function notEqual(actual, expected, message) { // eslint-disable-next-line eqeqeq if (actual == expected) { - innerFail(actual, expected, message, '!=', notEqual); + innerFail({ + actual, + expected, + message, + operator: '!=', + stackStartFn: notEqual + }); } }; // The equivalence assertion tests a deep equality relation. assert.deepEqual = function deepEqual(actual, expected, message) { if (!isDeepEqual(actual, expected)) { - innerFail(actual, expected, message, 'deepEqual', deepEqual); + innerFail({ + actual, + expected, + message, + operator: 'deepEqual', + stackStartFn: deepEqual + }); } }; // The non-equivalence assertion tests for any deep inequality. assert.notDeepEqual = function notDeepEqual(actual, expected, message) { if (isDeepEqual(actual, expected)) { - innerFail(actual, expected, message, 'notDeepEqual', notDeepEqual); + innerFail({ + actual, + expected, + message, + operator: 'notDeepEqual', + stackStartFn: notDeepEqual + }); } }; /* eslint-enable */ assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { if (!isDeepStrictEqual(actual, expected)) { - innerFail(actual, expected, message, 'deepStrictEqual', deepStrictEqual); + innerFail({ + actual, + expected, + message, + operator: 'deepStrictEqual', + stackStartFn: deepStrictEqual + }); } }; assert.notDeepStrictEqual = notDeepStrictEqual; function notDeepStrictEqual(actual, expected, message) { if (isDeepStrictEqual(actual, expected)) { - innerFail(actual, expected, message, 'notDeepStrictEqual', - notDeepStrictEqual); + innerFail({ + actual, + expected, + message, + operator: 'notDeepStrictEqual', + stackStartFn: notDeepStrictEqual + }); } } assert.strictEqual = function strictEqual(actual, expected, message) { if (!Object.is(actual, expected)) { - innerFail(actual, expected, message, 'strictEqual', strictEqual); + innerFail({ + actual, + expected, + message, + operator: 'strictEqual', + stackStartFn: strictEqual + }); } }; assert.notStrictEqual = function notStrictEqual(actual, expected, message) { if (Object.is(actual, expected)) { - innerFail(actual, expected, message, 'notStrictEqual', notStrictEqual); + innerFail({ + actual, + expected, + message, + operator: 'notStrictEqual', + stackStartFn: notStrictEqual + }); } }; @@ -184,7 +241,13 @@ function innerThrows(shouldThrow, block, expected, message) { details += ` (${expected.name})`; } details += message ? `: ${message}` : '.'; - fail(actual, expected, `Missing expected exception${details}`, fail); + innerFail({ + actual, + expected, + operator: 'throws', + message: `Missing expected exception${details}`, + stackStartFn: innerThrows + }); } if (expected && expectedException(actual, expected) === false) { throw actual; @@ -192,10 +255,13 @@ function innerThrows(shouldThrow, block, expected, message) { } else if (actual !== undefined) { if (!expected || expectedException(actual, expected)) { details = message ? `: ${message}` : '.'; - fail(actual, - expected, - `Got unwanted exception${details}\n${actual.message}`, - fail); + innerFail({ + actual, + expected, + operator: 'doesNotThrow', + message: `Got unwanted exception${details}\n${actual.message}`, + stackStartFn: innerThrows + }); } throw actual; } diff --git a/lib/internal/errors.js b/lib/internal/errors.js index dadba400b50..ab0d2fe54eb 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -136,7 +136,7 @@ class AssertionError extends Error { if (typeof options !== 'object' || options === null) { throw new exports.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'Object'); } - var { actual, expected, message, operator, stackStartFunction } = options; + var { actual, expected, message, operator, stackStartFn } = options; if (message) { super(message); } else { @@ -155,7 +155,7 @@ class AssertionError extends Error { this.actual = actual; this.expected = expected; this.operator = operator; - Error.captureStackTrace(this, stackStartFunction); + Error.captureStackTrace(this, stackStartFn); } } diff --git a/lib/net.js b/lib/net.js index f962a848fad..aa27e700508 100644 --- a/lib/net.js +++ b/lib/net.js @@ -254,7 +254,7 @@ function Socket(options) { // stop the handle from reading and pause the stream this._handle.reading = false; this._handle.readStop(); - this._readableState.flowing = false; + this.readableFlowing = false; } else if (!options.manualStart) { this.read(0); } @@ -701,17 +701,6 @@ protoGetter('localPort', function localPort() { }); -Socket.prototype.write = function(chunk, encoding, cb) { - if (typeof chunk !== 'string' && !(chunk instanceof Buffer)) { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', - 'chunk', - ['string', 'Buffer'], - chunk); - } - return stream.Duplex.prototype.write.apply(this, arguments); -}; - - Socket.prototype._writeGeneric = function(writev, data, encoding, cb) { // If we are still connecting, then buffer this for later. // The Writable logic will buffer up any more writes while @@ -830,7 +819,7 @@ protoGetter('bytesWritten', function bytesWritten() { if (!state) return undefined; - state.getBuffer().forEach(function(el) { + this.writableBuffer.forEach(function(el) { if (el.chunk instanceof Buffer) bytes += el.chunk.length; else diff --git a/lib/util.js b/lib/util.js index 7eae9a99069..0a7af758f43 100644 --- a/lib/util.js +++ b/lib/util.js @@ -230,17 +230,21 @@ function format(f) { return str; } -var debugs = {}; -var debugEnviron; +const debugs = {}; +let debugEnvRegex = /^$/; +if (process.env.NODE_DEBUG) { + let debugEnv = process.env.NODE_DEBUG; + debugEnv = debugEnv.replace(/[|\\{}()[\]^$+?.]/g, '\\$&') + .replace(/\*/g, '.*') + .replace(/,/g, '$|^') + .toUpperCase(); + debugEnvRegex = new RegExp(`^${debugEnv}$`, 'i'); +} function debuglog(set) { - if (debugEnviron === undefined) { - debugEnviron = new Set( - (process.env.NODE_DEBUG || '').split(',').map((s) => s.toUpperCase())); - } set = set.toUpperCase(); if (!debugs[set]) { - if (debugEnviron.has(set)) { + if (debugEnvRegex.test(set)) { var pid = process.pid; debugs[set] = function() { var msg = exports.format.apply(exports, arguments); diff --git a/src/env.h b/src/env.h index 4fb33427657..7ee016f65d8 100644 --- a/src/env.h +++ b/src/env.h @@ -107,7 +107,6 @@ class ModuleWrap; V(cached_data_string, "cachedData") \ V(cached_data_produced_string, "cachedDataProduced") \ V(cached_data_rejected_string, "cachedDataRejected") \ - V(callback_string, "callback") \ V(change_string, "change") \ V(channel_string, "channel") \ V(chunks_sent_since_last_write_string, "chunksSentSinceLastWrite") \ @@ -115,10 +114,8 @@ class ModuleWrap; V(oncertcb_string, "oncertcb") \ V(onclose_string, "_onclose") \ V(code_string, "code") \ - V(configurable_string, "configurable") \ V(cwd_string, "cwd") \ V(dest_string, "dest") \ - V(destroy_string, "destroy") \ V(destroyed_string, "destroyed") \ V(detached_string, "detached") \ V(dns_a_string, "A") \ @@ -132,13 +129,8 @@ class ModuleWrap; V(dns_srv_string, "SRV") \ V(dns_txt_string, "TXT") \ V(domain_string, "domain") \ - V(emit_string, "emit") \ V(emit_warning_string, "emitWarning") \ V(exchange_string, "exchange") \ - V(enumerable_string, "enumerable") \ - V(idle_string, "idle") \ - V(irq_string, "irq") \ - V(enablepush_string, "enablePush") \ V(encoding_string, "encoding") \ V(enter_string, "enter") \ V(entries_string, "entries") \ @@ -159,16 +151,12 @@ class ModuleWrap; V(file_string, "file") \ V(fingerprint_string, "fingerprint") \ V(flags_string, "flags") \ - V(get_string, "get") \ V(get_data_clone_error_string, "_getDataCloneError") \ V(get_shared_array_buffer_id_string, "_getSharedArrayBufferId") \ V(gid_string, "gid") \ V(handle_string, "handle") \ - V(heap_total_string, "heapTotal") \ - V(heap_used_string, "heapUsed") \ V(homedir_string, "homedir") \ V(hostmaster_string, "hostmaster") \ - V(id_string, "id") \ V(ignore_string, "ignore") \ V(immediate_callback_string, "_immediateCallback") \ V(infoaccess_string, "infoAccess") \ @@ -182,19 +170,15 @@ class ModuleWrap; V(issuer_string, "issuer") \ V(issuercert_string, "issuerCertificate") \ V(kill_signal_string, "killSignal") \ - V(length_string, "length") \ V(mac_string, "mac") \ V(main_string, "main") \ V(max_buffer_string, "maxBuffer") \ V(message_string, "message") \ V(minttl_string, "minttl") \ - V(model_string, "model") \ V(modulus_string, "modulus") \ V(name_string, "name") \ V(netmask_string, "netmask") \ - V(nice_string, "nice") \ V(nsname_string, "nsname") \ - V(nexttick_string, "nextTick") \ V(ocsp_request_string, "OCSPRequest") \ V(onchange_string, "onchange") \ V(onclienthello_string, "onclienthello") \ @@ -254,26 +238,20 @@ class ModuleWrap; V(service_string, "service") \ V(servername_string, "servername") \ V(session_id_string, "sessionId") \ - V(set_string, "set") \ V(shell_string, "shell") \ V(signal_string, "signal") \ V(size_string, "size") \ V(sni_context_err_string, "Invalid SNI context") \ V(sni_context_string, "sni_context") \ - V(speed_string, "speed") \ V(stack_string, "stack") \ V(status_string, "status") \ V(stdio_string, "stdio") \ - V(stream_string, "stream") \ V(subject_string, "subject") \ V(subjectaltname_string, "subjectaltname") \ - V(sys_string, "sys") \ V(syscall_string, "syscall") \ - V(tick_callback_string, "_tickCallback") \ V(tick_domain_cb_string, "_tickDomainCallback") \ V(ticketkeycallback_string, "onticketkeycallback") \ V(timeout_string, "timeout") \ - V(times_string, "times") \ V(tls_ticket_string, "tlsTicket") \ V(ttl_string, "ttl") \ V(type_string, "type") \ diff --git a/src/inspector_socket.cc b/src/inspector_socket.cc index 23b77f6aa56..386b4c3af07 100644 --- a/src/inspector_socket.cc +++ b/src/inspector_socket.cc @@ -328,7 +328,7 @@ class WsHandler : public ProtocolHandler { } while (processed > 0 && !data->empty()); } - void Write(const std::vector data) { + void Write(const std::vector data) override { std::vector output = encode_frame_hybi17(data); WriteRaw(output, WriteRequest::Cleanup); } @@ -446,7 +446,7 @@ class HttpHandler : public ProtocolHandler { } } - void CancelHandshake() { + void CancelHandshake() override { const char HANDSHAKE_FAILED_RESPONSE[] = "HTTP/1.0 400 Bad Request\r\n" "Content-Type: text/html; charset=UTF-8\r\n\r\n" diff --git a/src/inspector_socket_server.cc b/src/inspector_socket_server.cc index bf114251cb1..03e5c60e656 100644 --- a/src/inspector_socket_server.cc +++ b/src/inspector_socket_server.cc @@ -84,11 +84,6 @@ const char* MatchPathSegment(const char* path, const char* expected) { return nullptr; } -void OnBufferAlloc(uv_handle_t* handle, size_t len, uv_buf_t* buf) { - buf->base = new char[len]; - buf->len = len; -} - void PrintDebuggerReadyMessage(const std::string& host, int port, const std::vector& ids, @@ -235,7 +230,6 @@ class SocketSession { private: const int id_; InspectorSocket::Pointer ws_socket_; - InspectorSocketServer* server_; const int server_port_; std::string ws_key_; }; @@ -531,10 +525,7 @@ void InspectorSocketServer::Send(int session_id, const std::string& message) { // InspectorSession tracking SocketSession::SocketSession(InspectorSocketServer* server, int id, int server_port) - : id_(id), - server_(server), - server_port_(server_port) { } - + : id_(id), server_port_(server_port) {} void SocketSession::Send(const std::string& message) { ws_socket_->Write(message.data(), message.length()); diff --git a/src/js_stream.cc b/src/js_stream.cc index 3c969ef37d1..ae125e4964b 100644 --- a/src/js_stream.cc +++ b/src/js_stream.cc @@ -202,14 +202,14 @@ void JSStream::ReadBuffer(const FunctionCallbackInfo& args) { do { uv_buf_t buf; ssize_t avail = len; - wrap->OnAlloc(len, &buf); + wrap->EmitAlloc(len, &buf); if (static_cast(buf.len) < avail) avail = buf.len; memcpy(buf.base, data, avail); data += avail; len -= avail; - wrap->OnRead(avail, &buf); + wrap->EmitRead(avail, &buf); } while (len != 0); } @@ -218,7 +218,7 @@ void JSStream::EmitEOF(const FunctionCallbackInfo& args) { JSStream* wrap; ASSIGN_OR_RETURN_UNWRAP(&wrap, args.Holder()); - wrap->OnRead(UV_EOF, nullptr); + wrap->EmitRead(UV_EOF, nullptr); } diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 614c1067c6c..480be4dd15e 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -2849,6 +2849,24 @@ int SSLWrap::SetCACerts(SecureContext* sc) { } +Connection::Connection(Environment* env, + v8::Local wrap, + SecureContext* sc, + SSLWrap::Kind kind) + : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_SSLCONNECTION), + SSLWrap(env, sc, kind), + bio_read_(nullptr), + bio_write_(nullptr), + hello_offset_(0) { + MakeWeak(this); + Wrap(wrap, this); + hello_parser_.Start(SSLWrap::OnClientHello, + OnClientHelloParseEnd, + this); + enable_session_callbacks(); +} + + void Connection::OnClientHelloParseEnd(void* arg) { Connection* conn = static_cast(arg); diff --git a/src/node_crypto.h b/src/node_crypto.h index 636cbb99d4d..463be5f0727 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -432,19 +432,7 @@ class Connection : public AsyncWrap, public SSLWrap { Connection(Environment* env, v8::Local wrap, SecureContext* sc, - SSLWrap::Kind kind) - : AsyncWrap(env, wrap, AsyncWrap::PROVIDER_SSLCONNECTION), - SSLWrap(env, sc, kind), - bio_read_(nullptr), - bio_write_(nullptr), - hello_offset_(0) { - MakeWeak(this); - Wrap(wrap, this); - hello_parser_.Start(SSLWrap::OnClientHello, - OnClientHelloParseEnd, - this); - enable_session_callbacks(); - } + SSLWrap::Kind kind); private: static void SSLInfoCallback(const SSL *ssl, int where, int ret); diff --git a/src/node_crypto_clienthello-inl.h b/src/node_crypto_clienthello-inl.h index 019d7188de6..5aff1816b2f 100644 --- a/src/node_crypto_clienthello-inl.h +++ b/src/node_crypto_clienthello-inl.h @@ -30,6 +30,21 @@ namespace node { namespace crypto { +inline ClientHelloParser::ClientHelloParser() + : state_(kEnded), + onhello_cb_(nullptr), + onend_cb_(nullptr), + cb_arg_(nullptr), + session_size_(0), + session_id_(nullptr), + servername_size_(0), + servername_(nullptr), + ocsp_request_(0), + tls_ticket_size_(0), + tls_ticket_(nullptr) { + Reset(); +} + inline void ClientHelloParser::Reset() { frame_len_ = 0; body_offset_ = 0; diff --git a/src/node_crypto_clienthello.h b/src/node_crypto_clienthello.h index 70f082b2c2a..32c470677d0 100644 --- a/src/node_crypto_clienthello.h +++ b/src/node_crypto_clienthello.h @@ -33,19 +33,7 @@ namespace crypto { class ClientHelloParser { public: - ClientHelloParser() : state_(kEnded), - onhello_cb_(nullptr), - onend_cb_(nullptr), - cb_arg_(nullptr), - session_size_(0), - session_id_(nullptr), - servername_size_(0), - servername_(nullptr), - ocsp_request_(0), - tls_ticket_size_(0), - tls_ticket_(nullptr) { - Reset(); - } + inline ClientHelloParser(); class ClientHello { public: diff --git a/src/node_file.cc b/src/node_file.cc index f867fd75bb6..b5331fe8717 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -154,10 +154,6 @@ void NewFSReqWrap(const FunctionCallbackInfo& args) { } -inline bool IsInt64(double x) { - return x == static_cast(static_cast(x)); -} - void After(uv_fs_t *req) { FSReqWrap* req_wrap = static_cast(req->data); CHECK_EQ(req_wrap->req(), req); diff --git a/src/node_url.cc b/src/node_url.cc index 578c73c7f03..853a23d40d7 100644 --- a/src/node_url.cc +++ b/src/node_url.cc @@ -325,6 +325,74 @@ const uint8_t C0_CONTROL_ENCODE_SET[32] = { 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80 }; +const uint8_t FRAGMENT_ENCODE_SET[32] = { + // 00 01 02 03 04 05 06 07 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 08 09 0A 0B 0C 0D 0E 0F + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 10 11 12 13 14 15 16 17 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 18 19 1A 1B 1C 1D 1E 1F + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 20 21 22 23 24 25 26 27 + 0x01 | 0x00 | 0x04 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 28 29 2A 2B 2C 2D 2E 2F + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 30 31 32 33 34 35 36 37 + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 38 39 3A 3B 3C 3D 3E 3F + 0x00 | 0x00 | 0x00 | 0x00 | 0x10 | 0x00 | 0x40 | 0x00, + // 40 41 42 43 44 45 46 47 + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 48 49 4A 4B 4C 4D 4E 4F + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 50 51 52 53 54 55 56 57 + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 58 59 5A 5B 5C 5D 5E 5F + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 60 61 62 63 64 65 66 67 + 0x01 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 68 69 6A 6B 6C 6D 6E 6F + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 70 71 72 73 74 75 76 77 + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00, + // 78 79 7A 7B 7C 7D 7E 7F + 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x00 | 0x80, + // 80 81 82 83 84 85 86 87 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 88 89 8A 8B 8C 8D 8E 8F + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 90 91 92 93 94 95 96 97 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // 98 99 9A 9B 9C 9D 9E 9F + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // A0 A1 A2 A3 A4 A5 A6 A7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // A8 A9 AA AB AC AD AE AF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // B0 B1 B2 B3 B4 B5 B6 B7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // B8 B9 BA BB BC BD BE BF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // C0 C1 C2 C3 C4 C5 C6 C7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // C8 C9 CA CB CC CD CE CF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // D0 D1 D2 D3 D4 D5 D6 D7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // D8 D9 DA DB DC DD DE DF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // E0 E1 E2 E3 E4 E5 E6 E7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // E8 E9 EA EB EC ED EE EF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // F0 F1 F2 F3 F4 F5 F6 F7 + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, + // F8 F9 FA FB FC FD FE FF + 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80 +}; + + const uint8_t PATH_ENCODE_SET[32] = { // 00 01 02 03 04 05 06 07 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80, @@ -1889,7 +1957,7 @@ void URL::Parse(const char* input, case 0: break; default: - AppendOrEscape(&buffer, ch, C0_CONTROL_ENCODE_SET); + AppendOrEscape(&buffer, ch, FRAGMENT_ENCODE_SET); } break; default: diff --git a/src/stream_base.cc b/src/stream_base.cc index 46d2ff5faf0..bb25fc1cff0 100644 --- a/src/stream_base.cc +++ b/src/stream_base.cc @@ -402,7 +402,7 @@ void StreamBase::AfterWrite(WriteWrap* req_wrap, int status) { // Unref handle property Local req_wrap_obj = req_wrap->object(); req_wrap_obj->Delete(env->context(), env->handle_string()).FromJust(); - OnAfterWrite(req_wrap, status); + EmitAfterWrite(req_wrap, status); Local argv[] = { Integer::New(env->isolate(), status), diff --git a/src/stream_base.h b/src/stream_base.h index 5bf5f013947..345554fa05c 100644 --- a/src/stream_base.h +++ b/src/stream_base.h @@ -166,19 +166,19 @@ class StreamResource { virtual void ClearError(); // Events - inline void OnAfterWrite(WriteWrap* w, int status) { + inline void EmitAfterWrite(WriteWrap* w, int status) { if (!after_write_cb_.is_empty()) after_write_cb_.fn(w, status, after_write_cb_.ctx); } - inline void OnAlloc(size_t size, uv_buf_t* buf) { + inline void EmitAlloc(size_t size, uv_buf_t* buf) { if (!alloc_cb_.is_empty()) alloc_cb_.fn(size, buf, alloc_cb_.ctx); } - inline void OnRead(ssize_t nread, - const uv_buf_t* buf, - uv_handle_type pending = UV_UNKNOWN_HANDLE) { + inline void EmitRead(ssize_t nread, + const uv_buf_t* buf, + uv_handle_type pending = UV_UNKNOWN_HANDLE) { if (nread > 0) bytes_read_ += static_cast(nread); if (!read_cb_.is_empty()) diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index 3cce3b151cf..f6cfba84c28 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -165,7 +165,7 @@ void LibuvStreamWrap::OnAlloc(uv_handle_t* handle, CHECK_EQ(wrap->stream(), reinterpret_cast(handle)); - return static_cast(wrap)->OnAlloc(suggested_size, buf); + return wrap->EmitAlloc(suggested_size, buf); } @@ -263,7 +263,7 @@ void LibuvStreamWrap::OnRead(uv_stream_t* handle, } } - static_cast(wrap)->OnRead(nread, buf, type); + wrap->EmitRead(nread, buf, type); } diff --git a/src/tls_wrap.cc b/src/tls_wrap.cc index 616771b389c..c661a0ac32a 100644 --- a/src/tls_wrap.cc +++ b/src/tls_wrap.cc @@ -230,11 +230,11 @@ void TLSWrap::Receive(const FunctionCallbackInfo& args) { // Copy given buffer entirely or partiall if handle becomes closed while (len > 0 && wrap->IsAlive() && !wrap->IsClosing()) { - wrap->stream_->OnAlloc(len, &buf); + wrap->stream_->EmitAlloc(len, &buf); size_t copy = buf.len > len ? len : buf.len; memcpy(buf.base, data, copy); buf.len = copy; - wrap->stream_->OnRead(buf.len, &buf); + wrap->stream_->EmitRead(buf.len, &buf); data += copy; len -= copy; @@ -443,11 +443,11 @@ void TLSWrap::ClearOut() { int avail = read; uv_buf_t buf; - OnAlloc(avail, &buf); + EmitAlloc(avail, &buf); if (static_cast(buf.len) < avail) avail = buf.len; memcpy(buf.base, current, avail); - OnRead(avail, &buf); + EmitRead(avail, &buf); // Caveat emptor: OnRead() calls into JS land which can result in // the SSL context object being destroyed. We have to carefully @@ -463,7 +463,7 @@ void TLSWrap::ClearOut() { int flags = SSL_get_shutdown(ssl_); if (!eof_ && flags & SSL_RECEIVED_SHUTDOWN) { eof_ = true; - OnRead(UV_EOF, nullptr); + EmitRead(UV_EOF, nullptr); } // We need to check whether an error occurred or the connection was @@ -739,13 +739,13 @@ void TLSWrap::DoRead(ssize_t nread, eof_ = true; } - OnRead(nread, nullptr); + EmitRead(nread, nullptr); return; } // Only client connections can receive data if (ssl_ == nullptr) { - OnRead(UV_EPROTO, nullptr); + EmitRead(UV_EPROTO, nullptr); return; } diff --git a/test/addons-napi/test_buffer/test.js b/test/addons-napi/test_buffer/test.js index 45b86600cab..fd8902cd203 100644 --- a/test/addons-napi/test_buffer/test.js +++ b/test/addons-napi/test_buffer/test.js @@ -12,15 +12,13 @@ assert.strictEqual(binding.newExternalBuffer().toString(), binding.theText); if (process.jsEngine !== 'chakracore') { console.log('gc1'); global.gc(); - assert.strictEqual(binding.getDeleterCallCount(), 1, - 'deleter was not called'); + assert.strictEqual(binding.getDeleterCallCount(), 1); } assert.strictEqual(binding.copyBuffer().toString(), binding.theText); let buffer = binding.staticBuffer(); -assert.strictEqual(binding.bufferHasInstance(buffer), true, - 'buffer type checking fails'); +assert.strictEqual(binding.bufferHasInstance(buffer), true); assert.strictEqual(binding.bufferInfo(buffer), true); buffer = null; @@ -28,6 +26,5 @@ buffer = null; if (process.jsEngine !== 'chakracore') { global.gc(); console.log('gc2'); - assert.strictEqual(binding.getDeleterCallCount(), 2, - 'deleter was not called'); + assert.strictEqual(binding.getDeleterCallCount(), 2); } diff --git a/test/fixtures/url-setter-tests.js b/test/fixtures/url-setter-tests.js index 6f769eaec75..289812cb7e3 100644 --- a/test/fixtures/url-setter-tests.js +++ b/test/fixtures/url-setter-tests.js @@ -2,7 +2,7 @@ /* The following tests are copied from WPT. Modifications to them should be upstreamed first. Refs: - https://github.com/w3c/web-platform-tests/blob/b30abaecf4/url/setters_tests.json + https://github.com/w3c/web-platform-tests/blob/ed4bb727ed/url/setters_tests.json License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html */ module.exports = @@ -1793,13 +1793,53 @@ module.exports = "hash": "" } }, + { + "href": "http://example.net", + "new_value": "#foo bar", + "expected": { + "href": "http://example.net/#foo%20bar", + "hash": "#foo%20bar" + } + }, + { + "href": "http://example.net", + "new_value": "#foo\"bar", + "expected": { + "href": "http://example.net/#foo%22bar", + "hash": "#foo%22bar" + } + }, + { + "href": "http://example.net", + "new_value": "#foobar", + "expected": { + "href": "http://example.net/#foo%3Ebar", + "hash": "#foo%3Ebar" + } + }, + { + "href": "http://example.net", + "new_value": "#foo`bar", + "expected": { + "href": "http://example.net/#foo%60bar", + "hash": "#foo%60bar" + } + }, { "comment": "Simple percent-encoding; nuls, tabs, and newlines are removed", "href": "a:/", "new_value": "\u0000\u0001\t\n\r\u001f !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~\u007f\u0080\u0081Éé", "expected": { - "href": "a:/#%01%1F !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9", - "hash": "#%01%1F !\"#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~%7F%C2%80%C2%81%C3%89%C3%A9" + "href": "a:/#%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9", + "hash": "#%01%1F%20!%22#$%&'()*+,-./09:;%3C=%3E?@AZ[\\]^_%60az{|}~%7F%C2%80%C2%81%C3%89%C3%A9" } }, { diff --git a/test/fixtures/url-tests.js b/test/fixtures/url-tests.js index 48f77fe0774..745adb8d8aa 100644 --- a/test/fixtures/url-tests.js +++ b/test/fixtures/url-tests.js @@ -2,7 +2,7 @@ /* The following tests are copied from WPT. Modifications to them should be upstreamed first. Refs: - https://github.com/w3c/web-platform-tests/blob/11757f1/url/urltestdata.json + https://github.com/w3c/web-platform-tests/blob/ed4bb727ed/url/urltestdata.json License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html */ module.exports = @@ -161,7 +161,7 @@ module.exports = { "input": "http://f:21/ b ? d # e ", "base": "http://example.org/foo/bar", - "href": "http://f:21/%20b%20?%20d%20# e", + "href": "http://f:21/%20b%20?%20d%20#%20e", "origin": "http://f:21", "protocol": "http:", "username": "", @@ -171,12 +171,12 @@ module.exports = "port": "21", "pathname": "/%20b%20", "search": "?%20d%20", - "hash": "# e" + "hash": "#%20e" }, { "input": "lolscheme:x x#x x", "base": "about:blank", - "href": "lolscheme:x x#x x", + "href": "lolscheme:x x#x%20x", "protocol": "lolscheme:", "username": "", "password": "", @@ -185,7 +185,7 @@ module.exports = "port": "", "pathname": "x x", "search": "", - "hash": "#x x" + "hash": "#x%20x" }, { "input": "http://f:/c", @@ -2268,7 +2268,7 @@ module.exports = { "input": "http://www.google.com/foo?bar=baz# »", "base": "about:blank", - "href": "http://www.google.com/foo?bar=baz# %C2%BB", + "href": "http://www.google.com/foo?bar=baz#%20%C2%BB", "origin": "http://www.google.com", "protocol": "http:", "username": "", @@ -2278,12 +2278,12 @@ module.exports = "port": "", "pathname": "/foo", "search": "?bar=baz", - "hash": "# %C2%BB" + "hash": "#%20%C2%BB" }, { "input": "data:test# »", "base": "about:blank", - "href": "data:test# %C2%BB", + "href": "data:test#%20%C2%BB", "origin": "null", "protocol": "data:", "username": "", @@ -2293,7 +2293,7 @@ module.exports = "port": "", "pathname": "test", "search": "", - "hash": "# %C2%BB" + "hash": "#%20%C2%BB" }, { "input": "http://www.google.com", @@ -4795,6 +4795,70 @@ module.exports = "searchParams": "qux=", "hash": "#foo%08bar" }, + { + "input": "http://foo.bar/baz?qux#foo\"bar", + "base": "about:blank", + "href": "http://foo.bar/baz?qux#foo%22bar", + "origin": "http://foo.bar", + "protocol": "http:", + "username": "", + "password": "", + "host": "foo.bar", + "hostname": "foo.bar", + "port": "", + "pathname": "/baz", + "search": "?qux", + "searchParams": "qux=", + "hash": "#foo%22bar" + }, + { + "input": "http://foo.bar/baz?qux#foobar", + "base": "about:blank", + "href": "http://foo.bar/baz?qux#foo%3Ebar", + "origin": "http://foo.bar", + "protocol": "http:", + "username": "", + "password": "", + "host": "foo.bar", + "hostname": "foo.bar", + "port": "", + "pathname": "/baz", + "search": "?qux", + "searchParams": "qux=", + "hash": "#foo%3Ebar" + }, + { + "input": "http://foo.bar/baz?qux#foo`bar", + "base": "about:blank", + "href": "http://foo.bar/baz?qux#foo%60bar", + "origin": "http://foo.bar", + "protocol": "http:", + "username": "", + "password": "", + "host": "foo.bar", + "hostname": "foo.bar", + "port": "", + "pathname": "/baz", + "search": "?qux", + "searchParams": "qux=", + "hash": "#foo%60bar" + }, "# IPv4 parsing (via https://github.com/nodejs/node/pull/10317)", { "input": "http://192.168.257", diff --git a/test/message/error_exit.v8.out b/test/message/error_exit.v8.out index 833bc745874..0fc93306204 100644 --- a/test/message/error_exit.v8.out +++ b/test/message/error_exit.v8.out @@ -1,6 +1,6 @@ Exiting with code=1 assert.js:* - throw new errors.AssertionError({ + throw new errors.AssertionError(obj); ^ AssertionError [ERR_ASSERTION]: 1 strictEqual 2 diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 8996cde1d65..41cd4f376e6 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -469,10 +469,15 @@ assert.throws(() => { assert.ifError(new Error('test error')); }, assert.doesNotThrow(() => { assert.ifError(null); }); assert.doesNotThrow(() => { assert.ifError(); }); -assert.throws(() => { - assert.doesNotThrow(makeBlock(thrower, Error), 'user message'); -}, /Got unwanted exception: user message/, - 'a.doesNotThrow ignores user message'); +common.expectsError( + () => assert.doesNotThrow(makeBlock(thrower, Error), 'user message'), + { + type: a.AssertionError, + code: 'ERR_ASSERTION', + operator: 'doesNotThrow', + message: 'Got unwanted exception: user message\n[object Object]' + } +); { let threw = false; @@ -559,7 +564,8 @@ a.throws(makeBlock(thrower, TypeError), (err) => { () => { a.throws((noop)); }, common.expectsError({ code: 'ERR_ASSERTION', - message: /^Missing expected exception\.$/ + message: /^Missing expected exception\.$/, + operator: 'throws' })); assert.throws( @@ -777,3 +783,12 @@ common.expectsError( /* eslint-enable no-restricted-properties */ assert(7); } + +common.expectsError( + () => assert.ok(null), + { + code: 'ERR_ASSERTION', + type: assert.AssertionError, + message: 'null == true' + } +); diff --git a/test/parallel/test-benchmark-misc.js b/test/parallel/test-benchmark-misc.js index df3bae4706a..52f568f9742 100644 --- a/test/parallel/test-benchmark-misc.js +++ b/test/parallel/test-benchmark-misc.js @@ -11,4 +11,4 @@ runBenchmark('misc', [ 'n=1', 'type=extend', 'val=magyarország.icom.museum' -]); +], { NODEJS_BENCHMARK_ZERO_ALLOWED: 1 }); diff --git a/test/parallel/test-http-connect.js b/test/parallel/test-http-connect.js index 4b251832ff1..b019c61573e 100644 --- a/test/parallel/test-http-connect.js +++ b/test/parallel/test-http-connect.js @@ -42,9 +42,9 @@ server.on('connect', common.mustCall((req, socket, firstBodyChunk) => { })); })); -server.listen(0, common.mustCall(function() { +server.listen(0, common.mustCall(() => { const req = http.request({ - port: this.address().port, + port: server.address().port, method: 'CONNECT', path: 'google.com:443' }, common.mustNotCall()); diff --git a/test/parallel/test-http-date-header.js b/test/parallel/test-http-date-header.js index 386501c9f47..b389e336647 100644 --- a/test/parallel/test-http-date-header.js +++ b/test/parallel/test-http-date-header.js @@ -26,7 +26,7 @@ const http = require('http'); const testResBody = 'other stuff!\n'; -const server = http.createServer(function(req, res) { +const server = http.createServer((req, res) => { assert.ok(!('date' in req.headers), 'Request headers contained a Date.'); res.writeHead(200, { @@ -37,16 +37,16 @@ const server = http.createServer(function(req, res) { server.listen(0); -server.addListener('listening', function() { +server.addListener('listening', () => { const options = { - port: this.address().port, + port: server.address().port, path: '/', method: 'GET' }; - const req = http.request(options, function(res) { + const req = http.request(options, (res) => { assert.ok('date' in res.headers, 'Response headers didn\'t contain a Date.'); - res.addListener('end', function() { + res.addListener('end', () => { server.close(); process.exit(); }); diff --git a/test/parallel/test-http-default-encoding.js b/test/parallel/test-http-default-encoding.js index 9fb0cca6563..36d3f0a6524 100644 --- a/test/parallel/test-http-default-encoding.js +++ b/test/parallel/test-http-default-encoding.js @@ -27,11 +27,11 @@ const http = require('http'); const expected = 'This is a unicode text: سلام'; let result = ''; -const server = http.Server(function(req, res) { +const server = http.Server((req, res) => { req.setEncoding('utf8'); - req.on('data', function(chunk) { + req.on('data', (chunk) => { result += chunk; - }).on('end', function() { + }).on('end', () => { server.close(); res.writeHead(200); res.end('hello world\n'); @@ -44,15 +44,15 @@ server.listen(0, function() { port: this.address().port, path: '/', method: 'POST' - }, function(res) { + }, (res) => { console.log(res.statusCode); res.resume(); - }).on('error', function(e) { + }).on('error', (e) => { console.log(e.message); process.exit(1); }).end(expected); }); -process.on('exit', function() { +process.on('exit', () => { assert.strictEqual(expected, result); }); diff --git a/test/parallel/test-http-hightwatermark.js b/test/parallel/test-http-hightwatermark.js new file mode 100644 index 00000000000..b2432227a9d --- /dev/null +++ b/test/parallel/test-http-hightwatermark.js @@ -0,0 +1,52 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); +const http = require('http'); + +// These test cases to check socketOnDrain where needPause becomes false. +// When send large response enough to exceed highWaterMark, it expect the socket +// to be paused and res.write would be failed. +// And it should be resumed when outgoingData falls below highWaterMark. + +let requestReceived = 0; + +const server = http.createServer(function(req, res) { + const id = ++requestReceived; + const enoughToDrain = req.connection.writableHighWaterMark; + const body = 'x'.repeat(enoughToDrain); + + if (id === 1) { + // Case of needParse = false + req.connection.once('pause', common.mustCall(() => { + assert(req.connection._paused, '_paused must be true because it exceeds' + + 'highWaterMark by second request'); + })); + } else { + // Case of needParse = true + const resume = req.connection.parser.resume.bind(req.connection.parser); + req.connection.parser.resume = common.mustCall((...args) => { + const paused = req.connection._paused; + assert(!paused, '_paused must be false because it become false by ' + + 'socketOnDrain when outgoingData falls below ' + + 'highWaterMark'); + return resume(...args); + }); + } + assert(!res.write(body), 'res.write must return false because it will ' + + 'exceed highWaterMark on this call'); + res.end(); +}).on('listening', () => { + const c = net.createConnection(server.address().port, () => { + c.write('GET / HTTP/1.1\r\n\r\n'); + c.write('GET / HTTP/1.1\r\n\r\n'); + c.end(); + }); + + c.on('data', () => {}); + c.on('end', () => { + server.close(); + }); +}); + +server.listen(0); diff --git a/test/parallel/test-stream-push-order.js b/test/parallel/test-stream-push-order.js index be2db9f44a6..ce4f336b025 100644 --- a/test/parallel/test-stream-push-order.js +++ b/test/parallel/test-stream-push-order.js @@ -47,6 +47,6 @@ s.read(0); // ACTUALLY [1, 3, 5, 6, 4, 2] process.on('exit', function() { - assert.deepStrictEqual(s._readableState.buffer.join(','), '1,2,3,4,5,6'); + assert.deepStrictEqual(s.readableBuffer.join(','), '1,2,3,4,5,6'); console.log('ok'); }); diff --git a/test/parallel/test-stream-readable-reading-readingMore.js b/test/parallel/test-stream-readable-reading-readingMore.js index bee3a1c82a8..e31d2dd921c 100644 --- a/test/parallel/test-stream-readable-reading-readingMore.js +++ b/test/parallel/test-stream-readable-reading-readingMore.js @@ -15,7 +15,7 @@ assert.strictEqual(state.readingMore, false); readable.on('data', common.mustCall((data) => { // while in a flowing state, should try to read more. - if (state.flowing) + if (readable.readableFlowing) assert.strictEqual(state.readingMore, true); // reading as long as we've not ended diff --git a/test/parallel/test-stream2-transform.js b/test/parallel/test-stream2-transform.js index 819b088e275..16a0523994c 100644 --- a/test/parallel/test-stream2-transform.js +++ b/test/parallel/test-stream2-transform.js @@ -46,7 +46,7 @@ const Transform = require('_stream_transform'); assert.strictEqual(tx._readableState.length, 10); assert.strictEqual(transformed, 10); assert.strictEqual(tx._transformState.writechunk.length, 5); - assert.deepStrictEqual(tx._writableState.getBuffer().map(function(c) { + assert.deepStrictEqual(tx.writableBuffer.map(function(c) { return c.chunk.length; }), [6, 7, 8, 9, 10]); } diff --git a/test/parallel/test-stream2-unpipe-leak.js b/test/parallel/test-stream2-unpipe-leak.js index cc331d58217..5c19be061fd 100644 --- a/test/parallel/test-stream2-unpipe-leak.js +++ b/test/parallel/test-stream2-unpipe-leak.js @@ -66,7 +66,7 @@ assert.strictEqual(dest.listeners('finish').length, 0); console.error(src._readableState); process.on('exit', function() { - src._readableState.buffer.length = 0; + src.readableBuffer.length = 0; console.error(src._readableState); assert(src._readableState.length >= src.readableHighWaterMark); console.log('ok'); diff --git a/test/parallel/test-stream3-pause-then-read.js b/test/parallel/test-stream3-pause-then-read.js index d75fe697081..f7bfadaf9d1 100644 --- a/test/parallel/test-stream3-pause-then-read.js +++ b/test/parallel/test-stream3-pause-then-read.js @@ -68,7 +68,7 @@ function readn(n, then) { r.once('readable', read); else { assert.strictEqual(c.length, n); - assert(!r._readableState.flowing); + assert(!r.readableFlowing); then(); } })(); diff --git a/test/parallel/test-util-promisify.js b/test/parallel/test-util-promisify.js index 656d6d60aa8..235d5c40db7 100644 --- a/test/parallel/test-util-promisify.js +++ b/test/parallel/test-util-promisify.js @@ -184,3 +184,13 @@ const stat = promisify(fs.stat); }) ]); } + +[undefined, null, true, 0, 'str', {}, [], Symbol()].forEach((input) => { + common.expectsError( + () => promisify(input), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "original" argument must be of type Function' + }); +}); diff --git a/test/sequential/test-util-debug.js b/test/sequential/test-util-debug.js index 6e20ca49d81..c79f99ff283 100644 --- a/test/sequential/test-util-debug.js +++ b/test/sequential/test-util-debug.js @@ -43,6 +43,15 @@ function parent() { test('f$oo', true, 'f$oo'); test('f$oo', false, 'f.oo'); test('no-bar-at-all', false, 'bar'); + + test('test-abc', true, 'test-abc'); + test('test-a', false, 'test-abc'); + test('test-*', true, 'test-abc'); + test('test-*c', true, 'test-abc'); + test('test-*abc', true, 'test-abc'); + test('abc-test', true, 'abc-test'); + test('a*-test', true, 'abc-test'); + test('*-test', true, 'abc-test'); } function test(environ, shouldWrite, section) { diff --git a/tools/eslint-rules/lowercase-name-for-primitive.js b/tools/eslint-rules/lowercase-name-for-primitive.js index bdf10328f3f..cb603b62c0c 100644 --- a/tools/eslint-rules/lowercase-name-for-primitive.js +++ b/tools/eslint-rules/lowercase-name-for-primitive.js @@ -9,41 +9,38 @@ // Rule Definition //------------------------------------------------------------------------------ +const astSelector = 'NewExpression[callee.property.name="TypeError"]' + + '[arguments.0.value="ERR_INVALID_ARG_TYPE"]'; + const primitives = [ 'number', 'string', 'boolean', 'null', 'undefined' ]; module.exports = function(context) { - return { - NewExpression(node) { - if ( - node.callee.property && - node.callee.property.name === 'TypeError' && - node.arguments[0].value === 'ERR_INVALID_ARG_TYPE' - ) { - checkNamesArgument(node.arguments[2]); - } + function checkNamesArgument(node) { + const names = node.arguments[2]; - function checkNamesArgument(names) { - switch (names.type) { - case 'Literal': - checkName(names.value); - break; - case 'ArrayExpression': - names.elements.forEach((name) => { - checkName(name.value); - }); - break; - } - } + switch (names.type) { + case 'Literal': + checkName(node, names.value); + break; + case 'ArrayExpression': + names.elements.forEach((name) => { + checkName(node, name.value); + }); + break; + } + } - function checkName(name) { - const lowercaseName = name.toLowerCase(); - if (primitives.includes(lowercaseName) && !primitives.includes(name)) { - const msg = `primitive should use lowercase: ${name}`; - context.report(node, msg); - } - } + function checkName(node, name) { + const lowercaseName = name.toLowerCase(); + if (primitives.includes(lowercaseName) && !primitives.includes(name)) { + const msg = `primitive should use lowercase: ${name}`; + context.report(node, msg); } + } + + return { + [astSelector]: (node) => checkNamesArgument(node) }; }; diff --git a/vcbuild.bat b/vcbuild.bat index 49a2c00ee92..d7d9b461adb 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -107,7 +107,7 @@ if /i "%1"=="upload" set upload=1&goto arg-ok if /i "%1"=="small-icu" set i18n_arg=%1&goto arg-ok if /i "%1"=="full-icu" set i18n_arg=%1&goto arg-ok if /i "%1"=="intl-none" set i18n_arg=%1&goto arg-ok -if /i "%1"=="without-intl" set i18n_arg=intl-none&goto arg-ok +if /i "%1"=="without-intl" set i18n_arg=none&goto arg-ok if /i "%1"=="download-all" set download_arg="--download=all"&goto arg-ok if /i "%1"=="ignore-flaky" set test_args=%test_args% --flaky-tests=dontcare&goto arg-ok if /i "%1"=="enable-vtune" set enable_vtune_arg=1&goto arg-ok