From 66081d1ddbf05d5acc1def2de9707ce2b6973059 Mon Sep 17 00:00:00 2001 From: DavidCai Date: Sat, 11 Feb 2017 21:36:34 +0800 Subject: [PATCH 001/164] test: increase coverage of buffer PR-URL: https://github.com/nodejs/node/pull/11312 Backport-of: https://github.com/nodejs/node/pull/11122 Reviewed-By: James M Snell Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Italo A. Casas --- test/parallel/test-buffer-compare-offset.js | 2 ++ test/parallel/test-buffer-write-noassert.js | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/test/parallel/test-buffer-compare-offset.js b/test/parallel/test-buffer-compare-offset.js index deed1a41cb664c..037e82e055cb91 100644 --- a/test/parallel/test-buffer-compare-offset.js +++ b/test/parallel/test-buffer-compare-offset.js @@ -11,6 +11,7 @@ assert.strictEqual(-1, a.compare(b)); // Equivalent to a.compare(b). assert.strictEqual(-1, a.compare(b, 0)); assert.strictEqual(-1, a.compare(b, '0')); +assert.strictEqual(-1, a.compare(b, undefined)); // Equivalent to a.compare(b). assert.strictEqual(-1, a.compare(b, 0, undefined, 0)); @@ -63,5 +64,6 @@ assert.throws(() => a.compare(b, 0, 1, 0, 100), oor); assert.throws(() => a.compare(b, -1), oor); assert.throws(() => a.compare(b, 0, '0xff'), oor); assert.throws(() => a.compare(b, 0, Infinity), oor); +assert.throws(() => a.compare(b, 0, 1, -1), oor); assert.throws(() => a.compare(b, -Infinity, Infinity), oor); assert.throws(() => a.compare(), /Argument must be a Buffer/); diff --git a/test/parallel/test-buffer-write-noassert.js b/test/parallel/test-buffer-write-noassert.js index c0054733b85bb2..7b2f8588c697eb 100644 --- a/test/parallel/test-buffer-write-noassert.js +++ b/test/parallel/test-buffer-write-noassert.js @@ -20,6 +20,17 @@ function write(funx, args, result, res) { ); } + { + const error = /Int/.test(funx) ? + /^TypeError: "buffer" argument must be a Buffer instance$/ : + /^TypeError: argument should be a Buffer$/; + + assert.throws( + () => Buffer.alloc(9)[funx].apply(new Uint32Array(1), args), + error + ); + } + { const buf2 = Buffer.alloc(9); assert.strictEqual(buf2[funx](...args, true), result); From d4000e73edc0172150a26a42f982a7570aef9630 Mon Sep 17 00:00:00 2001 From: Jaideep Bajwa Date: Thu, 9 Feb 2017 10:59:50 -0500 Subject: [PATCH 002/164] deps: cherry-pick 7c982e7 from V8 upstream Original commit message: PPC/s390: [Turbofan]: Use new MachineTypes in access-builder. Port 56429fc14671a10749190a4dfeacd38b7270f6f5 Original Commit Message: Introduced MachineType::TaggedSigned() and TaggedPointer(). The idea is to quit using the representational dimension of Type, and instead encode this information in the MachineRepresentation (itself lightly wrapped in MachineType, along with MachineSemantic). There are three parts to the whole change: 1) Places that set the machine representation - constant nodes, loads nad stores, global object and native context specialization. 2) Places that propagate type/representation - this is representation inference (aka simplified lowering). At the end of this process we expect to have a MachineRepresentation for every node. An interesting part of this is phi merging. 3) Places that examine representation - WriteBarrier elimination does this. Currently it's looking at the Type representation dimension, but as a part of this change (or in a soon-to-follow change) it can simply examine the MachineRepresentation. R=mvstanton@chromium.org, joransiu@ca.ibm.com, jyan@ca.ibm.com, michael_dawson@ca.ibm.com BUG= LOG=N Review-Url: https://codereview.chromium.org/2662223003 Cr-Commit-Position: refs/heads/master@{#42817} PR-URL: https://github.com/nodejs/node/pull/11263 Backport-of: https://github.com/v8/v8/commit/7c982e7ecf7669c05af199bf827dd80110f37cad Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell Reviewed-By: Ali Ijaz Sheikh --- deps/v8/include/v8-version.h | 2 +- deps/v8/src/compiler/ppc/instruction-selector-ppc.cc | 2 +- deps/v8/src/compiler/s390/instruction-selector-s390.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index b216cf04c30a00..f2c738770a43b4 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 5 #define V8_MINOR_VERSION 5 #define V8_BUILD_NUMBER 372 -#define V8_PATCH_LEVEL 40 +#define V8_PATCH_LEVEL 41 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/compiler/ppc/instruction-selector-ppc.cc b/deps/v8/src/compiler/ppc/instruction-selector-ppc.cc index a2eb7b8f22c9b8..1a3523745b9fae 100644 --- a/deps/v8/src/compiler/ppc/instruction-selector-ppc.cc +++ b/deps/v8/src/compiler/ppc/instruction-selector-ppc.cc @@ -245,7 +245,7 @@ void InstructionSelector::VisitStore(Node* node) { MachineRepresentation rep = store_rep.representation(); if (write_barrier_kind != kNoWriteBarrier) { - DCHECK_EQ(MachineRepresentation::kTagged, rep); + DCHECK(CanBeTaggedPointer(rep)); AddressingMode addressing_mode; InstructionOperand inputs[3]; size_t input_count = 0; diff --git a/deps/v8/src/compiler/s390/instruction-selector-s390.cc b/deps/v8/src/compiler/s390/instruction-selector-s390.cc index f1aa332a493ce4..c4cd3c92993ac4 100644 --- a/deps/v8/src/compiler/s390/instruction-selector-s390.cc +++ b/deps/v8/src/compiler/s390/instruction-selector-s390.cc @@ -343,7 +343,7 @@ void InstructionSelector::VisitStore(Node* node) { MachineRepresentation rep = store_rep.representation(); if (write_barrier_kind != kNoWriteBarrier) { - DCHECK_EQ(MachineRepresentation::kTagged, rep); + DCHECK(CanBeTaggedPointer(rep)); AddressingMode addressing_mode; InstructionOperand inputs[3]; size_t input_count = 0; From 58e2517fc0c32e54dac82710d05a1de9947ee256 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Fri, 10 Feb 2017 10:00:19 -0500 Subject: [PATCH 003/164] child_process: exit spawnSync with null on signal This commit sets the spawnSync() exit code to null when the child is killed via signal. This brings the behavior more in sync with spawn(). Fixes: https://github.com/nodejs/node/issues/11284 PR-URL: https://github.com/nodejs/node/pull/11288 Reviewed-By: Santiago Gimeno Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Evan Lucas --- src/spawn_sync.cc | 13 +++++++++---- .../test-child-process-spawnsync-kill-signal.js | 5 ++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/spawn_sync.cc b/src/spawn_sync.cc index 79f10a0ea2594d..3fcd61f22a4614 100644 --- a/src/spawn_sync.cc +++ b/src/spawn_sync.cc @@ -645,12 +645,17 @@ Local SyncProcessRunner::BuildResultObject() { Integer::New(env()->isolate(), GetError())); } - if (exit_status_ >= 0) - js_result->Set(env()->status_string(), - Number::New(env()->isolate(), static_cast(exit_status_))); - else + if (exit_status_ >= 0) { + if (term_signal_ > 0) { + js_result->Set(env()->status_string(), Null(env()->isolate())); + } else { + js_result->Set(env()->status_string(), + Number::New(env()->isolate(), static_cast(exit_status_))); + } + } else { // If exit_status_ < 0 the process was never started because of some error. js_result->Set(env()->status_string(), Null(env()->isolate())); + } if (term_signal_ > 0) js_result->Set(env()->signal_string(), diff --git a/test/parallel/test-child-process-spawnsync-kill-signal.js b/test/parallel/test-child-process-spawnsync-kill-signal.js index 8a3c362216eac5..b0d47e0aa68f5c 100644 --- a/test/parallel/test-child-process-spawnsync-kill-signal.js +++ b/test/parallel/test-child-process-spawnsync-kill-signal.js @@ -1,12 +1,11 @@ 'use strict'; -const common = require('../common'); +require('../common'); const assert = require('assert'); const cp = require('child_process'); if (process.argv[2] === 'child') { setInterval(() => {}, 1000); } else { - const exitCode = common.isWindows ? 1 : 0; const { SIGKILL } = process.binding('constants').os.signals; function spawn(killSignal) { @@ -14,7 +13,7 @@ if (process.argv[2] === 'child') { [__filename, 'child'], {killSignal, timeout: 100}); - assert.strictEqual(child.status, exitCode); + assert.strictEqual(child.status, null); assert.strictEqual(child.error.code, 'ETIMEDOUT'); return child; } From e7978f04a4a764ae5491b24b5dfdeb0cf9ebb073 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Fri, 10 Feb 2017 11:41:32 -0500 Subject: [PATCH 004/164] test: cover dgram socket close during cluster bind When a non-exclusive dgram socket is bound from a cluster worker, it attempts to get a handle from the cluster module. This commit adds coverage for the case where the socket is closed while querying the cluster module for a handle. PR-URL: https://github.com/nodejs/node/pull/11292 Reviewed-By: James M Snell --- .../test-dgram-cluster-close-during-bind.js | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 test/parallel/test-dgram-cluster-close-during-bind.js diff --git a/test/parallel/test-dgram-cluster-close-during-bind.js b/test/parallel/test-dgram-cluster-close-during-bind.js new file mode 100644 index 00000000000000..ec62693abfb645 --- /dev/null +++ b/test/parallel/test-dgram-cluster-close-during-bind.js @@ -0,0 +1,40 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const cluster = require('cluster'); +const dgram = require('dgram'); + +if (common.isWindows) { + common.skip('dgram clustering is currently not supported on windows.'); + return; +} + +if (cluster.isMaster) { + cluster.fork(); +} else { + // When the socket attempts to bind, it requests a handle from the cluster. + // Close the socket before returning the handle from the cluster. + const socket = dgram.createSocket('udp4'); + const _getServer = cluster._getServer; + + cluster._getServer = common.mustCall(function(self, options, callback) { + socket.close(common.mustCall(() => { + _getServer.call(this, self, options, common.mustCall((err, handle) => { + assert.strictEqual(err, 0); + + // When the socket determines that it was already closed, it will + // close the handle. Use handle.close() to terminate the test. + const close = handle.close; + + handle.close = common.mustCall(function() { + setImmediate(() => cluster.worker.disconnect()); + return close.call(this); + }); + + callback(err, handle); + })); + })); + }); + + socket.bind(common.mustNotCall('Socket should not bind.')); +} From 8a5c0fb0ffe7aab410d86697938bab0d27d3acf5 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sun, 12 Feb 2017 11:29:57 +0100 Subject: [PATCH 005/164] src: remove unused typedef Seems to have been overlooked in commit dd93c53 ("Make node::DLOpen use uv_dlopen") from 2011. PR-URL: https://github.com/nodejs/node/pull/11322 Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Nikolai Vavilov Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Timothy Gu --- src/node.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/node.cc b/src/node.cc index 0ee0133df41c75..65605ce07a7ae5 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2368,8 +2368,6 @@ struct node_module* get_linked_module(const char* name) { return mp; } -typedef void (UV_DYNAMIC* extInit)(Local exports); - // DLOpen is process.dlopen(module, filename). // Used to load 'module.node' dynamically shared objects. // From 6a45265e81acd4e9ef1ddc65be51077ff176cd70 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Wed, 1 Feb 2017 23:14:40 +0200 Subject: [PATCH 006/164] doc: update code examples in domain.md * var -> const * string concatenation -> template strings PR-URL: https://github.com/nodejs/node/pull/11110 Reviewed-By: Evan Lucas Reviewed-By: James M Snell --- doc/api/domain.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/api/domain.md b/doc/api/domain.md index cfea9ddeff81f8..1cc25e0cf8d8fb 100644 --- a/doc/api/domain.md +++ b/doc/api/domain.md @@ -47,13 +47,13 @@ For example, this is not a good idea: ```js // XXX WARNING! BAD IDEA! -var d = require('domain').create(); +const d = require('domain').create(); d.on('error', (er) => { // The error won't crash the process, but what it does is worse! // Though we've prevented abrupt process restarting, we are leaking // resources like crazy if this ever happens. // This is no better than process.on('uncaughtException')! - console.log('error, but oh well', er.message); + console.log(`error, but oh well ${er.message}`); }); d.run(() => { require('http').createServer((req, res) => { @@ -104,9 +104,9 @@ if (cluster.isMaster) { // worker processes to serve requests. How it works, caveats, etc. const server = require('http').createServer((req, res) => { - var d = domain.create(); + const d = domain.create(); d.on('error', (er) => { - console.error('error', er.stack); + console.error(`error ${er.stack}`); // Note: we're in dangerous territory! // By definition, something unexpected occurred, @@ -115,7 +115,7 @@ if (cluster.isMaster) { try { // make sure we close down within 30 seconds - var killtimer = setTimeout(() => { + const killtimer = setTimeout(() => { process.exit(1); }, 30000); // But don't keep the process open just for that! @@ -135,7 +135,7 @@ if (cluster.isMaster) { res.end('Oops, there was a problem!\n'); } catch (er2) { // oh well, not much we can do at this point. - console.error('Error sending 500!', er2.stack); + console.error(`Error sending 500! ${er2.stack}`); } }); @@ -156,7 +156,7 @@ if (cluster.isMaster) { // This part is not important. Just an example routing thing. // You'd put your fancy application logic here. function handleRequest(req, res) { - switch(req.url) { + switch (req.url) { case '/error': // We do some async stuff, and then... setTimeout(() => { @@ -239,7 +239,7 @@ serverDomain.run(() => { // req and res are also created in the scope of serverDomain // however, we'd prefer to have a separate domain for each request. // create it first thing, and add req and res to it. - var reqd = domain.create(); + const reqd = domain.create(); reqd.add(req); reqd.add(res); reqd.on('error', (er) => { @@ -247,8 +247,8 @@ serverDomain.run(() => { try { res.writeHead(500); res.end('Error occurred, sorry.'); - } catch (er) { - console.error('Error sending 500', er, req.url); + } catch (er2) { + console.error('Error sending 500', er2, req.url); } }); }).listen(1337); From 506a1cb03f68168bb43e71c91014ae7e8974637a Mon Sep 17 00:00:00 2001 From: John Barboza Date: Thu, 29 Dec 2016 02:22:35 -0500 Subject: [PATCH 007/164] timer,domain: maintain order of timer callbacks PR-URL: https://github.com/nodejs/node/pull/10522 Fixes: https://github.com/nodejs/node/issues/1271 Reviewed-By: Sam Roberts Reviewed-By: James M Snell Reviewed-By: Gibson Fahnestock Reviewed-By: Jeremiah Senkpiel --- lib/timers.js | 15 +++++++++++ .../test-domain-timers-uncaught-exception.js | 25 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 test/parallel/test-domain-timers-uncaught-exception.js diff --git a/lib/timers.js b/lib/timers.js index 3490baa0e5730a..0784f7f1e11247 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -156,12 +156,19 @@ function TimersList(msecs, unrefed) { this._timer = new TimerWrap(); this._unrefed = unrefed; this.msecs = msecs; + this.nextTick = false; } function listOnTimeout() { var list = this._list; var msecs = list.msecs; + if (list.nextTick) { + list.nextTick = false; + process.nextTick(listOnTimeoutNT, list); + return; + } + debug('timeout callback %d', msecs); var now = TimerWrap.now(); @@ -239,6 +246,14 @@ function tryOnTimeout(timer, list) { } finally { if (!threw) return; + // Postpone all later list events to next tick. We need to do this + // so that the events are called in the order they were created. + const lists = list._unrefed === true ? unrefedLists : refedLists; + for (var key in lists) { + if (key > list.msecs) { + lists[key].nextTick = true; + } + } // We need to continue processing after domain error handling // is complete, but not by using whatever domain was left over // when the timeout threw its exception. diff --git a/test/parallel/test-domain-timers-uncaught-exception.js b/test/parallel/test-domain-timers-uncaught-exception.js new file mode 100644 index 00000000000000..d564d853ac935f --- /dev/null +++ b/test/parallel/test-domain-timers-uncaught-exception.js @@ -0,0 +1,25 @@ +'use strict'; +const common = require('../common'); + +// This test ensures that the timer callbacks are called in the order in which +// they were created in the event of an unhandled exception in the domain. + +const domain = require('domain').create(); +const assert = require('assert'); + +let first = false; + +domain.run(function() { + setTimeout(() => { throw new Error('FAIL'); }, 1); + setTimeout(() => { first = true; }, 1); + setTimeout(() => { assert.strictEqual(first, true); }, 2); + + // Ensure that 2 ms have really passed + let i = 1e6; + while (i--); +}); + +domain.once('error', common.mustCall((err) => { + assert(err); + assert.strictEqual(err.message, 'FAIL'); +})); From 4d7c9427c18499939122bcc5841ce0914b263e26 Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Tue, 7 Feb 2017 00:08:45 +0200 Subject: [PATCH 008/164] doc: synchronize + update _toc.md and all.md PR-URL: https://github.com/nodejs/node/pull/11206 Reviewed-By: Jeremiah Senkpiel Reviewed-By: James M Snell --- doc/api/_toc.md | 1 + doc/api/all.md | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/api/_toc.md b/doc/api/_toc.md index 2527ad84e2e360..345e8e393145fd 100644 --- a/doc/api/_toc.md +++ b/doc/api/_toc.md @@ -35,6 +35,7 @@ * [String Decoder](string_decoder.html) * [Timers](timers.html) * [TLS/SSL](tls.html) +* [Tracing](tracing.html) * [TTY](tty.html) * [UDP/Datagram](dgram.html) * [URL](url.html) diff --git a/doc/api/all.md b/doc/api/all.md index 93c7a300a162e9..f65b24587511a1 100644 --- a/doc/api/all.md +++ b/doc/api/all.md @@ -1,15 +1,15 @@ @include documentation @include synopsis -@include addons @include assert @include buffer +@include addons @include child_process @include cluster @include cli @include console @include crypto @include debugger -@include dgram +@include deprecations @include dns @include domain @include errors @@ -31,7 +31,9 @@ @include string_decoder @include timers @include tls +@include tracing @include tty +@include dgram @include url @include util @include v8 From 348f2ef59fc8c8576ec9a5424932b294142487ae Mon Sep 17 00:00:00 2001 From: Akito Ito Date: Fri, 10 Feb 2017 13:05:45 +0900 Subject: [PATCH 009/164] test: improve crypto coverage * call Certificate function directly * check exception when sign option is undefined PR-URL: https://github.com/nodejs/node/pull/11280 Reviewed-By: Rich Trott Reviewed-By: Colin Ihrig Reviewed-By: Santiago Gimeno Reviewed-By: James M Snell --- test/parallel/test-crypto-certificate.js | 3 +++ test/parallel/test-crypto-sign-verify.js | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/test/parallel/test-crypto-certificate.js b/test/parallel/test-crypto-certificate.js index ebd83b019ba146..c051716556410d 100644 --- a/test/parallel/test-crypto-certificate.js +++ b/test/parallel/test-crypto-certificate.js @@ -37,3 +37,6 @@ assert.strictEqual(certificate.exportChallenge(spkacFail), ''); function stripLineEndings(obj) { return obj.replace(/\n/g, ''); } + +// direct call Certificate() should return instance +assert(crypto.Certificate() instanceof crypto.Certificate); diff --git a/test/parallel/test-crypto-sign-verify.js b/test/parallel/test-crypto-sign-verify.js index ae78cd9d8b3420..81b2c109b69b20 100644 --- a/test/parallel/test-crypto-sign-verify.js +++ b/test/parallel/test-crypto-sign-verify.js @@ -70,3 +70,10 @@ const keyPem = fs.readFileSync(common.fixturesDir + '/test_key.pem', 'ascii'); verified = verStream.verify(certPem, s3); assert.strictEqual(verified, true, 'sign and verify (stream)'); } + +// Test throws exception when key options is null +{ + assert.throws(() => { + crypto.createSign('RSA-SHA1').update('Test123').sign(null, 'base64'); + }, /^Error: No key provided to sign$/); +} From 7a3553f792bcf960a3b0c1352e0e23843f277d36 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 9 Feb 2017 23:41:14 +0800 Subject: [PATCH 010/164] benchmark: move url data to fixtures PR-URL: https://github.com/nodejs/node/pull/11264 Reviewed-By: James M Snell Reviewed-By: Joyee Cheung Reviewed-By: Brian White --- benchmark/fixtures/url-inputs.js | 30 +++++++++++++++++++ .../url/legacy-vs-whatwg-url-get-prop.js | 14 +-------- benchmark/url/legacy-vs-whatwg-url-parse.js | 14 +-------- ...legacy-vs-whatwg-url-searchparams-parse.js | 13 +------- ...cy-vs-whatwg-url-searchparams-serialize.js | 13 +------- .../url/legacy-vs-whatwg-url-serialize.js | 14 +-------- 6 files changed, 35 insertions(+), 63 deletions(-) create mode 100644 benchmark/fixtures/url-inputs.js diff --git a/benchmark/fixtures/url-inputs.js b/benchmark/fixtures/url-inputs.js new file mode 100644 index 00000000000000..7b1983f6faa590 --- /dev/null +++ b/benchmark/fixtures/url-inputs.js @@ -0,0 +1,30 @@ +'use strict'; + +exports.urls = { + long: 'http://nodejs.org:89/docs/latest/api/foo/bar/qua/13949281/0f28b/' + + '/5d49/b3020/url.html#test?payload1=true&payload2=false&test=1' + + '&benchmark=3&foo=38.38.011.293&bar=1234834910480&test=19299&3992&' + + 'key=f5c65e1e98fe07e648249ad41e1cfdb0', + short: 'https://nodejs.org/en/blog/', + idn: 'http://你好你好.在线', + auth: 'https://user:pass@example.com/path?search=1', + file: 'file:///foo/bar/test/node.js', + ws: 'ws://localhost:9229/f46db715-70df-43ad-a359-7f9949f39868', + javascript: 'javascript:alert("node is awesome");', + percent: 'https://%E4%BD%A0/foo', + dot: 'https://example.org/./a/../b/./c' +}; + +exports.searchParams = { + noencode: 'foo=bar&baz=quux&xyzzy=thud', + multicharsep: 'foo=bar&&&&&&&&&&baz=quux&&&&&&&&&&xyzzy=thud', + encodefake: 'foo=%©ar&baz=%A©uux&xyzzy=%©ud', + encodemany: '%66%6F%6F=bar&%62%61%7A=quux&xyzzy=%74h%75d', + encodelast: 'foo=bar&baz=quux&xyzzy=thu%64', + multivalue: 'foo=bar&foo=baz&foo=quux&quuy=quuz', + multivaluemany: 'foo=bar&foo=baz&foo=quux&quuy=quuz&foo=abc&foo=def&' + + 'foo=ghi&foo=jkl&foo=mno&foo=pqr&foo=stu&foo=vwxyz', + manypairs: 'a&b&c&d&e&f&g&h&i&j&k&l&m&n&o&p&q&r&s&t&u&v&w&x&y&z', + manyblankpairs: '&&&&&&&&&&&&&&&&&&&&&&&&', + altspaces: 'foo+bar=baz+quux&xyzzy+thud=quuy+quuz&abc=def+ghi' +}; diff --git a/benchmark/url/legacy-vs-whatwg-url-get-prop.js b/benchmark/url/legacy-vs-whatwg-url-get-prop.js index f703b75b16f6f7..ffc8b4995df3de 100644 --- a/benchmark/url/legacy-vs-whatwg-url-get-prop.js +++ b/benchmark/url/legacy-vs-whatwg-url-get-prop.js @@ -3,19 +3,7 @@ const common = require('../common.js'); const url = require('url'); const URL = url.URL; const assert = require('assert'); - -const inputs = { - long: 'http://nodejs.org:89/docs/latest/api/url.html#test?' + - 'payload1=true&payload2=false&test=1&benchmark=3&' + - 'foo=38.38.011.293&bar=1234834910480&test=19299&3992&' + - 'key=f5c65e1e98fe07e648249ad41e1cfdb0', - short: 'https://nodejs.org/en/blog/', - idn: 'http://你好你好', - auth: 'https://user:pass@example.com/path?search=1', - special: 'file:///foo/bar/test/node.js', - percent: 'https://%E4%BD%A0/foo', - dot: 'https://example.org/./a/../b/./c' -}; +const inputs = require('../fixtures/url-inputs.js').urls; const bench = common.createBenchmark(main, { type: Object.keys(inputs), diff --git a/benchmark/url/legacy-vs-whatwg-url-parse.js b/benchmark/url/legacy-vs-whatwg-url-parse.js index 64533e67e4a46a..ec386b7b85597d 100644 --- a/benchmark/url/legacy-vs-whatwg-url-parse.js +++ b/benchmark/url/legacy-vs-whatwg-url-parse.js @@ -3,19 +3,7 @@ const common = require('../common.js'); const url = require('url'); const URL = url.URL; const assert = require('assert'); - -const inputs = { - long: 'http://nodejs.org:89/docs/latest/api/url.html#test?' + - 'payload1=true&payload2=false&test=1&benchmark=3&' + - 'foo=38.38.011.293&bar=1234834910480&test=19299&3992&' + - 'key=f5c65e1e98fe07e648249ad41e1cfdb0', - short: 'https://nodejs.org/en/blog/', - idn: 'http://你好你好', - auth: 'https://user:pass@example.com/path?search=1', - special: 'file:///foo/bar/test/node.js', - percent: 'https://%E4%BD%A0/foo', - dot: 'https://example.org/./a/../b/./c' -}; +const inputs = require('../fixtures/url-inputs.js').urls; const bench = common.createBenchmark(main, { type: Object.keys(inputs), diff --git a/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js b/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js index e76f2dd837bb97..86714df6c196a7 100644 --- a/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js +++ b/benchmark/url/legacy-vs-whatwg-url-searchparams-parse.js @@ -2,18 +2,7 @@ const common = require('../common.js'); const { URLSearchParams } = require('url'); const querystring = require('querystring'); - -const inputs = { - noencode: 'foo=bar&baz=quux&xyzzy=thud', - encodemany: '%66%6F%6F=bar&%62%61%7A=quux&xyzzy=%74h%75d', - encodefake: 'foo=%©ar&baz=%A©uux&xyzzy=%©ud', - encodelast: 'foo=bar&baz=quux&xyzzy=thu%64', - multicharsep: 'foo=bar&&&&&&&&&&baz=quux&&&&&&&&&&xyzzy=thud', - multivalue: 'foo=bar&foo=baz&foo=quux&quuy=quuz', - multivaluemany: 'foo=bar&foo=baz&foo=quux&quuy=quuz&foo=abc&foo=def&' + - 'foo=ghi&foo=jkl&foo=mno&foo=pqr&foo=stu&foo=vwxyz', - manypairs: 'a&b&c&d&e&f&g&h&i&j&k&l&m&n&o&p&q&r&s&t&u&v&w&x&y&z' -}; +const inputs = require('../fixtures/url-inputs.js').searchParams; const bench = common.createBenchmark(main, { type: Object.keys(inputs), diff --git a/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js b/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js index ef3160eccd49e6..7e56b5fba6e4f8 100644 --- a/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js +++ b/benchmark/url/legacy-vs-whatwg-url-searchparams-serialize.js @@ -2,18 +2,7 @@ const common = require('../common.js'); const { URLSearchParams } = require('url'); const querystring = require('querystring'); - -const inputs = { - noencode: 'foo=bar&baz=quux&xyzzy=thud', - encodemany: '%66%6F%6F=bar&%62%61%7A=quux&xyzzy=%74h%75d', - encodefake: 'foo=%©ar&baz=%A©uux&xyzzy=%©ud', - encodelast: 'foo=bar&baz=quux&xyzzy=thu%64', - multicharsep: 'foo=bar&&&&&&&&&&baz=quux&&&&&&&&&&xyzzy=thud', - multivalue: 'foo=bar&foo=baz&foo=quux&quuy=quuz', - multivaluemany: 'foo=bar&foo=baz&foo=quux&quuy=quuz&foo=abc&foo=def&' + - 'foo=ghi&foo=jkl&foo=mno&foo=pqr&foo=stu&foo=vwxyz', - manypairs: 'a&b&c&d&e&f&g&h&i&j&k&l&m&n&o&p&q&r&s&t&u&v&w&x&y&z' -}; +const inputs = require('../fixtures/url-inputs.js').searchParams; const bench = common.createBenchmark(main, { type: Object.keys(inputs), diff --git a/benchmark/url/legacy-vs-whatwg-url-serialize.js b/benchmark/url/legacy-vs-whatwg-url-serialize.js index c0b7f5a6ce1565..911e79794b84fb 100644 --- a/benchmark/url/legacy-vs-whatwg-url-serialize.js +++ b/benchmark/url/legacy-vs-whatwg-url-serialize.js @@ -3,19 +3,7 @@ const common = require('../common.js'); const url = require('url'); const URL = url.URL; const assert = require('assert'); - -const inputs = { - long: 'http://nodejs.org:89/docs/latest/api/url.html#test?' + - 'payload1=true&payload2=false&test=1&benchmark=3&' + - 'foo=38.38.011.293&bar=1234834910480&test=19299&3992&' + - 'key=f5c65e1e98fe07e648249ad41e1cfdb0', - short: 'https://nodejs.org/en/blog/', - idn: 'http://你好你好', - auth: 'https://user:pass@example.com/path?search=1', - special: 'file:///foo/bar/test/node.js', - percent: 'https://%E4%BD%A0/foo', - dot: 'https://example.org/./a/../b/./c' -}; +const inputs = require('../fixtures/url-inputs.js').urls; const bench = common.createBenchmark(main, { type: Object.keys(inputs), From 678ea11955855c60bccfe31b70e4e891c843f244 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 9 Feb 2017 23:41:42 +0800 Subject: [PATCH 011/164] benchmark: refactor whatwg-url-properties PR-URL: https://github.com/nodejs/node/pull/11264 Reviewed-By: James M Snell Reviewed-By: Joyee Cheung Reviewed-By: Brian White --- benchmark/url/whatwg-url-properties.js | 34 +++++++------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/benchmark/url/whatwg-url-properties.js b/benchmark/url/whatwg-url-properties.js index 375939c601d363..9bdc9778a8c922 100644 --- a/benchmark/url/whatwg-url-properties.js +++ b/benchmark/url/whatwg-url-properties.js @@ -1,16 +1,11 @@ 'use strict'; +const common = require('../common.js'); +const URL = require('url').URL; +const inputs = require('../fixtures/url-inputs.js').urls; -var common = require('../common.js'); -var URL = require('url').URL; - -var bench = common.createBenchmark(main, { - url: [ - 'http://example.com/', - 'https://encrypted.google.com/search?q=url&q=site:npmjs.org&hl=en', - 'javascript:alert("node is awesome");', - 'http://user:pass@foo.bar.com:21/aaa/zzz?l=24#test' - ], - prop: ['toString', 'href', 'origin', 'protocol', +const bench = common.createBenchmark(main, { + input: Object.keys(inputs), + prop: ['href', 'origin', 'protocol', 'username', 'password', 'host', 'hostname', 'port', 'pathname', 'search', 'searchParams', 'hash'], n: [1e4] @@ -34,14 +29,6 @@ function get(n, url, prop) { bench.end(n); } -function stringify(n, url, prop) { - bench.start(); - for (var i = 0; i < n; i += 1) { - url.toString(); - } - bench.end(n); -} - const alternatives = { href: 'http://user:pass@foo.bar.com:21/aaa/zzz?l=25#test', protocol: 'https:', @@ -61,7 +48,8 @@ function getAlternative(prop) { function main(conf) { const n = conf.n | 0; - const url = new URL(conf.url); + const input = inputs[conf.input]; + const url = new URL(input); const prop = conf.prop; switch (prop) { @@ -74,17 +62,13 @@ function main(conf) { case 'pathname': case 'search': case 'hash': + case 'href': setAndGet(n, url, prop, getAlternative(prop)); break; - // TODO: move href to the first group when the setter lands. - case 'href': case 'origin': case 'searchParams': get(n, url, prop); break; - case 'toString': - stringify(n, url); - break; default: throw new Error('Unknown prop'); } From 662b0c31ce7b0d3155eb5699021f8a066e5e1d66 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 13 Feb 2017 14:26:49 -0800 Subject: [PATCH 012/164] dns: avoid use of arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/11359 Reviewed-By: Luigi Pinca Reviewed-By: Michael Dawson Reviewed-By: Michaël Zasso Reviewed-By: Сковорода Никита Андреевич Date: Mon, 13 Feb 2017 13:26:42 -0800 Subject: [PATCH 013/164] tls: avoid potentially deoptimizing use of arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace use of arguments with `...args` ``` tls/tls-connect.js dur=5 concurrency=1 -9.43 % 0.172136744 tls/tls-connect.js dur=5 concurrency=10 29.05 % ** 0.001108115 ``` PR-URL: https://github.com/nodejs/node/pull/11357 Reviewed-By: Sam Roberts Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Rich Trott Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- lib/_tls_wrap.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index 83a0f109939dc5..b2d30fb25ae6bf 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -294,9 +294,9 @@ var proxiedMethods = [ // Proxy HandleWrap, PipeWrap and TCPWrap methods proxiedMethods.forEach(function(name) { - tls_wrap.TLSWrap.prototype[name] = function methodProxy() { + tls_wrap.TLSWrap.prototype[name] = function methodProxy(...args) { if (this._parent[name]) - return this._parent[name].apply(this._parent, arguments); + return this._parent[name].apply(this._parent, args); }; }); @@ -986,11 +986,7 @@ function normalizeConnectArgs(listArgs) { return (cb) ? [options, cb] : [options]; } -exports.connect = function(/* [port,] [host,] [options,] [cb] */) { - const argsLen = arguments.length; - var args = new Array(argsLen); - for (var i = 0; i < argsLen; i++) - args[i] = arguments[i]; +exports.connect = function(...args /* [port,] [host,] [options,] [cb] */) { args = normalizeConnectArgs(args); var options = args[0]; var cb = args[1]; From 7d47f27049193887484b8f68bab70458d243de80 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 13 Feb 2017 17:45:42 -0500 Subject: [PATCH 014/164] src: remove unused variable in node_crypto MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit env was unused since the ref'd commit Ref: https://github.com/nodejs/node/commit/e34ee1d2c978d46f8aee3fedda0f32bc2a04d7d4 PR-URL: https://github.com/nodejs/node/pull/11361 Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell Reviewed-By: Anna Henningsen Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Brian White --- src/node_crypto.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 072a48f40c58dc..51c68ac804b074 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -1813,7 +1813,6 @@ template void SSLWrap::LoadSession(const FunctionCallbackInfo& args) { Base* w; ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder()); - Environment* env = w->ssl_env(); if (args.Length() >= 1 && Buffer::HasInstance(args[0])) { ssize_t slen = Buffer::Length(args[0]); From 0762482339b80064938874ec4e7e4305e80021d8 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Fri, 10 Feb 2017 14:11:22 -0800 Subject: [PATCH 015/164] assert: unlock the assert API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the Stability Index on `assert` from Locked to Stable. PR-URL: https://github.com/nodejs/node/pull/11304 Ref: https://github.com/nodejs/node/issues/11200 Reviewed-By: Sam Roberts Reviewed-By: Michaël Zasso Reviewed-By: Gibson Fahnestock Reviewed-By: Joyee Cheung Reviewed-By: Luigi Pinca Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Evan Lucas Reviewed-By: Anna Henningsen Reviewed-By: James M Snell --- doc/api/assert.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index 8c4279f5d03d22..6e0c9ad409464c 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -1,6 +1,6 @@ # Assert -> Stability: 3 - Locked +> Stability: 2 - Stable The `assert` module provides a simple set of assertion tests that can be used to test invariants. From d08a8e68e87906014c5c4d55f51e21acba8a79e6 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 13 Feb 2017 14:14:42 -0800 Subject: [PATCH 016/164] buffer: avoid use of arguments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid use of arguments in Buffer.prototype.toString() PR-URL: https://github.com/nodejs/node/pull/11358 Reviewed-By: Colin Ihrig Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Luigi Pinca Reviewed-By: Joyee Cheung Reviewed-By: Anna Henningsen --- lib/buffer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index 3f47677dd56469..6ca079223723fc 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -493,12 +493,12 @@ function slowToString(encoding, start, end) { } -Buffer.prototype.toString = function() { +Buffer.prototype.toString = function(encoding, start, end) { let result; if (arguments.length === 0) { result = this.utf8Slice(0, this.length); } else { - result = slowToString.apply(this, arguments); + result = slowToString.call(this, encoding, start, end); } if (result === undefined) throw new Error('"toString()" failed'); From 4ffad094ba25b27d42a01d28ca1a2737076b731d Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 15 Feb 2017 09:35:57 -0800 Subject: [PATCH 017/164] buffer: refactor slowToString MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since slowToString only has one callsite, refactor to eliminate the use of call. PR-URL: https://github.com/nodejs/node/pull/11358 Reviewed-By: Colin Ihrig Reviewed-By: Сковорода Никита Андреевич Reviewed-By: Luigi Pinca Reviewed-By: Joyee Cheung Reviewed-By: Anna Henningsen --- lib/buffer.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/buffer.js b/lib/buffer.js index 6ca079223723fc..21e24c2980f5e6 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -426,10 +426,10 @@ Object.defineProperty(Buffer.prototype, 'offset', { }); -function slowToString(encoding, start, end) { +function slowToString(buf, encoding, start, end) { var loweredCase = false; - // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // No need to verify that "buf.length <= MAX_UINT32" since it's a read-only // property of a typed array. // This behaves neither like String nor Uint8Array in that we set start/end @@ -438,13 +438,13 @@ function slowToString(encoding, start, end) { // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. if (start === undefined || start < 0) start = 0; - // Return early if start > this.length. Done here to prevent potential uint32 + // Return early if start > buf.length. Done here to prevent potential uint32 // coercion fail below. - if (start > this.length) + if (start > buf.length) return ''; - if (end === undefined || end > this.length) - end = this.length; + if (end === undefined || end > buf.length) + end = buf.length; if (end <= 0) return ''; @@ -461,27 +461,27 @@ function slowToString(encoding, start, end) { while (true) { switch (encoding) { case 'hex': - return this.hexSlice(start, end); + return buf.hexSlice(start, end); case 'utf8': case 'utf-8': - return this.utf8Slice(start, end); + return buf.utf8Slice(start, end); case 'ascii': - return this.asciiSlice(start, end); + return buf.asciiSlice(start, end); case 'latin1': case 'binary': - return this.latin1Slice(start, end); + return buf.latin1Slice(start, end); case 'base64': - return this.base64Slice(start, end); + return buf.base64Slice(start, end); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': - return this.ucs2Slice(start, end); + return buf.ucs2Slice(start, end); default: if (loweredCase) @@ -498,7 +498,7 @@ Buffer.prototype.toString = function(encoding, start, end) { if (arguments.length === 0) { result = this.utf8Slice(0, this.length); } else { - result = slowToString.call(this, encoding, start, end); + result = slowToString(this, encoding, start, end); } if (result === undefined) throw new Error('"toString()" failed'); From 6a2f330dbd3d68e7c75826bdc3bef57e67e5a114 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Fri, 10 Feb 2017 23:45:03 -0800 Subject: [PATCH 018/164] assert: remove unneeded condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/11314 Reviewed-By: Colin Ihrig Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Michael Dawson --- lib/assert.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/assert.js b/lib/assert.js index 7f69ba0c60e476..baecb38d4f33d8 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -294,7 +294,8 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) { }; function expectedException(actual, expected) { - if (!actual || !expected) { + // actual is guaranteed to be an Error object, but we need to check expected. + if (!expected) { return false; } From f495389d67b130b8a04467cf9a1c1bbcd5656b08 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Mon, 13 Feb 2017 20:29:33 -0800 Subject: [PATCH 019/164] test: refactor test-tls-cert-chains-in-ca When splitting PEM string into separate certs, use non-capturing regexp to avoid having to put the split string back with .map(). As a bonus, this splits the PEM into two certs, rather than 2 certs and a third crufty whitespace-only string. PR-URL: https://github.com/nodejs/node/pull/11367 Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Sam Roberts --- test/parallel/test-tls-cert-chains-in-ca.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/parallel/test-tls-cert-chains-in-ca.js b/test/parallel/test-tls-cert-chains-in-ca.js index 69f62c3f72d859..3b4e78919fb8b4 100644 --- a/test/parallel/test-tls-cert-chains-in-ca.js +++ b/test/parallel/test-tls-cert-chains-in-ca.js @@ -12,8 +12,7 @@ const { // agent6-cert.pem includes cert for agent6 and ca3, split it apart and // provide ca3 in the .ca property. -const agent6Chain = keys.agent6.cert.split('-----END CERTIFICATE-----') - .map((c) => { return c + '-----END CERTIFICATE-----'; }); +const agent6Chain = keys.agent6.cert.split(/(?=-----BEGIN CERTIFICATE-----)/); const agent6End = agent6Chain[0]; const agent6Middle = agent6Chain[1]; connect({ From 96a6d64250de3013d0507fce36f028d83d3bd040 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 28 Jan 2017 13:27:02 +0100 Subject: [PATCH 020/164] src: make copies of startup environment variables Mutations of the environment can invalidate pointers to environment variables, so make `secure_getenv()` copy them out instead of returning pointers. PR-URL: https://github.com/nodejs/node/pull/11051 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Sam Roberts --- src/node.cc | 49 ++++++++++++++++++++++++++++---------------- src/node_i18n.cc | 12 +++++------ src/node_i18n.h | 3 ++- src/node_internals.h | 2 ++ 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/node.cc b/src/node.cc index 65605ce07a7ae5..a88f04333ce647 100644 --- a/src/node.cc +++ b/src/node.cc @@ -154,7 +154,7 @@ static node_module* modlist_addon; #if defined(NODE_HAVE_I18N_SUPPORT) // Path to ICU data (for i18n / Intl) -static const char* icu_data_dir = nullptr; +static std::string icu_data_dir; // NOLINT(runtime/string) #endif // used by C++ modules as well @@ -901,12 +901,21 @@ Local UVException(Isolate* isolate, // Look up environment variable unless running as setuid root. -inline const char* secure_getenv(const char* key) { +inline bool SafeGetenv(const char* key, std::string* text) { #ifndef _WIN32 - if (getuid() != geteuid() || getgid() != getegid()) - return nullptr; + // TODO(bnoordhuis) Should perhaps also check whether getauxval(AT_SECURE) + // is non-zero on Linux. + if (getuid() != geteuid() || getgid() != getegid()) { + text->clear(); + return false; + } #endif - return getenv(key); + if (const char* value = getenv(key)) { + *text = value; + return true; + } + text->clear(); + return false; } @@ -3061,11 +3070,11 @@ void SetupProcessObject(Environment* env, #if defined(NODE_HAVE_I18N_SUPPORT) && defined(U_ICU_VERSION) // ICU-related versions are now handled on the js side, see bootstrap_node.js - if (icu_data_dir != nullptr) { + if (!icu_data_dir.empty()) { // Did the user attempt (via env var or parameter) to set an ICU path? READONLY_PROPERTY(process, "icu_data_dir", - OneByteString(env->isolate(), icu_data_dir)); + OneByteString(env->isolate(), icu_data_dir.c_str())); } #endif @@ -3694,7 +3703,7 @@ static void ParseArgs(int* argc, #endif /* HAVE_OPENSSL */ #if defined(NODE_HAVE_I18N_SUPPORT) } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) { - icu_data_dir = arg + 15; + icu_data_dir.assign(arg, 15); #endif } else if (strcmp(arg, "--expose-internals") == 0 || strcmp(arg, "--expose_internals") == 0) { @@ -4181,8 +4190,10 @@ void Init(int* argc, #endif // Allow for environment set preserving symlinks. - if (auto preserve_symlinks = secure_getenv("NODE_PRESERVE_SYMLINKS")) { - config_preserve_symlinks = (*preserve_symlinks == '1'); + { + std::string text; + config_preserve_symlinks = + SafeGetenv("NODE_PRESERVE_SYMLINKS", &text) && text[0] == '1'; } // Parse a few arguments which are specific to Node. @@ -4211,12 +4222,11 @@ void Init(int* argc, #endif #if defined(NODE_HAVE_I18N_SUPPORT) - if (icu_data_dir == nullptr) { - // if the parameter isn't given, use the env variable. - icu_data_dir = secure_getenv("NODE_ICU_DATA"); - } + // If the parameter isn't given, use the env variable. + if (icu_data_dir.empty()) + SafeGetenv("NODE_ICU_DATA", &icu_data_dir); // Initialize ICU. - // If icu_data_dir is nullptr here, it will load the 'minimal' data. + // If icu_data_dir is empty here, it will load the 'minimal' data. if (!i18n::InitializeICUDirectory(icu_data_dir)) { FatalError(nullptr, "Could not initialize ICU " "(check NODE_ICU_DATA or --icu-data-dir parameters)"); @@ -4481,8 +4491,11 @@ int Start(int argc, char** argv) { Init(&argc, const_cast(argv), &exec_argc, &exec_argv); #if HAVE_OPENSSL - if (const char* extra = secure_getenv("NODE_EXTRA_CA_CERTS")) - crypto::UseExtraCaCerts(extra); + { + std::string extra_ca_certs; + if (SafeGetenv("NODE_EXTRA_CA_CERTS", &extra_ca_certs)) + crypto::UseExtraCaCerts(extra_ca_certs); + } #ifdef NODE_FIPS_MODE // In the case of FIPS builds we should make sure // the random source is properly initialized first. @@ -4491,7 +4504,7 @@ int Start(int argc, char** argv) { // V8 on Windows doesn't have a good source of entropy. Seed it from // OpenSSL's pool. V8::SetEntropySource(crypto::EntropySource); -#endif +#endif // HAVE_OPENSSL v8_platform.Initialize(v8_thread_pool_size); V8::Initialize(); diff --git a/src/node_i18n.cc b/src/node_i18n.cc index a98fdca4d1bffd..40d048fa36d0ce 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -404,12 +404,8 @@ static void GetVersion(const FunctionCallbackInfo& args) { } } -bool InitializeICUDirectory(const char* icu_data_path) { - if (icu_data_path != nullptr) { - flag_icu_data_dir = true; - u_setDataDirectory(icu_data_path); - return true; // no error - } else { +bool InitializeICUDirectory(const std::string& path) { + if (path.empty()) { UErrorCode status = U_ZERO_ERROR; #ifdef NODE_HAVE_SMALL_ICU // install the 'small' data. @@ -418,6 +414,10 @@ bool InitializeICUDirectory(const char* icu_data_path) { // no small data, so nothing to do. #endif // !NODE_HAVE_SMALL_ICU return (status == U_ZERO_ERROR); + } else { + flag_icu_data_dir = true; + u_setDataDirectory(path.c_str()); + return true; // No error. } } diff --git a/src/node_i18n.h b/src/node_i18n.h index 21a579526ddc1a..0bfd3c5c859792 100644 --- a/src/node_i18n.h +++ b/src/node_i18n.h @@ -4,6 +4,7 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "node.h" +#include #if defined(NODE_HAVE_I18N_SUPPORT) @@ -13,7 +14,7 @@ extern bool flag_icu_data_dir; namespace i18n { -bool InitializeICUDirectory(const char* icu_data_path); +bool InitializeICUDirectory(const std::string& path); int32_t ToASCII(MaybeStackBuffer* buf, const char* input, diff --git a/src/node_internals.h b/src/node_internals.h index 0a65be7642ff2a..c22cb22c948bd2 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -12,6 +12,8 @@ #include #include +#include + struct sockaddr; // Variation on NODE_DEFINE_CONSTANT that sets a String value. From 73e316e90870574c9958f38abc65c6cc138fc4e8 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 11 Feb 2017 14:00:22 +0100 Subject: [PATCH 021/164] src: make --icu-data-dir= switch testable Move some code around so we can properly test whether the switch actually does anything. PR-URL: https://github.com/nodejs/node/pull/11255 Reviewed-By: James M Snell Reviewed-By: Sam Roberts --- lib/internal/process.js | 4 +--- src/node.cc | 13 +------------ src/node_config.cc | 7 +++++-- src/node_i18n.cc | 3 --- src/node_i18n.h | 2 +- test/parallel/test-intl-no-icu-data.js | 7 +++++++ 6 files changed, 15 insertions(+), 21 deletions(-) create mode 100644 test/parallel/test-intl-no-icu-data.js diff --git a/lib/internal/process.js b/lib/internal/process.js index 441fb722edb153..a756f0d429c10d 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -122,7 +122,7 @@ function setupConfig(_source) { const oldV8BreakIterator = Intl.v8BreakIterator; const des = Object.getOwnPropertyDescriptor(Intl, 'v8BreakIterator'); des.value = require('internal/util').deprecate(function v8BreakIterator() { - if (processConfig.hasSmallICU && !process.icu_data_dir) { + if (processConfig.hasSmallICU && !processConfig.icuDataDir) { // Intl.v8BreakIterator() would crash w/ fatal error, so throw instead. throw new Error('v8BreakIterator: full ICU data not installed. ' + 'See https://github.com/nodejs/node/wiki/Intl'); @@ -131,8 +131,6 @@ function setupConfig(_source) { }, 'Intl.v8BreakIterator is deprecated and will be removed soon.'); Object.defineProperty(Intl, 'v8BreakIterator', des); } - // Don’t let icu_data_dir leak through. - delete process.icu_data_dir; } diff --git a/src/node.cc b/src/node.cc index a88f04333ce647..78a72e3263016b 100644 --- a/src/node.cc +++ b/src/node.cc @@ -154,7 +154,7 @@ static node_module* modlist_addon; #if defined(NODE_HAVE_I18N_SUPPORT) // Path to ICU data (for i18n / Intl) -static std::string icu_data_dir; // NOLINT(runtime/string) +std::string icu_data_dir; // NOLINT(runtime/string) #endif // used by C++ modules as well @@ -3067,17 +3067,6 @@ void SetupProcessObject(Environment* env, "ares", FIXED_ONE_BYTE_STRING(env->isolate(), ARES_VERSION_STR)); -#if defined(NODE_HAVE_I18N_SUPPORT) && defined(U_ICU_VERSION) - // ICU-related versions are now handled on the js side, see bootstrap_node.js - - if (!icu_data_dir.empty()) { - // Did the user attempt (via env var or parameter) to set an ICU path? - READONLY_PROPERTY(process, - "icu_data_dir", - OneByteString(env->isolate(), icu_data_dir.c_str())); - } -#endif - const char node_modules_version[] = NODE_STRINGIFY(NODE_MODULE_VERSION); READONLY_PROPERTY( versions, diff --git a/src/node_config.cc b/src/node_config.cc index 401345f6a608be..98b219c3e81d1b 100644 --- a/src/node_config.cc +++ b/src/node_config.cc @@ -38,8 +38,11 @@ void InitConfig(Local target, READONLY_BOOLEAN_PROPERTY("hasSmallICU"); #endif // NODE_HAVE_SMALL_ICU - if (flag_icu_data_dir) - READONLY_BOOLEAN_PROPERTY("usingICUDataDir"); + target->DefineOwnProperty(env->context(), + OneByteString(env->isolate(), "icuDataDir"), + OneByteString(env->isolate(), icu_data_dir.data())) + .FromJust(); + #endif // NODE_HAVE_I18N_SUPPORT if (config_preserve_symlinks) diff --git a/src/node_i18n.cc b/src/node_i18n.cc index 40d048fa36d0ce..648012a50601e3 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -70,8 +70,6 @@ using v8::Object; using v8::String; using v8::Value; -bool flag_icu_data_dir = false; - namespace i18n { const size_t kStorageSize = 1024; @@ -415,7 +413,6 @@ bool InitializeICUDirectory(const std::string& path) { #endif // !NODE_HAVE_SMALL_ICU return (status == U_ZERO_ERROR); } else { - flag_icu_data_dir = true; u_setDataDirectory(path.c_str()); return true; // No error. } diff --git a/src/node_i18n.h b/src/node_i18n.h index 0bfd3c5c859792..21567eeb3ec38f 100644 --- a/src/node_i18n.h +++ b/src/node_i18n.h @@ -10,7 +10,7 @@ namespace node { -extern bool flag_icu_data_dir; +extern std::string icu_data_dir; // NOLINT(runtime/string) namespace i18n { diff --git a/test/parallel/test-intl-no-icu-data.js b/test/parallel/test-intl-no-icu-data.js new file mode 100644 index 00000000000000..dd14c146719fb1 --- /dev/null +++ b/test/parallel/test-intl-no-icu-data.js @@ -0,0 +1,7 @@ +// Flags: --icu-data-dir=test/fixtures/empty/ +'use strict'; +require('../common'); +const assert = require('assert'); + +// No-op when ICU case mappings are unavailable. +assert.strictEqual('ç'.toLocaleUpperCase('el'), 'ç'); From a8613f8ce4bdbee32ed25819092e9a9c7f137c87 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 11 Feb 2017 14:04:58 +0100 Subject: [PATCH 022/164] src: fix --icu-data-dir= regression Commit a8734af ("src: make copies of startup environment variables") from two weeks ago introduced a regression in the capturing of the `--icu-data-dir=` switch: it captured the string up to the `=` instead of what comes after it. PR-URL: https://github.com/nodejs/node/pull/11255 Reviewed-By: James M Snell Reviewed-By: Sam Roberts --- src/node.cc | 2 +- test/parallel/test-intl-no-icu-data.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/node.cc b/src/node.cc index 78a72e3263016b..37d4309aa0c39a 100644 --- a/src/node.cc +++ b/src/node.cc @@ -3692,7 +3692,7 @@ static void ParseArgs(int* argc, #endif /* HAVE_OPENSSL */ #if defined(NODE_HAVE_I18N_SUPPORT) } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) { - icu_data_dir.assign(arg, 15); + icu_data_dir.assign(arg + 15); #endif } else if (strcmp(arg, "--expose-internals") == 0 || strcmp(arg, "--expose_internals") == 0) { diff --git a/test/parallel/test-intl-no-icu-data.js b/test/parallel/test-intl-no-icu-data.js index dd14c146719fb1..ce5e9a08121cdc 100644 --- a/test/parallel/test-intl-no-icu-data.js +++ b/test/parallel/test-intl-no-icu-data.js @@ -2,6 +2,8 @@ 'use strict'; require('../common'); const assert = require('assert'); +const config = process.binding('config'); // No-op when ICU case mappings are unavailable. assert.strictEqual('ç'.toLocaleUpperCase('el'), 'ç'); +assert.strictEqual(config.icuDataDir, 'test/fixtures/empty/'); From 8be6702539bbbcb81c9c222a42fb384d1eb67a9b Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Fri, 27 Jan 2017 11:49:14 -0800 Subject: [PATCH 023/164] src: add SafeGetenv() to internal API Allow it to be used anywhere in src/ that env variables with security implications are accessed. PR-URL: #11006 Reviewed-By: Michael Dawson Reviewed-By: Ben Noordhuis --- src/node.cc | 2 +- src/node_internals.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/node.cc b/src/node.cc index 37d4309aa0c39a..0b319ea1a0bffd 100644 --- a/src/node.cc +++ b/src/node.cc @@ -901,7 +901,7 @@ Local UVException(Isolate* isolate, // Look up environment variable unless running as setuid root. -inline bool SafeGetenv(const char* key, std::string* text) { +bool SafeGetenv(const char* key, std::string* text) { #ifndef _WIN32 // TODO(bnoordhuis) Should perhaps also check whether getauxval(AT_SECURE) // is non-zero on Linux. diff --git a/src/node_internals.h b/src/node_internals.h index c22cb22c948bd2..adfb453895a650 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -108,6 +108,8 @@ void RegisterSignalHandler(int signal, bool reset_handler = false); #endif +bool SafeGetenv(const char* key, std::string* text); + template constexpr size_t arraysize(const T(&)[N]) { return N; } From 570c5e1da8169bf23b0431884818aeca9f50f294 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Wed, 25 Jan 2017 14:13:34 -0800 Subject: [PATCH 024/164] crypto: support OPENSSL_CONF again A side-effect of https://github.com/nodejs/node-private/pull/82 was to remove support for OPENSSL_CONF, as well as removing the default read of a configuration file on startup. Partly revert this, allowing OPENSSL_CONF to be used to specify a configuration file to read on startup, but do not read a file by default. If the --openssl-config command line option is provided, its value is used, not the OPENSSL_CONF environment variable. Fix: https://github.com/nodejs/node/issues/10938 PR-URL: https://github.com/nodejs/node/pull/11006 Reviewed-By: Michael Dawson Reviewed-By: Ben Noordhuis --- doc/api/cli.md | 13 +++++++++++++ doc/node.1 | 10 ++++++++++ src/node.cc | 14 ++++++++++---- src/node_crypto.cc | 4 ++-- src/node_internals.h | 2 +- test/parallel/test-crypto-fips.js | 25 ++++++++++++++++++++++--- 6 files changed, 58 insertions(+), 10 deletions(-) diff --git a/doc/api/cli.md b/doc/api/cli.md index 809bd326a6273c..099c4c993d113c 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -363,6 +363,18 @@ misformatted, but any errors are otherwise ignored. Note that neither the well known nor extra certificates are used when the `ca` options property is explicitly specified for a TLS or HTTPS client or server. +### `OPENSSL_CONF=file` + + +Load an OpenSSL configuration file on startup. Among other uses, this can be +used to enable FIPS-compliant crypto if Node.js is built with `./configure +\-\-openssl\-fips`. + +If the [`--openssl-config`][] command line option is used, the environment +variable is ignored. + ### `SSL_CERT_DIR=dir` If `--use-openssl-ca` is enabled, this overrides and sets OpenSSL's directory @@ -386,3 +398,4 @@ OpenSSL, it may cause them to trust the same CAs as node. [debugger]: debugger.html [REPL]: repl.html [SlowBuffer]: buffer.html#buffer_class_slowbuffer +[`--openssl-config`]: #cli_openssl_config_file diff --git a/doc/node.1 b/doc/node.1 index ffe72e1d022aa6..026485d3920923 100644 --- a/doc/node.1 +++ b/doc/node.1 @@ -243,6 +243,16 @@ asynchronous when outputting to a TTY on platforms which support async stdio. Setting this will void any guarantee that stdio will not be interleaved or dropped at program exit. \fBAvoid use.\fR +.TP +.BR OPENSSL_CONF = \fIfile\fR +Load an OpenSSL configuration file on startup. Among other uses, this can be +used to enable FIPS-compliant crypto if Node.js is built with +\fB./configure \-\-openssl\-fips\fR. + +If the +\fB\-\-openssl\-config\fR +command line option is used, the environment variable is ignored. + .TP .BR SSL_CERT_DIR = \fIdir\fR If \fB\-\-use\-openssl\-ca\fR is enabled, this overrides and sets OpenSSL's directory diff --git a/src/node.cc b/src/node.cc index 0b319ea1a0bffd..2f470ddda0a83b 100644 --- a/src/node.cc +++ b/src/node.cc @@ -174,7 +174,7 @@ bool ssl_openssl_cert_store = bool enable_fips_crypto = false; bool force_fips_crypto = false; # endif // NODE_FIPS_MODE -const char* openssl_config = nullptr; +std::string openssl_config; // NOLINT(runtime/string) #endif // HAVE_OPENSSL // true if process warnings should be suppressed @@ -3517,8 +3517,9 @@ static void PrintHelp() { " --enable-fips enable FIPS crypto at startup\n" " --force-fips force FIPS crypto (cannot be disabled)\n" #endif /* NODE_FIPS_MODE */ - " --openssl-config=path load OpenSSL configuration file from\n" - " the specified path\n" + " --openssl-config=file load OpenSSL configuration from the\n" + " specified file (overrides\n" + " OPENSSL_CONF)\n" #endif /* HAVE_OPENSSL */ #if defined(NODE_HAVE_I18N_SUPPORT) " --icu-data-dir=dir set ICU data load path to dir\n" @@ -3551,6 +3552,8 @@ static void PrintHelp() { " prefixed to the module search path\n" "NODE_REPL_HISTORY path to the persistent REPL history\n" " file\n" + "OPENSSL_CONF load OpenSSL configuration from file\n" + "\n" "Documentation can be found at https://nodejs.org/\n"); } @@ -3688,7 +3691,7 @@ static void ParseArgs(int* argc, force_fips_crypto = true; #endif /* NODE_FIPS_MODE */ } else if (strncmp(arg, "--openssl-config=", 17) == 0) { - openssl_config = arg + 17; + openssl_config.assign(arg + 17); #endif /* HAVE_OPENSSL */ #if defined(NODE_HAVE_I18N_SUPPORT) } else if (strncmp(arg, "--icu-data-dir=", 15) == 0) { @@ -4185,6 +4188,9 @@ void Init(int* argc, SafeGetenv("NODE_PRESERVE_SYMLINKS", &text) && text[0] == '1'; } + if (openssl_config.empty()) + SafeGetenv("OPENSSL_CONF", &openssl_config); + // Parse a few arguments which are specific to Node. int v8_argc; const char** v8_argv; diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 51c68ac804b074..d9f056682013b5 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -5880,14 +5880,14 @@ void InitCryptoOnce() { OPENSSL_no_config(); // --openssl-config=... - if (openssl_config != nullptr) { + if (!openssl_config.empty()) { OPENSSL_load_builtin_modules(); #ifndef OPENSSL_NO_ENGINE ENGINE_load_builtin_engines(); #endif ERR_clear_error(); CONF_modules_load_file( - openssl_config, + openssl_config.c_str(), nullptr, CONF_MFLAGS_DEFAULT_SECTION); int err = ERR_get_error(); diff --git a/src/node_internals.h b/src/node_internals.h index adfb453895a650..f786adcdb3121c 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -36,7 +36,7 @@ namespace node { // Set in node.cc by ParseArgs with the value of --openssl-config. // Used in node_crypto.cc when initializing OpenSSL. -extern const char* openssl_config; +extern std::string openssl_config; // Set in node.cc by ParseArgs when --preserve-symlinks is used. // Used in node_config.cc to set a constant on process.binding('config') diff --git a/test/parallel/test-crypto-fips.js b/test/parallel/test-crypto-fips.js index 6fd3352740c8c3..ae510741943ca8 100644 --- a/test/parallel/test-crypto-fips.js +++ b/test/parallel/test-crypto-fips.js @@ -37,8 +37,9 @@ function testHelper(stream, args, expectedOutput, cmd, env) { env: env }); - console.error('Spawned child [pid:' + child.pid + '] with cmd ' + - cmd + ' and args \'' + args + '\''); + console.error('Spawned child [pid:' + child.pid + '] with cmd \'' + + cmd + '\' expect %j with args \'' + args + '\'' + + ' OPENSSL_CONF=%j', expectedOutput, env.OPENSSL_CONF); function childOk(child) { console.error('Child #' + ++num_children_ok + @@ -92,10 +93,26 @@ testHelper( compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED, 'require("crypto").fips', process.env); -// OPENSSL_CONF should _not_ be able to turn on FIPS mode + +// OPENSSL_CONF should be able to turn on FIPS mode testHelper( 'stdout', [], + compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED, + 'require("crypto").fips', + addToEnv('OPENSSL_CONF', CNF_FIPS_ON)); + +// --openssl-config option should override OPENSSL_CONF +testHelper( + 'stdout', + [`--openssl-config=${CNF_FIPS_ON}`], + compiledWithFips() ? FIPS_ENABLED : FIPS_DISABLED, + 'require("crypto").fips', + addToEnv('OPENSSL_CONF', CNF_FIPS_OFF)); + +testHelper( + 'stdout', + [`--openssl-config=${CNF_FIPS_OFF}`], FIPS_DISABLED, 'require("crypto").fips', addToEnv('OPENSSL_CONF', CNF_FIPS_ON)); @@ -107,6 +124,7 @@ testHelper( compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING, 'require("crypto").fips', process.env); + // OPENSSL_CONF should _not_ make a difference to --enable-fips testHelper( compiledWithFips() ? 'stdout' : 'stderr', @@ -122,6 +140,7 @@ testHelper( compiledWithFips() ? FIPS_ENABLED : OPTION_ERROR_STRING, 'require("crypto").fips', process.env); + // Using OPENSSL_CONF should not make a difference to --force-fips testHelper( compiledWithFips() ? 'stdout' : 'stderr', From 7aaa960f4c93ab7b4b33234ab6636d0063b28bbc Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 2 Feb 2017 14:13:16 +0800 Subject: [PATCH 025/164] test, url: synchronize WPT url tests * attributon of WPT in url-setter-tests * add WPT test utilities * synchronize WPT URLSearchParams tests * synchronize WPT url tests * split whatwg-url-inspect test * port historical url tests from WPT * protocol setter and special URLs Refs: https://github.com/w3c/web-platform-tests/pull/4413 Refs: https://github.com/whatwg/url/issues/104 Backport-of: https://github.com/nodejs/node/pull/11079 --- test/common.js | 25 ++ test/fixtures/url-setter-tests.json | 48 ++- test/fixtures/url-tests-additional.js | 87 +++++ test/parallel/test-whatwg-url-constructor.js | 142 ++++++++ test/parallel/test-whatwg-url-historical.js | 46 +++ test/parallel/test-whatwg-url-inspect.js | 83 +++++ test/parallel/test-whatwg-url-origin.js | 52 +++ test/parallel/test-whatwg-url-parsing.js | 192 +---------- test/parallel/test-whatwg-url-properties.js | 2 +- .../test-whatwg-url-searchparams-append.js | 103 +++--- ...est-whatwg-url-searchparams-constructor.js | 316 +++++++++++------- .../test-whatwg-url-searchparams-delete.js | 91 ++--- .../test-whatwg-url-searchparams-entries.js | 1 + .../test-whatwg-url-searchparams-foreach.js | 79 +++-- .../test-whatwg-url-searchparams-get.js | 69 ++-- .../test-whatwg-url-searchparams-getall.js | 80 ++--- .../test-whatwg-url-searchparams-has.js | 76 +++-- .../test-whatwg-url-searchparams-inspect.js | 7 +- .../test-whatwg-url-searchparams-keys.js | 1 + .../test-whatwg-url-searchparams-set.js | 73 ++-- ...est-whatwg-url-searchparams-stringifier.js | 238 +++++++------ .../test-whatwg-url-searchparams-values.js | 1 + test/parallel/test-whatwg-url-searchparams.js | 1 + test/parallel/test-whatwg-url-setters.js | 82 ++++- test/parallel/test-whatwg-url-tostringtag.js | 2 + 25 files changed, 1194 insertions(+), 703 deletions(-) create mode 100644 test/fixtures/url-tests-additional.js create mode 100644 test/parallel/test-whatwg-url-constructor.js create mode 100644 test/parallel/test-whatwg-url-historical.js create mode 100644 test/parallel/test-whatwg-url-inspect.js create mode 100644 test/parallel/test-whatwg-url-origin.js diff --git a/test/common.js b/test/common.js index 830206ea0f93ef..6cdf698fb5e839 100644 --- a/test/common.js +++ b/test/common.js @@ -588,3 +588,28 @@ Object.defineProperty(exports, 'hasIntl', { return process.binding('config').hasIntl; } }); + +// https://github.com/w3c/testharness.js/blob/master/testharness.js +exports.WPT = { + test: (fn, desc) => { + try { + fn(); + } catch (err) { + if (err instanceof Error) + err.message = `In ${desc}:\n ${err.message}`; + throw err; + } + }, + assert_equals: assert.strictEqual, + assert_true: (value, message) => assert.strictEqual(value, true, message), + assert_false: (value, message) => assert.strictEqual(value, false, message), + assert_throws: (code, func, desc) => { + assert.throws(func, (err) => { + return typeof err === 'object' && 'name' in err && err.name === code.name; + }, desc); + }, + assert_array_equals: assert.deepStrictEqual, + assert_unreached(desc) { + assert.fail(undefined, undefined, `Reached unreachable code: ${desc}`); + } +}; diff --git a/test/fixtures/url-setter-tests.json b/test/fixtures/url-setter-tests.json index 56a1c00a86fd45..4876b9940c1d98 100644 --- a/test/fixtures/url-setter-tests.json +++ b/test/fixtures/url-setter-tests.json @@ -1,5 +1,6 @@ { "comment": [ + "License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html", "## Tests for setters of https://url.spec.whatwg.org/#urlutils-members", "", "This file contains a JSON object.", @@ -19,8 +20,7 @@ " get the attribute `key` (invoke its getter).", " The returned string must be equal to `value`.", "", - "Note: the 'href' setter is already covered by urltestdata.json.", - "Source: https://github.com/w3c/web-platform-tests/tree/master/url" + "Note: the 'href' setter is already covered by urltestdata.json." ], "protocol": [ { @@ -103,7 +103,7 @@ } }, { - "comment": "Can’t switch from special scheme to non-special. Note: this may change, see https://github.com/whatwg/url/issues/104", + "comment": "Can’t switch from special scheme to non-special", "href": "http://example.net", "new_value": "b", "expected": { @@ -111,6 +111,22 @@ "protocol": "http:" } }, + { + "href": "https://example.net", + "new_value": "s", + "expected": { + "href": "https://example.net/", + "protocol": "https:" + } + }, + { + "href": "ftp://example.net", + "new_value": "test", + "expected": { + "href": "ftp://example.net/", + "protocol": "ftp:" + } + }, { "comment": "Cannot-be-a-base URL doesn’t have a host, but URL in a special scheme must.", "href": "mailto:me@example.net", @@ -121,7 +137,7 @@ } }, { - "comment": "Can’t switch from non-special scheme to special. Note: this may change, see https://github.com/whatwg/url/issues/104", + "comment": "Can’t switch from non-special scheme to special", "href": "ssh://me@example.net", "new_value": "http", "expected": { @@ -129,6 +145,30 @@ "protocol": "ssh:" } }, + { + "href": "ssh://me@example.net", + "new_value": "gopher", + "expected": { + "href": "ssh://me@example.net/", + "protocol": "ssh:" + } + }, + { + "href": "ssh://me@example.net", + "new_value": "file", + "expected": { + "href": "ssh://me@example.net/", + "protocol": "ssh:" + } + }, + { + "href": "nonsense:///test", + "new_value": "https", + "expected": { + "href": "nonsense:///test", + "protocol": "nonsense:" + } + }, { "comment": "Stuff after the first ':' is ignored", "href": "http://example.net", diff --git a/test/fixtures/url-tests-additional.js b/test/fixtures/url-tests-additional.js new file mode 100644 index 00000000000000..7e3282d17d091b --- /dev/null +++ b/test/fixtures/url-tests-additional.js @@ -0,0 +1,87 @@ +module.exports = [ + { + 'url': 'tftp://foobar.com/someconfig;mode=netascii', + 'protocol': 'tftp:', + 'hostname': 'foobar.com', + 'pathname': '/someconfig;mode=netascii' + }, + { + 'url': 'telnet://user:pass@foobar.com:23/', + 'protocol': 'telnet:', + 'username': 'user', + 'password': 'pass', + 'hostname': 'foobar.com', + 'port': '23', + 'pathname': '/' + }, + { + 'url': 'ut2004://10.10.10.10:7777/Index.ut2', + 'protocol': 'ut2004:', + 'hostname': '10.10.10.10', + 'port': '7777', + 'pathname': '/Index.ut2' + }, + { + 'url': 'redis://foo:bar@somehost:6379/0?baz=bam&qux=baz', + 'protocol': 'redis:', + 'username': 'foo', + 'password': 'bar', + 'hostname': 'somehost', + 'port': '6379', + 'pathname': '/0', + 'search': '?baz=bam&qux=baz' + }, + { + 'url': 'rsync://foo@host:911/sup', + 'protocol': 'rsync:', + 'username': 'foo', + 'hostname': 'host', + 'port': '911', + 'pathname': '/sup' + }, + { + 'url': 'git://github.com/foo/bar.git', + 'protocol': 'git:', + 'hostname': 'github.com', + 'pathname': '/foo/bar.git' + }, + { + 'url': 'irc://myserver.com:6999/channel?passwd', + 'protocol': 'irc:', + 'hostname': 'myserver.com', + 'port': '6999', + 'pathname': '/channel', + 'search': '?passwd' + }, + { + 'url': 'dns://fw.example.org:9999/foo.bar.org?type=TXT', + 'protocol': 'dns:', + 'hostname': 'fw.example.org', + 'port': '9999', + 'pathname': '/foo.bar.org', + 'search': '?type=TXT' + }, + { + 'url': 'ldap://localhost:389/ou=People,o=JNDITutorial', + 'protocol': 'ldap:', + 'hostname': 'localhost', + 'port': '389', + 'pathname': '/ou=People,o=JNDITutorial' + }, + { + 'url': 'git+https://github.com/foo/bar', + 'protocol': 'git+https:', + 'hostname': 'github.com', + 'pathname': '/foo/bar' + }, + { + 'url': 'urn:ietf:rfc:2648', + 'protocol': 'urn:', + 'pathname': 'ietf:rfc:2648' + }, + { + 'url': 'tag:joe@example.org,2001:foo/bar', + 'protocol': 'tag:', + 'pathname': 'joe@example.org,2001:foo/bar' + } +]; diff --git a/test/parallel/test-whatwg-url-constructor.js b/test/parallel/test-whatwg-url-constructor.js new file mode 100644 index 00000000000000..a8a8667fc47021 --- /dev/null +++ b/test/parallel/test-whatwg-url-constructor.js @@ -0,0 +1,142 @@ +'use strict'; +const common = require('../common'); +const path = require('path'); +const { URL, URLSearchParams } = require('url'); +const { test, assert_equals, assert_true, assert_throws } = common.WPT; + +if (!common.hasIntl) { + // A handful of the tests fail when ICU is not included. + common.skip('missing Intl'); + return; +} + +const request = { + response: require(path.join(common.fixturesDir, 'url-tests.json')) +}; + +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/8791bed/url/url-constructor.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +function runURLConstructorTests() { + // var setup = async_test("Loading data…") + // setup.step(function() { + // var request = new XMLHttpRequest() + // request.open("GET", "urltestdata.json") + // request.send() + // request.responseType = "json" + // request.onload = setup.step_func(function() { + runURLTests(request.response) + // setup.done() + // }) + // }) +} + +function bURL(url, base) { + return new URL(url, base || "about:blank") +} + + +function runURLTests(urltests) { + for(var i = 0, l = urltests.length; i < l; i++) { + var expected = urltests[i] + if (typeof expected === "string") continue // skip comments + + test(function() { + if (expected.failure) { + assert_throws(new TypeError(), function() { + bURL(expected.input, expected.base) + }) + return + } + + var url = bURL(expected.input, expected.base) + assert_equals(url.href, expected.href, "href") + assert_equals(url.protocol, expected.protocol, "protocol") + assert_equals(url.username, expected.username, "username") + assert_equals(url.password, expected.password, "password") + assert_equals(url.host, expected.host, "host") + assert_equals(url.hostname, expected.hostname, "hostname") + assert_equals(url.port, expected.port, "port") + assert_equals(url.pathname, expected.pathname, "pathname") + assert_equals(url.search, expected.search, "search") + if ("searchParams" in expected) { + assert_true("searchParams" in url) + // assert_equals(url.searchParams.toString(), expected.searchParams, "searchParams") + } + assert_equals(url.hash, expected.hash, "hash") + }, "Parsing: <" + expected.input + "> against <" + expected.base + ">") + } +} + +function runURLSearchParamTests() { + test(function() { + var url = bURL('http://example.org/?a=b') + assert_true("searchParams" in url) + var searchParams = url.searchParams + assert_true(url.searchParams === searchParams, 'Object identity should hold.') + }, 'URL.searchParams getter') + + test(function() { + var url = bURL('http://example.org/?a=b') + assert_true("searchParams" in url) + var searchParams = url.searchParams + assert_equals(searchParams.toString(), 'a=b') + + searchParams.set('a', 'b') + assert_equals(url.searchParams.toString(), 'a=b') + assert_equals(url.search, '?a=b') + url.search = '' + assert_equals(url.searchParams.toString(), '') + assert_equals(url.search, '') + assert_equals(searchParams.toString(), '') + }, 'URL.searchParams updating, clearing') + + test(function() { + 'use strict' + var urlString = 'http://example.org' + var url = bURL(urlString) + assert_throws(TypeError(), function() { url.searchParams = new URLSearchParams(urlString) }) + }, 'URL.searchParams setter, invalid values') + + test(function() { + var url = bURL('http://example.org/file?a=b&c=d') + assert_true("searchParams" in url) + var searchParams = url.searchParams + assert_equals(url.search, '?a=b&c=d') + assert_equals(searchParams.toString(), 'a=b&c=d') + + // Test that setting 'search' propagates to the URL object's query object. + url.search = 'e=f&g=h' + assert_equals(url.search, '?e=f&g=h') + assert_equals(searchParams.toString(), 'e=f&g=h') + + // ..and same but with a leading '?'. + url.search = '?e=f&g=h' + assert_equals(url.search, '?e=f&g=h') + assert_equals(searchParams.toString(), 'e=f&g=h') + + // And in the other direction, altering searchParams propagates + // back to 'search'. + // searchParams.append('i', ' j ') + // assert_equals(url.search, '?e=f&g=h&i=+j+') + // assert_equals(url.searchParams.toString(), 'e=f&g=h&i=+j+') + // assert_equals(searchParams.get('i'), ' j ') + + // searchParams.set('e', 'updated') + // assert_equals(url.search, '?e=updated&g=h&i=+j+') + // assert_equals(searchParams.get('e'), 'updated') + + // var url2 = bURL('http://example.org/file??a=b&c=d') + // assert_equals(url2.search, '??a=b&c=d') + // assert_equals(url2.searchParams.toString(), '%3Fa=b&c=d') + + // url2.href = 'http://example.org/file??a=b' + // assert_equals(url2.search, '??a=b') + // assert_equals(url2.searchParams.toString(), '%3Fa=b') + }, 'URL.searchParams and URL.search setters, update propagation') +} +runURLSearchParamTests() +runURLConstructorTests() +/* eslint-enable */ diff --git a/test/parallel/test-whatwg-url-historical.js b/test/parallel/test-whatwg-url-historical.js new file mode 100644 index 00000000000000..452c14fc77a319 --- /dev/null +++ b/test/parallel/test-whatwg-url-historical.js @@ -0,0 +1,46 @@ +'use strict'; +const common = require('../common'); +const URL = require('url').URL; +const { test, assert_equals, assert_throws } = common.WPT; + +if (!common.hasIntl) { + // A handful of the tests fail when ICU is not included. + common.skip('missing Intl'); + return; +} + +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/8791bed/url/historical.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +// var objects = [ +// [function() { return window.location }, "location object"], +// [function() { return document.createElement("a") }, "a element"], +// [function() { return document.createElement("area") }, "area element"], +// ]; + +// objects.forEach(function(o) { +// test(function() { +// var object = o[0](); +// assert_false("searchParams" in object, +// o[1] + " should not have a searchParams attribute"); +// }, "searchParams on " + o[1]); +// }); + +test(function() { + var url = new URL("./foo", "http://www.example.org"); + assert_equals(url.href, "http://www.example.org/foo"); + assert_throws(new TypeError(), function() { + url.href = "./bar"; + }); +}, "Setting URL's href attribute and base URLs"); + +test(function() { + assert_equals(URL.domainToASCII, undefined); +}, "URL.domainToASCII should be undefined"); + +test(function() { + assert_equals(URL.domainToUnicode, undefined); +}, "URL.domainToUnicode should be undefined"); +/* eslint-enable */ diff --git a/test/parallel/test-whatwg-url-inspect.js b/test/parallel/test-whatwg-url-inspect.js new file mode 100644 index 00000000000000..4c6c8771b9f8f4 --- /dev/null +++ b/test/parallel/test-whatwg-url-inspect.js @@ -0,0 +1,83 @@ +'use strict'; + +const common = require('../common'); +const util = require('util'); +const URL = require('url').URL; +const path = require('path'); +const assert = require('assert'); + +if (!common.hasIntl) { + // A handful of the tests fail when ICU is not included. + common.skip('missing Intl'); + return; +} + +// Tests below are not from WPT. +const tests = require(path.join(common.fixturesDir, 'url-tests.json')); +const additional_tests = require( + path.join(common.fixturesDir, 'url-tests-additional.js')); + +const allTests = additional_tests.slice(); +for (const test of tests) { + if (test.failure || typeof test === 'string') continue; + allTests.push(test); +} + +for (const test of allTests) { + const url = test.url ? new URL(test.url) : new URL(test.input, test.base); + + for (const showHidden of [true, false]) { + const res = util.inspect(url, { + showHidden + }); + + const lines = res.split('\n'); + + const firstLine = lines[0]; + assert.strictEqual(firstLine, 'URL {'); + + const lastLine = lines[lines.length - 1]; + assert.strictEqual(lastLine, '}'); + + const innerLines = lines.slice(1, lines.length - 1); + const keys = new Set(); + for (const line of innerLines) { + const i = line.indexOf(': '); + const k = line.slice(0, i).trim(); + const v = line.slice(i + 2); + assert.strictEqual(keys.has(k), false, 'duplicate key found: ' + k); + keys.add(k); + + const hidden = new Set([ + 'password', + 'cannot-be-base', + 'special' + ]); + if (showHidden) { + if (!hidden.has(k)) { + assert.strictEqual(v, url[k], k); + continue; + } + + if (k === 'password') { + assert.strictEqual(v, url[k], k); + } + if (k === 'cannot-be-base') { + assert.ok(v.match(/^true$|^false$/), k + ' is Boolean'); + } + if (k === 'special') { + assert.ok(v.match(/^true$|^false$/), k + ' is Boolean'); + } + continue; + } + + // showHidden is false + if (k === 'password') { + assert.strictEqual(v, '--------', k); + continue; + } + assert.strictEqual(hidden.has(k), false, 'no hidden keys: ' + k); + assert.strictEqual(v, url[k], k); + } + } +} diff --git a/test/parallel/test-whatwg-url-origin.js b/test/parallel/test-whatwg-url-origin.js new file mode 100644 index 00000000000000..1186a1d1844147 --- /dev/null +++ b/test/parallel/test-whatwg-url-origin.js @@ -0,0 +1,52 @@ +'use strict'; +const common = require('../common'); +const path = require('path'); +const URL = require('url').URL; +const { test, assert_equals } = common.WPT; + +if (!common.hasIntl) { + // A handful of the tests fail when ICU is not included. + common.skip('missing Intl'); + return; +} + +const request = { + response: require(path.join(common.fixturesDir, 'url-tests.json')) +}; + +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/8791bed/url/url-origin.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +function runURLOriginTests() { + // var setup = async_test("Loading data…") + // setup.step(function() { + // var request = new XMLHttpRequest() + // request.open("GET", "urltestdata.json") + // request.send() + // request.responseType = "json" + // request.onload = setup.step_func(function() { + runURLTests(request.response) + // setup.done() + // }) + // }) +} + +function bURL(url, base) { + return new URL(url, base || "about:blank") +} + +function runURLTests(urltests) { + for(var i = 0, l = urltests.length; i < l; i++) { + var expected = urltests[i] + if (typeof expected === "string" || !("origin" in expected)) continue + test(function() { + var url = bURL(expected.input, expected.base) + assert_equals(url.origin, expected.origin, "origin") + }, "Origin parsing: <" + expected.input + "> against <" + expected.base + ">") + } +} + +runURLOriginTests() +/* eslint-enable */ diff --git a/test/parallel/test-whatwg-url-parsing.js b/test/parallel/test-whatwg-url-parsing.js index f1fd2ae9051533..6775f79746a57d 100644 --- a/test/parallel/test-whatwg-url-parsing.js +++ b/test/parallel/test-whatwg-url-parsing.js @@ -1,7 +1,9 @@ 'use strict'; const common = require('../common'); -const util = require('util'); +const URL = require('url').URL; +const path = require('path'); +const assert = require('assert'); if (!common.hasIntl) { // A handful of the tests fail when ICU is not included. @@ -9,25 +11,9 @@ if (!common.hasIntl) { return; } -const URL = require('url').URL; -const path = require('path'); -const assert = require('assert'); +// Tests below are not from WPT. const tests = require(path.join(common.fixturesDir, 'url-tests.json')); -function verifyURL(url, test) { - if (test.href) assert.strictEqual(url.href, test.href); - if (test.origin) assert.strictEqual(url.origin, test.origin); - if (test.protocol) assert.strictEqual(url.protocol, test.protocol); - if (test.username) assert.strictEqual(url.username, test.username); - if (test.password) assert.strictEqual(url.password, test.password); - if (test.hostname) assert.strictEqual(url.hostname, test.hostname); - if (test.host) assert.strictEqual(url.host, test.host); - if (test.port !== undefined) assert.strictEqual(url.port, test.port); - if (test.pathname) assert.strictEqual(url.pathname, test.pathname); - if (test.search) assert.strictEqual(url.search, test.search); - if (test.hash) assert.strictEqual(url.hash, test.hash); -} - for (const test of tests) { if (typeof test === 'string') continue; @@ -35,167 +21,23 @@ for (const test of tests) { if (test.failure) { assert.throws(() => new URL(test.input, test.base), /^TypeError: Invalid URL$/); - } else { - const url = new URL(test.input, test.base); - verifyURL(url, test); } } -const additional_tests = [ - { - 'url': 'tftp://foobar.com/someconfig;mode=netascii', - 'protocol': 'tftp:', - 'hostname': 'foobar.com', - 'pathname': '/someconfig;mode=netascii' - }, - { - 'url': 'telnet://user:pass@foobar.com:23/', - 'protocol': 'telnet:', - 'username': 'user', - 'password': 'pass', - 'hostname': 'foobar.com', - 'port': '23', - 'pathname': '/' - }, - { - 'url': 'ut2004://10.10.10.10:7777/Index.ut2', - 'protocol': 'ut2004:', - 'hostname': '10.10.10.10', - 'port': '7777', - 'pathname': '/Index.ut2' - }, - { - 'url': 'redis://foo:bar@somehost:6379/0?baz=bam&qux=baz', - 'protocol': 'redis:', - 'username': 'foo', - 'password': 'bar', - 'hostname': 'somehost', - 'port': '6379', - 'pathname': '/0', - 'search': '?baz=bam&qux=baz' - }, - { - 'url': 'rsync://foo@host:911/sup', - 'protocol': 'rsync:', - 'username': 'foo', - 'hostname': 'host', - 'port': '911', - 'pathname': '/sup' - }, - { - 'url': 'git://github.com/foo/bar.git', - 'protocol': 'git:', - 'hostname': 'github.com', - 'pathname': '/foo/bar.git' - }, - { - 'url': 'irc://myserver.com:6999/channel?passwd', - 'protocol': 'irc:', - 'hostname': 'myserver.com', - 'port': '6999', - 'pathname': '/channel', - 'search': '?passwd' - }, - { - 'url': 'dns://fw.example.org:9999/foo.bar.org?type=TXT', - 'protocol': 'dns:', - 'hostname': 'fw.example.org', - 'port': '9999', - 'pathname': '/foo.bar.org', - 'search': '?type=TXT' - }, - { - 'url': 'ldap://localhost:389/ou=People,o=JNDITutorial', - 'protocol': 'ldap:', - 'hostname': 'localhost', - 'port': '389', - 'pathname': '/ou=People,o=JNDITutorial' - }, - { - 'url': 'git+https://github.com/foo/bar', - 'protocol': 'git+https:', - 'hostname': 'github.com', - 'pathname': '/foo/bar' - }, - { - 'url': 'urn:ietf:rfc:2648', - 'protocol': 'urn:', - 'pathname': 'ietf:rfc:2648' - }, - { - 'url': 'tag:joe@example.org,2001:foo/bar', - 'protocol': 'tag:', - 'pathname': 'joe@example.org,2001:foo/bar' - } -]; +const additional_tests = require( + path.join(common.fixturesDir, 'url-tests-additional.js')); for (const test of additional_tests) { const url = new URL(test.url); - verifyURL(url, test); -} - -// test inspect -const allTests = additional_tests.slice(); -for (const test of tests) { - if (test.failure || typeof test === 'string') continue; - allTests.push(test); -} - -for (const test of allTests) { - const url = test.url ? new URL(test.url) : new URL(test.input, test.base); - - for (const showHidden of [true, false]) { - const res = util.inspect(url, { - showHidden - }); - - const lines = res.split('\n'); - - const firstLine = lines[0]; - assert.strictEqual(firstLine, 'URL {'); - - const lastLine = lines[lines.length - 1]; - assert.strictEqual(lastLine, '}'); - - const innerLines = lines.slice(1, lines.length - 1); - const keys = new Set(); - for (const line of innerLines) { - const i = line.indexOf(': '); - const k = line.slice(0, i).trim(); - const v = line.slice(i + 2); - assert.strictEqual(keys.has(k), false, 'duplicate key found: ' + k); - keys.add(k); - - const hidden = new Set([ - 'password', - 'cannot-be-base', - 'special' - ]); - if (showHidden) { - if (!hidden.has(k)) { - assert.strictEqual(v, url[k], k); - continue; - } - - if (k === 'password') { - assert.strictEqual(v, url[k], k); - } - if (k === 'cannot-be-base') { - assert.ok(v.match(/^true$|^false$/), k + ' is Boolean'); - } - if (k === 'special') { - assert.ok(v.match(/^true$|^false$/), k + ' is Boolean'); - } - continue; - } - - // showHidden is false - if (k === 'password') { - assert.strictEqual(v, '--------', k); - continue; - } - assert.strictEqual(hidden.has(k), false, 'no hidden keys: ' + k); - assert.strictEqual(v, url[k], k); - } - } + if (test.href) assert.strictEqual(url.href, test.href); + if (test.origin) assert.strictEqual(url.origin, test.origin); + if (test.protocol) assert.strictEqual(url.protocol, test.protocol); + if (test.username) assert.strictEqual(url.username, test.username); + if (test.password) assert.strictEqual(url.password, test.password); + if (test.hostname) assert.strictEqual(url.hostname, test.hostname); + if (test.host) assert.strictEqual(url.host, test.host); + if (test.port !== undefined) assert.strictEqual(url.port, test.port); + if (test.pathname) assert.strictEqual(url.pathname, test.pathname); + if (test.search) assert.strictEqual(url.search, test.search); + if (test.hash) assert.strictEqual(url.hash, test.hash); } diff --git a/test/parallel/test-whatwg-url-properties.js b/test/parallel/test-whatwg-url-properties.js index b762659fb6eadc..f093791b2de867 100644 --- a/test/parallel/test-whatwg-url-properties.js +++ b/test/parallel/test-whatwg-url-properties.js @@ -2,11 +2,11 @@ 'use strict'; require('../common'); - const URL = require('url').URL; const assert = require('assert'); const urlToOptions = require('internal/url').urlToOptions; +// Tests below are not from WPT. const url = new URL('http://user:pass@foo.bar.com:21/aaa/zzz?l=24#test'); const oldParams = url.searchParams; // for test of [SameObject] diff --git a/test/parallel/test-whatwg-url-searchparams-append.js b/test/parallel/test-whatwg-url-searchparams-append.js index 44f49d20b09526..2e3a33b26307c3 100644 --- a/test/parallel/test-whatwg-url-searchparams-append.js +++ b/test/parallel/test-whatwg-url-searchparams-append.js @@ -1,55 +1,60 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const URLSearchParams = require('url').URLSearchParams; +const { test, assert_equals, assert_true } = common.WPT; -let params; +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/8791bed/url/urlsearchparams-append.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +test(function() { + var params = new URLSearchParams(); + params.append('a', 'b'); + assert_equals(params + '', 'a=b'); + params.append('a', 'b'); + assert_equals(params + '', 'a=b&a=b'); + params.append('a', 'c'); + assert_equals(params + '', 'a=b&a=b&a=c'); +}, 'Append same name'); +test(function() { + var params = new URLSearchParams(); + params.append('', ''); + assert_equals(params + '', '='); + params.append('', ''); + assert_equals(params + '', '=&='); +}, 'Append empty strings'); +test(function() { + var params = new URLSearchParams(); + params.append(null, null); + assert_equals(params + '', 'null=null'); + params.append(null, null); + assert_equals(params + '', 'null=null&null=null'); +}, 'Append null'); +test(function() { + var params = new URLSearchParams(); + params.append('first', 1); + params.append('second', 2); + params.append('third', ''); + params.append('first', 10); + assert_true(params.has('first'), 'Search params object has name "first"'); + assert_equals(params.get('first'), '1', 'Search params object has name "first" with value "1"'); + assert_equals(params.get('second'), '2', 'Search params object has name "second" with value "2"'); + assert_equals(params.get('third'), '', 'Search params object has name "third" with value ""'); + params.append('first', 10); + assert_equals(params.get('first'), '1', 'Search params object has name "first" with value "1"'); +}, 'Append multiple'); +/* eslint-enable */ -// Append same name -params = new URLSearchParams(); -params.append('a', 'b'); -assert.strictEqual(params + '', 'a=b'); -params.append('a', 'b'); -assert.strictEqual(params + '', 'a=b&a=b'); -params.append('a', 'c'); -assert.strictEqual(params + '', 'a=b&a=b&a=c'); - -// Append empty strings -params = new URLSearchParams(); -params.append('', ''); -assert.strictEqual(params + '', '='); -params.append('', ''); -assert.strictEqual(params + '', '=&='); - -// Append null -params = new URLSearchParams(); -params.append(null, null); -assert.strictEqual(params + '', 'null=null'); -params.append(null, null); -assert.strictEqual(params + '', 'null=null&null=null'); - -// Append multiple -params = new URLSearchParams(); -params.append('first', 1); -params.append('second', 2); -params.append('third', ''); -params.append('first', 10); -assert.strictEqual(true, params.has('first'), - 'Search params object has name "first"'); -assert.strictEqual(params.get('first'), '1', - 'Search params object has name "first" with value "1"'); -assert.strictEqual(params.get('second'), '2', - 'Search params object has name "second" with value "2"'); -assert.strictEqual(params.get('third'), '', - 'Search params object has name "third" with value ""'); -params.append('first', 10); -assert.strictEqual(params.get('first'), '1', - 'Search params object has name "first" with value "1"'); - -assert.throws(() => { - params.append.call(undefined); -}, /^TypeError: Value of `this` is not a URLSearchParams$/); -assert.throws(() => { - params.set('a'); -}, /^TypeError: "name" and "value" arguments must be specified$/); +// Tests below are not from WPT. +{ + const params = new URLSearchParams(); + assert.throws(() => { + params.append.call(undefined); + }, /^TypeError: Value of `this` is not a URLSearchParams$/); + assert.throws(() => { + params.set('a'); + }, /^TypeError: "name" and "value" arguments must be specified$/); +} diff --git a/test/parallel/test-whatwg-url-searchparams-constructor.js b/test/parallel/test-whatwg-url-searchparams-constructor.js index 9b7ca1e4e9c54a..4e177ce59ccf20 100644 --- a/test/parallel/test-whatwg-url-searchparams-constructor.js +++ b/test/parallel/test-whatwg-url-searchparams-constructor.js @@ -1,130 +1,196 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const URLSearchParams = require('url').URLSearchParams; +const { + test, assert_equals, assert_true, assert_false +} = common.WPT; -let params; - -// Basic URLSearchParams construction -params = new URLSearchParams(); -assert.strictEqual(params + '', ''); -params = new URLSearchParams(''); -assert.strictEqual(params + '', ''); -params = new URLSearchParams('a=b'); -assert.strictEqual(params + '', 'a=b'); -params = new URLSearchParams(params); -assert.strictEqual(params + '', 'a=b'); - -// URLSearchParams constructor, empty. -assert.throws(() => URLSearchParams(), TypeError, - 'Calling \'URLSearchParams\' without \'new\' should throw.'); -// assert.throws(() => new URLSearchParams(DOMException.prototype), TypeError); -assert.throws(() => { - new URLSearchParams({ - toString() { throw new TypeError('Illegal invocation'); } - }); -}, TypeError); -params = new URLSearchParams(''); -assert.notStrictEqual(params, null, 'constructor returned non-null value.'); -// eslint-disable-next-line no-proto -assert.strictEqual(params.__proto__, URLSearchParams.prototype, - 'expected URLSearchParams.prototype as prototype.'); -params = new URLSearchParams({}); -// assert.strictEqual(params + '', '%5Bobject+Object%5D='); -assert.strictEqual(params + '', '%5Bobject%20Object%5D='); - -// URLSearchParams constructor, string. -params = new URLSearchParams('a=b'); -assert.notStrictEqual(params, null, 'constructor returned non-null value.'); -assert.strictEqual(true, params.has('a'), - 'Search params object has name "a"'); -assert.strictEqual(false, params.has('b'), - 'Search params object has not got name "b"'); -params = new URLSearchParams('a=b&c'); -assert.notStrictEqual(params, null, 'constructor returned non-null value.'); -assert.strictEqual(true, params.has('a'), - 'Search params object has name "a"'); -assert.strictEqual(true, params.has('c'), - 'Search params object has name "c"'); -params = new URLSearchParams('&a&&& &&&&&a+b=& c&m%c3%b8%c3%b8'); -assert.notStrictEqual(params, null, 'constructor returned non-null value.'); -assert.strictEqual(true, params.has('a'), 'Search params object has name "a"'); -assert.strictEqual(true, params.has('a b'), - 'Search params object has name "a b"'); -assert.strictEqual(true, params.has(' '), - 'Search params object has name " "'); -assert.strictEqual(false, params.has('c'), - 'Search params object did not have the name "c"'); -assert.strictEqual(true, params.has(' c'), - 'Search params object has name " c"'); -assert.strictEqual(true, params.has('møø'), - 'Search params object has name "møø"'); - -// URLSearchParams constructor, object. -const seed = new URLSearchParams('a=b&c=d'); -params = new URLSearchParams(seed); -assert.notStrictEqual(params, null, 'constructor returned non-null value.'); -assert.strictEqual(params.get('a'), 'b'); -assert.strictEqual(params.get('c'), 'd'); -assert.strictEqual(false, params.has('d')); -// The name-value pairs are copied when created; later updates -// should not be observable. -seed.append('e', 'f'); -assert.strictEqual(false, params.has('e')); -params.append('g', 'h'); -assert.strictEqual(false, seed.has('g')); - -// Parse + -params = new URLSearchParams('a=b+c'); -assert.strictEqual(params.get('a'), 'b c'); -params = new URLSearchParams('a+b=c'); -assert.strictEqual(params.get('a b'), 'c'); - -// Parse space -params = new URLSearchParams('a=b c'); -assert.strictEqual(params.get('a'), 'b c'); -params = new URLSearchParams('a b=c'); -assert.strictEqual(params.get('a b'), 'c'); - -// Parse %20 -params = new URLSearchParams('a=b%20c'); -assert.strictEqual(params.get('a'), 'b c'); -params = new URLSearchParams('a%20b=c'); -assert.strictEqual(params.get('a b'), 'c'); - -// Parse \0 -params = new URLSearchParams('a=b\0c'); -assert.strictEqual(params.get('a'), 'b\0c'); -params = new URLSearchParams('a\0b=c'); -assert.strictEqual(params.get('a\0b'), 'c'); - -// Parse %00 -params = new URLSearchParams('a=b%00c'); -assert.strictEqual(params.get('a'), 'b\0c'); -params = new URLSearchParams('a%00b=c'); -assert.strictEqual(params.get('a\0b'), 'c'); - -// Parse \u2384 (Unicode Character 'COMPOSITION SYMBOL' (U+2384)) -params = new URLSearchParams('a=b\u2384'); -assert.strictEqual(params.get('a'), 'b\u2384'); -params = new URLSearchParams('a\u2384b=c'); -assert.strictEqual(params.get('a\u2384b'), 'c'); - -// Parse %e2%8e%84 (Unicode Character 'COMPOSITION SYMBOL' (U+2384)) -params = new URLSearchParams('a=b%e2%8e%84'); -assert.strictEqual(params.get('a'), 'b\u2384'); -params = new URLSearchParams('a%e2%8e%84b=c'); -assert.strictEqual(params.get('a\u2384b'), 'c'); - -// Parse \uD83D\uDCA9 (Unicode Character 'PILE OF POO' (U+1F4A9)) -params = new URLSearchParams('a=b\uD83D\uDCA9c'); -assert.strictEqual(params.get('a'), 'b\uD83D\uDCA9c'); -params = new URLSearchParams('a\uD83D\uDCA9b=c'); -assert.strictEqual(params.get('a\uD83D\uDCA9b'), 'c'); - -// Parse %f0%9f%92%a9 (Unicode Character 'PILE OF POO' (U+1F4A9)) -params = new URLSearchParams('a=b%f0%9f%92%a9c'); -assert.strictEqual(params.get('a'), 'b\uD83D\uDCA9c'); -params = new URLSearchParams('a%f0%9f%92%a9b=c'); -assert.strictEqual(params.get('a\uD83D\uDCA9b'), 'c'); +/* eslint-disable */ +var params; // Strict mode fix for WPT. +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/405394a/url/urlsearchparams-constructor.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +test(function() { + var params = new URLSearchParams(); + assert_equals(params + '', ''); + params = new URLSearchParams(''); + assert_equals(params + '', ''); + params = new URLSearchParams('a=b'); + assert_equals(params + '', 'a=b'); + params = new URLSearchParams(params); + assert_equals(params + '', 'a=b'); +}, 'Basic URLSearchParams construction'); + +test(function() { + var params = new URLSearchParams() + assert_equals(params.toString(), "") +}, "URLSearchParams constructor, no arguments") + +// test(() => { +// params = new URLSearchParams(DOMException.prototype); +// assert_equals(params.toString(), "INDEX_SIZE_ERR=1&DOMSTRING_SIZE_ERR=2&HIERARCHY_REQUEST_ERR=3&WRONG_DOCUMENT_ERR=4&INVALID_CHARACTER_ERR=5&NO_DATA_ALLOWED_ERR=6&NO_MODIFICATION_ALLOWED_ERR=7&NOT_FOUND_ERR=8&NOT_SUPPORTED_ERR=9&INUSE_ATTRIBUTE_ERR=10&INVALID_STATE_ERR=11&SYNTAX_ERR=12&INVALID_MODIFICATION_ERR=13&NAMESPACE_ERR=14&INVALID_ACCESS_ERR=15&VALIDATION_ERR=16&TYPE_MISMATCH_ERR=17&SECURITY_ERR=18&NETWORK_ERR=19&ABORT_ERR=20&URL_MISMATCH_ERR=21"A_EXCEEDED_ERR=22&TIMEOUT_ERR=23&INVALID_NODE_TYPE_ERR=24&DATA_CLONE_ERR=25") +// }, "URLSearchParams constructor, DOMException.prototype as argument") + +test(() => { + params = new URLSearchParams(''); + assert_true(params != null, 'constructor returned non-null value.'); + assert_equals(params.__proto__, URLSearchParams.prototype, 'expected URLSearchParams.prototype as prototype.'); +}, "URLSearchParams constructor, empty string as argument") + +// test(() => { +// params = new URLSearchParams({}); +// assert_equals(params + '', ""); +// }, 'URLSearchParams constructor, {} as argument'); + +test(function() { + var params = new URLSearchParams('a=b'); + assert_true(params != null, 'constructor returned non-null value.'); + assert_true(params.has('a'), 'Search params object has name "a"'); + assert_false(params.has('b'), 'Search params object has not got name "b"'); + var params = new URLSearchParams('a=b&c'); + assert_true(params != null, 'constructor returned non-null value.'); + assert_true(params.has('a'), 'Search params object has name "a"'); + assert_true(params.has('c'), 'Search params object has name "c"'); + var params = new URLSearchParams('&a&&& &&&&&a+b=& c&m%c3%b8%c3%b8'); + assert_true(params != null, 'constructor returned non-null value.'); + assert_true(params.has('a'), 'Search params object has name "a"'); + assert_true(params.has('a b'), 'Search params object has name "a b"'); + assert_true(params.has(' '), 'Search params object has name " "'); + assert_false(params.has('c'), 'Search params object did not have the name "c"'); + assert_true(params.has(' c'), 'Search params object has name " c"'); + assert_true(params.has('møø'), 'Search params object has name "møø"'); +}, 'URLSearchParams constructor, string.'); + +test(function() { + var seed = new URLSearchParams('a=b&c=d'); + var params = new URLSearchParams(seed); + assert_true(params != null, 'constructor returned non-null value.'); + assert_equals(params.get('a'), 'b'); + assert_equals(params.get('c'), 'd'); + assert_false(params.has('d')); + // The name-value pairs are copied when created; later updates + // should not be observable. + seed.append('e', 'f'); + assert_false(params.has('e')); + params.append('g', 'h'); + assert_false(seed.has('g')); +}, 'URLSearchParams constructor, object.'); + +test(function() { + var params = new URLSearchParams('a=b+c'); + assert_equals(params.get('a'), 'b c'); + params = new URLSearchParams('a+b=c'); + assert_equals(params.get('a b'), 'c'); +}, 'Parse +'); + +test(function() { + var params = new URLSearchParams('a=b c'); + assert_equals(params.get('a'), 'b c'); + params = new URLSearchParams('a b=c'); + assert_equals(params.get('a b'), 'c'); +}, 'Parse space'); + +test(function() { + var params = new URLSearchParams('a=b%20c'); + assert_equals(params.get('a'), 'b c'); + params = new URLSearchParams('a%20b=c'); + assert_equals(params.get('a b'), 'c'); +}, 'Parse %20'); + +test(function() { + var params = new URLSearchParams('a=b\0c'); + assert_equals(params.get('a'), 'b\0c'); + params = new URLSearchParams('a\0b=c'); + assert_equals(params.get('a\0b'), 'c'); +}, 'Parse \\0'); + +test(function() { + var params = new URLSearchParams('a=b%00c'); + assert_equals(params.get('a'), 'b\0c'); + params = new URLSearchParams('a%00b=c'); + assert_equals(params.get('a\0b'), 'c'); +}, 'Parse %00'); + +test(function() { + var params = new URLSearchParams('a=b\u2384'); + assert_equals(params.get('a'), 'b\u2384'); + params = new URLSearchParams('a\u2384b=c'); + assert_equals(params.get('a\u2384b'), 'c'); +}, 'Parse \u2384'); // Unicode Character 'COMPOSITION SYMBOL' (U+2384) + +test(function() { + var params = new URLSearchParams('a=b%e2%8e%84'); + assert_equals(params.get('a'), 'b\u2384'); + params = new URLSearchParams('a%e2%8e%84b=c'); + assert_equals(params.get('a\u2384b'), 'c'); +}, 'Parse %e2%8e%84'); // Unicode Character 'COMPOSITION SYMBOL' (U+2384) + +test(function() { + var params = new URLSearchParams('a=b\uD83D\uDCA9c'); + assert_equals(params.get('a'), 'b\uD83D\uDCA9c'); + params = new URLSearchParams('a\uD83D\uDCA9b=c'); + assert_equals(params.get('a\uD83D\uDCA9b'), 'c'); +}, 'Parse \uD83D\uDCA9'); // Unicode Character 'PILE OF POO' (U+1F4A9) + +test(function() { + var params = new URLSearchParams('a=b%f0%9f%92%a9c'); + assert_equals(params.get('a'), 'b\uD83D\uDCA9c'); + params = new URLSearchParams('a%f0%9f%92%a9b=c'); + assert_equals(params.get('a\uD83D\uDCA9b'), 'c'); +}, 'Parse %f0%9f%92%a9'); // Unicode Character 'PILE OF POO' (U+1F4A9) + +// test(function() { +// var params = new URLSearchParams([]); +// assert_true(params != null, 'constructor returned non-null value.'); +// params = new URLSearchParams([['a', 'b'], ['c', 'd']]); +// assert_equals(params.get("a"), "b"); +// assert_equals(params.get("c"), "d"); +// assert_throws(new TypeError(), function() { new URLSearchParams([[1]]); }); +// assert_throws(new TypeError(), function() { new URLSearchParams([[1,2,3]]); }); +// }, "Constructor with sequence of sequences of strings"); + +// [ +// { "input": {"+": "%C2"}, "output": [[" ", "\uFFFD"]], "name": "object with +" }, +// { "input": {c: "x", a: "?"}, "output": [["c", "x"], ["a", "?"]], "name": "object with two keys" }, +// { "input": [["c", "x"], ["a", "?"]], "output": [["c", "x"], ["a", "?"]], "name": "array with two keys" } +// ].forEach((val) => { +// test(() => { +// let params = new URLSearchParams(val.input), +// i = 0 +// for (let param of params) { +// assert_array_equals(param, val.output[i]) +// i++ +// } +// }, "Construct with " + val.name) +// }) + +// test(() => { +// params = new URLSearchParams() +// params[Symbol.iterator] = function *() { +// yield ["a", "b"] +// } +// let params2 = new URLSearchParams(params) +// assert_equals(params2.get("a"), "b") +// }, "Custom [Symbol.iterator]") +/* eslint-enable */ + +// Tests below are not from WPT. +{ +// assert.throws(() => { +// new URLSearchParams({ +// toString() { throw new TypeError('Illegal invocation'); } +// }); +// }, TypeError); +} + +{ + let params; + // URLSearchParams constructor, undefined and null as argument + params = new URLSearchParams(undefined); + assert.strictEqual(params.toString(), ''); + params = new URLSearchParams(null); + assert.strictEqual(params.toString(), 'null='); +} diff --git a/test/parallel/test-whatwg-url-searchparams-delete.js b/test/parallel/test-whatwg-url-searchparams-delete.js index f39917e8e37712..c6235263f22bad 100644 --- a/test/parallel/test-whatwg-url-searchparams-delete.js +++ b/test/parallel/test-whatwg-url-searchparams-delete.js @@ -1,52 +1,57 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); -const url = require('url'); -const URL = url.URL; -const URLSearchParams = url.URLSearchParams; +const { URL, URLSearchParams } = require('url'); +const { test, assert_equals, assert_true, assert_false } = common.WPT; -let params; +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/8791bed/url/urlsearchparams-delete.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +test(function() { + var params = new URLSearchParams('a=b&c=d'); + params.delete('a'); + assert_equals(params + '', 'c=d'); + params = new URLSearchParams('a=a&b=b&a=a&c=c'); + params.delete('a'); + assert_equals(params + '', 'b=b&c=c'); + params = new URLSearchParams('a=a&=&b=b&c=c'); + params.delete(''); + assert_equals(params + '', 'a=a&b=b&c=c'); + params = new URLSearchParams('a=a&null=null&b=b'); + params.delete(null); + assert_equals(params + '', 'a=a&b=b'); + params = new URLSearchParams('a=a&undefined=undefined&b=b'); + params.delete(undefined); + assert_equals(params + '', 'a=a&b=b'); +}, 'Delete basics'); -// Delete basics -params = new URLSearchParams('a=b&c=d'); -params.delete('a'); -assert.strictEqual(params + '', 'c=d'); -params = new URLSearchParams('a=a&b=b&a=a&c=c'); -params.delete('a'); -assert.strictEqual(params + '', 'b=b&c=c'); -params = new URLSearchParams('a=a&=&b=b&c=c'); -params.delete(''); -assert.strictEqual(params + '', 'a=a&b=b&c=c'); -params = new URLSearchParams('a=a&null=null&b=b'); -params.delete(null); -assert.strictEqual(params + '', 'a=a&b=b'); -params = new URLSearchParams('a=a&undefined=undefined&b=b'); -params.delete(undefined); -assert.strictEqual(params + '', 'a=a&b=b'); +test(function() { + var params = new URLSearchParams(); + params.append('first', 1); + assert_true(params.has('first'), 'Search params object has name "first"'); + assert_equals(params.get('first'), '1', 'Search params object has name "first" with value "1"'); + params.delete('first'); + assert_false(params.has('first'), 'Search params object has no "first" name'); + params.append('first', 1); + params.append('first', 10); + params.delete('first'); + assert_false(params.has('first'), 'Search params object has no "first" name'); +}, 'Deleting appended multiple'); +/* eslint-enable */ -// Deleting appended multiple -params = new URLSearchParams(); -params.append('first', 1); -assert.strictEqual(true, params.has('first'), - 'Search params object has name "first"'); -assert.strictEqual(params.get('first'), '1', - 'Search params object has name "first" with value "1"'); -params.delete('first'); -assert.strictEqual(false, params.has('first'), - 'Search params object has no "first" name'); -params.append('first', 1); -params.append('first', 10); -params.delete('first'); -assert.strictEqual(false, params.has('first'), - 'Search params object has no "first" name'); - -assert.throws(() => { - params.delete.call(undefined); -}, /^TypeError: Value of `this` is not a URLSearchParams$/); -assert.throws(() => { - params.delete(); -}, /^TypeError: "name" argument must be specified$/); +// Tests below are not from WPT. +{ + const params = new URLSearchParams(); + assert.throws(() => { + params.delete.call(undefined); + }, /^TypeError: Value of `this` is not a URLSearchParams$/); + assert.throws(() => { + params.delete(); + }, /^TypeError: "name" argument must be specified$/); +} // https://github.com/nodejs/node/issues/10480 // Emptying searchParams should correctly update url's query diff --git a/test/parallel/test-whatwg-url-searchparams-entries.js b/test/parallel/test-whatwg-url-searchparams-entries.js index 97f60ceb17fa29..c8b8d129b01ad9 100644 --- a/test/parallel/test-whatwg-url-searchparams-entries.js +++ b/test/parallel/test-whatwg-url-searchparams-entries.js @@ -4,6 +4,7 @@ require('../common'); const assert = require('assert'); const URLSearchParams = require('url').URLSearchParams; +// Tests below are not from WPT. const params = new URLSearchParams('a=b&c=d'); const entries = params.entries(); assert.strictEqual(typeof entries[Symbol.iterator], 'function'); diff --git a/test/parallel/test-whatwg-url-searchparams-foreach.js b/test/parallel/test-whatwg-url-searchparams-foreach.js index 6adbb5789b0c11..9181371ae51c89 100644 --- a/test/parallel/test-whatwg-url-searchparams-foreach.js +++ b/test/parallel/test-whatwg-url-searchparams-foreach.js @@ -2,42 +2,53 @@ const common = require('../common'); const assert = require('assert'); -const url = require('url'); -const URL = url.URL; -const URLSearchParams = url.URLSearchParams; +const { URL, URLSearchParams } = require('url'); +const { test, assert_array_equals, assert_unreached } = common.WPT; -let a, b, i; +/* eslint-disable */ +var i; // Strict mode fix for WPT. +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/a8b2b1e/url/urlsearchparams-foreach.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +test(function() { + var params = new URLSearchParams('a=1&b=2&c=3'); + var keys = []; + var values = []; + params.forEach(function(value, key) { + keys.push(key); + values.push(value); + }); + assert_array_equals(keys, ['a', 'b', 'c']); + assert_array_equals(values, ['1', '2', '3']); +}, "ForEach Check"); -// ForEach Check -const params = new URLSearchParams('a=1&b=2&c=3'); -const keys = []; -const values = []; -params.forEach((value, key) => { - keys.push(key); - values.push(value); -}); -assert.deepStrictEqual(keys, ['a', 'b', 'c']); -assert.deepStrictEqual(values, ['1', '2', '3']); +test(function() { + let a = new URL("http://a.b/c?a=1&b=2&c=3&d=4"); + let b = a.searchParams; + var c = []; + for (i of b) { + a.search = "x=1&y=2&z=3"; + c.push(i); + } + assert_array_equals(c[0], ["a","1"]); + assert_array_equals(c[1], ["y","2"]); + assert_array_equals(c[2], ["z","3"]); +}, "For-of Check"); -// For-of Check -a = new URL('http://a.b/c?a=1&b=2&c=3&d=4'); -b = a.searchParams; -const c = []; -for (i of b) { - a.search = 'x=1&y=2&z=3'; - c.push(i); -} -assert.deepStrictEqual(c[0], ['a', '1']); -assert.deepStrictEqual(c[1], ['y', '2']); -assert.deepStrictEqual(c[2], ['z', '3']); +test(function() { + let a = new URL("http://a.b/c"); + let b = a.searchParams; + for (i of b) { + assert_unreached(i); + } +}, "empty"); +/* eslint-enable */ -// empty -a = new URL('http://a.b/c'); -b = a.searchParams; -for (i of b) { - common.fail('should not be reached'); +// Tests below are not from WPT. +{ + const params = new URLSearchParams(); + assert.throws(() => { + params.forEach.call(undefined); + }, /^TypeError: Value of `this` is not a URLSearchParams$/); } - -assert.throws(() => { - params.forEach.call(undefined); -}, /^TypeError: Value of `this` is not a URLSearchParams$/); diff --git a/test/parallel/test-whatwg-url-searchparams-get.js b/test/parallel/test-whatwg-url-searchparams-get.js index 95c3f47df5eabb..3a46993214a997 100644 --- a/test/parallel/test-whatwg-url-searchparams-get.js +++ b/test/parallel/test-whatwg-url-searchparams-get.js @@ -1,38 +1,45 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const URLSearchParams = require('url').URLSearchParams; +const { test, assert_equals, assert_true } = common.WPT; -let params; +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/8791bed/url/urlsearchparams-get.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +test(function() { + var params = new URLSearchParams('a=b&c=d'); + assert_equals(params.get('a'), 'b'); + assert_equals(params.get('c'), 'd'); + assert_equals(params.get('e'), null); + params = new URLSearchParams('a=b&c=d&a=e'); + assert_equals(params.get('a'), 'b'); + params = new URLSearchParams('=b&c=d'); + assert_equals(params.get(''), 'b'); + params = new URLSearchParams('a=&c=d&a=e'); + assert_equals(params.get('a'), ''); +}, 'Get basics'); -// Get basics -params = new URLSearchParams('a=b&c=d'); -assert.strictEqual(params.get('a'), 'b'); -assert.strictEqual(params.get('c'), 'd'); -assert.strictEqual(params.get('e'), null); -params = new URLSearchParams('a=b&c=d&a=e'); -assert.strictEqual(params.get('a'), 'b'); -params = new URLSearchParams('=b&c=d'); -assert.strictEqual(params.get(''), 'b'); -params = new URLSearchParams('a=&c=d&a=e'); -assert.strictEqual(params.get('a'), ''); +test(function() { + var params = new URLSearchParams('first=second&third&&'); + assert_true(params != null, 'constructor returned non-null value.'); + assert_true(params.has('first'), 'Search params object has name "first"'); + assert_equals(params.get('first'), 'second', 'Search params object has name "first" with value "second"'); + assert_equals(params.get('third'), '', 'Search params object has name "third" with the empty value.'); + assert_equals(params.get('fourth'), null, 'Search params object has no "fourth" name and value.'); +}, 'More get() basics'); +/* eslint-enable */ -// More get() basics -params = new URLSearchParams('first=second&third&&'); -assert.notStrictEqual(params, null, 'constructor returned non-null value.'); -assert.strictEqual(true, params.has('first'), - 'Search params object has name "first"'); -assert.strictEqual(params.get('first'), 'second', - 'Search params object has name "first" with value "second"'); -assert.strictEqual(params.get('third'), '', - 'Search params object has name "third" with empty value.'); -assert.strictEqual(params.get('fourth'), null, - 'Search params object has no "fourth" name and value.'); - -assert.throws(() => { - params.get.call(undefined); -}, /^TypeError: Value of `this` is not a URLSearchParams$/); -assert.throws(() => { - params.get(); -}, /^TypeError: "name" argument must be specified$/); +// Tests below are not from WPT. +{ + const params = new URLSearchParams(); + assert.throws(() => { + params.get.call(undefined); + }, /^TypeError: Value of `this` is not a URLSearchParams$/); + assert.throws(() => { + params.get(); + }, /^TypeError: "name" argument must be specified$/); +} diff --git a/test/parallel/test-whatwg-url-searchparams-getall.js b/test/parallel/test-whatwg-url-searchparams-getall.js index 52f581c0158a90..df055e009e7e4d 100644 --- a/test/parallel/test-whatwg-url-searchparams-getall.js +++ b/test/parallel/test-whatwg-url-searchparams-getall.js @@ -1,45 +1,49 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const URLSearchParams = require('url').URLSearchParams; +const { test, assert_equals, assert_true, assert_array_equals } = common.WPT; -let params; -let matches; +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/8791bed/url/urlsearchparams-getall.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +test(function() { + var params = new URLSearchParams('a=b&c=d'); + assert_array_equals(params.getAll('a'), ['b']); + assert_array_equals(params.getAll('c'), ['d']); + assert_array_equals(params.getAll('e'), []); + params = new URLSearchParams('a=b&c=d&a=e'); + assert_array_equals(params.getAll('a'), ['b', 'e']); + params = new URLSearchParams('=b&c=d'); + assert_array_equals(params.getAll(''), ['b']); + params = new URLSearchParams('a=&c=d&a=e'); + assert_array_equals(params.getAll('a'), ['', 'e']); +}, 'getAll() basics'); -// getAll() basics -params = new URLSearchParams('a=b&c=d'); -assert.deepStrictEqual(params.getAll('a'), ['b']); -assert.deepStrictEqual(params.getAll('c'), ['d']); -assert.deepStrictEqual(params.getAll('e'), []); -params = new URLSearchParams('a=b&c=d&a=e'); -assert.deepStrictEqual(params.getAll('a'), ['b', 'e']); -params = new URLSearchParams('=b&c=d'); -assert.deepStrictEqual(params.getAll(''), ['b']); -params = new URLSearchParams('a=&c=d&a=e'); -assert.deepStrictEqual(params.getAll('a'), ['', 'e']); +test(function() { + var params = new URLSearchParams('a=1&a=2&a=3&a'); + assert_true(params.has('a'), 'Search params object has name "a"'); + var matches = params.getAll('a'); + assert_true(matches && matches.length == 4, 'Search params object has values for name "a"'); + assert_array_equals(matches, ['1', '2', '3', ''], 'Search params object has expected name "a" values'); + params.set('a', 'one'); + assert_equals(params.get('a'), 'one', 'Search params object has name "a" with value "one"'); + var matches = params.getAll('a'); + assert_true(matches && matches.length == 1, 'Search params object has values for name "a"'); + assert_array_equals(matches, ['one'], 'Search params object has expected name "a" values'); +}, 'getAll() multiples'); +/* eslint-enable */ -// getAll() multiples -params = new URLSearchParams('a=1&a=2&a=3&a'); -assert.strictEqual(true, params.has('a'), - 'Search params object has name "a"'); -matches = params.getAll('a'); -assert(matches && matches.length == 4, - 'Search params object has values for name "a"'); -assert.deepStrictEqual(matches, ['1', '2', '3', ''], - 'Search params object has expected name "a" values'); -params.set('a', 'one'); -assert.strictEqual(params.get('a'), 'one', - 'Search params object has name "a" with value "one"'); -matches = params.getAll('a'); -assert(matches && matches.length == 1, - 'Search params object has values for name "a"'); -assert.deepStrictEqual(matches, ['one'], - 'Search params object has expected name "a" values'); - -assert.throws(() => { - params.getAll.call(undefined); -}, /^TypeError: Value of `this` is not a URLSearchParams$/); -assert.throws(() => { - params.getAll(); -}, /^TypeError: "name" argument must be specified$/); +// Tests below are not from WPT. +{ + const params = new URLSearchParams(); + assert.throws(() => { + params.getAll.call(undefined); + }, /^TypeError: Value of `this` is not a URLSearchParams$/); + assert.throws(() => { + params.getAll(); + }, /^TypeError: "name" argument must be specified$/); +} diff --git a/test/parallel/test-whatwg-url-searchparams-has.js b/test/parallel/test-whatwg-url-searchparams-has.js index bab34515d99ac2..1be9cf6121593e 100644 --- a/test/parallel/test-whatwg-url-searchparams-has.js +++ b/test/parallel/test-whatwg-url-searchparams-has.js @@ -1,42 +1,48 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const URLSearchParams = require('url').URLSearchParams; +const { test, assert_false, assert_true } = common.WPT; -let params; +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/8791bed/url/urlsearchparams-has.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +test(function() { + var params = new URLSearchParams('a=b&c=d'); + assert_true(params.has('a')); + assert_true(params.has('c')); + assert_false(params.has('e')); + params = new URLSearchParams('a=b&c=d&a=e'); + assert_true(params.has('a')); + params = new URLSearchParams('=b&c=d'); + assert_true(params.has('')); + params = new URLSearchParams('null=a'); + assert_true(params.has(null)); +}, 'Has basics'); -// Has basics -params = new URLSearchParams('a=b&c=d'); -assert.strictEqual(true, params.has('a')); -assert.strictEqual(true, params.has('c')); -assert.strictEqual(false, params.has('e')); -params = new URLSearchParams('a=b&c=d&a=e'); -assert.strictEqual(true, params.has('a')); -params = new URLSearchParams('=b&c=d'); -assert.strictEqual(true, params.has('')); -params = new URLSearchParams('null=a'); -assert.strictEqual(true, params.has(null)); +test(function() { + var params = new URLSearchParams('a=b&c=d&&'); + params.append('first', 1); + params.append('first', 2); + assert_true(params.has('a'), 'Search params object has name "a"'); + assert_true(params.has('c'), 'Search params object has name "c"'); + assert_true(params.has('first'), 'Search params object has name "first"'); + assert_false(params.has('d'), 'Search params object has no name "d"'); + params.delete('first'); + assert_false(params.has('first'), 'Search params object has no name "first"'); +}, 'has() following delete()'); +/* eslint-enable */ -// has() following delete() -params = new URLSearchParams('a=b&c=d&&'); -params.append('first', 1); -params.append('first', 2); -assert.strictEqual(true, params.has('a'), - 'Search params object has name "a"'); -assert.strictEqual(true, params.has('c'), - 'Search params object has name "c"'); -assert.strictEqual(true, params.has('first'), - 'Search params object has name "first"'); -assert.strictEqual(false, params.has('d'), - 'Search params object has no name "d"'); -params.delete('first'); -assert.strictEqual(false, params.has('first'), - 'Search params object has no name "first"'); - -assert.throws(() => { - params.has.call(undefined); -}, /^TypeError: Value of `this` is not a URLSearchParams$/); -assert.throws(() => { - params.has(); -}, /^TypeError: "name" argument must be specified$/); +// Tests below are not from WPT. +{ + const params = new URLSearchParams(); + assert.throws(() => { + params.has.call(undefined); + }, /^TypeError: Value of `this` is not a URLSearchParams$/); + assert.throws(() => { + params.has(); + }, /^TypeError: "name" argument must be specified$/); +} diff --git a/test/parallel/test-whatwg-url-searchparams-inspect.js b/test/parallel/test-whatwg-url-searchparams-inspect.js index 12472e1df0601a..768ec5aa390f06 100644 --- a/test/parallel/test-whatwg-url-searchparams-inspect.js +++ b/test/parallel/test-whatwg-url-searchparams-inspect.js @@ -3,12 +3,9 @@ require('../common'); const assert = require('assert'); const util = require('util'); -const URL = require('url').URL; - -// Until we export URLSearchParams -const m = new URL('http://example.org'); -const URLSearchParams = m.searchParams.constructor; +const URLSearchParams = require('url').URLSearchParams; +// Tests below are not from WPT. const sp = new URLSearchParams('?a=a&b=b&b=c'); assert.strictEqual(util.inspect(sp), "URLSearchParams { 'a' => 'a', 'b' => 'b', 'b' => 'c' }"); diff --git a/test/parallel/test-whatwg-url-searchparams-keys.js b/test/parallel/test-whatwg-url-searchparams-keys.js index d538422654065c..6942b152cd78e8 100644 --- a/test/parallel/test-whatwg-url-searchparams-keys.js +++ b/test/parallel/test-whatwg-url-searchparams-keys.js @@ -4,6 +4,7 @@ require('../common'); const assert = require('assert'); const URLSearchParams = require('url').URLSearchParams; +// Tests below are not from WPT. const params = new URLSearchParams('a=b&c=d'); const keys = params.keys(); diff --git a/test/parallel/test-whatwg-url-searchparams-set.js b/test/parallel/test-whatwg-url-searchparams-set.js index c818cc9f71af48..e78ce4763158b5 100644 --- a/test/parallel/test-whatwg-url-searchparams-set.js +++ b/test/parallel/test-whatwg-url-searchparams-set.js @@ -1,41 +1,46 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const URLSearchParams = require('url').URLSearchParams; +const { test, assert_equals, assert_true } = common.WPT; -let params; +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/8791bed/url/urlsearchparams-set.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +test(function() { + var params = new URLSearchParams('a=b&c=d'); + params.set('a', 'B'); + assert_equals(params + '', 'a=B&c=d'); + params = new URLSearchParams('a=b&c=d&a=e'); + params.set('a', 'B'); + assert_equals(params + '', 'a=B&c=d') + params.set('e', 'f'); + assert_equals(params + '', 'a=B&c=d&e=f') +}, 'Set basics'); -// Set basics -params = new URLSearchParams('a=b&c=d'); -params.set('a', 'B'); -assert.strictEqual(params + '', 'a=B&c=d'); -params = new URLSearchParams('a=b&c=d&a=e'); -params.set('a', 'B'); -assert.strictEqual(params + '', 'a=B&c=d'); -params.set('e', 'f'); -assert.strictEqual(params + '', 'a=B&c=d&e=f'); +test(function() { + var params = new URLSearchParams('a=1&a=2&a=3'); + assert_true(params.has('a'), 'Search params object has name "a"'); + assert_equals(params.get('a'), '1', 'Search params object has name "a" with value "1"'); + params.set('first', 4); + assert_true(params.has('a'), 'Search params object has name "a"'); + assert_equals(params.get('a'), '1', 'Search params object has name "a" with value "1"'); + params.set('a', 4); + assert_true(params.has('a'), 'Search params object has name "a"'); + assert_equals(params.get('a'), '4', 'Search params object has name "a" with value "4"'); +}, 'URLSearchParams.set'); +/* eslint-enable */ -// URLSearchParams.set -params = new URLSearchParams('a=1&a=2&a=3'); -assert.strictEqual(true, params.has('a'), - 'Search params object has name "a"'); -assert.strictEqual(params.get('a'), '1', - 'Search params object has name "a" with value "1"'); -params.set('first', 4); -assert.strictEqual(true, params.has('a'), - 'Search params object has name "a"'); -assert.strictEqual(params.get('a'), '1', - 'Search params object has name "a" with value "1"'); -params.set('a', 4); -assert.strictEqual(true, params.has('a'), - 'Search params object has name "a"'); -assert.strictEqual(params.get('a'), '4', - 'Search params object has name "a" with value "4"'); - -assert.throws(() => { - params.set.call(undefined); -}, /^TypeError: Value of `this` is not a URLSearchParams$/); -assert.throws(() => { - params.set('a'); -}, /^TypeError: "name" and "value" arguments must be specified$/); +// Tests below are not from WPT. +{ + const params = new URLSearchParams(); + assert.throws(() => { + params.set.call(undefined); + }, /^TypeError: Value of `this` is not a URLSearchParams$/); + assert.throws(() => { + params.set('a'); + }, /^TypeError: "name" and "value" arguments must be specified$/); +} diff --git a/test/parallel/test-whatwg-url-searchparams-stringifier.js b/test/parallel/test-whatwg-url-searchparams-stringifier.js index ba3f42683b46e6..7e85b9726167ad 100644 --- a/test/parallel/test-whatwg-url-searchparams-stringifier.js +++ b/test/parallel/test-whatwg-url-searchparams-stringifier.js @@ -1,115 +1,131 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const URLSearchParams = require('url').URLSearchParams; - -let params; - -// Serialize space -// querystring does not currently handle spaces intelligently -// params = new URLSearchParams(); -// params.append('a', 'b c'); -// assert.strictEqual(params + '', 'a=b+c'); -// params.delete('a'); -// params.append('a b', 'c'); -// assert.strictEqual(params + '', 'a+b=c'); - -// Serialize empty value -params = new URLSearchParams(); -params.append('a', ''); -assert.strictEqual(params + '', 'a='); -params.append('a', ''); -assert.strictEqual(params + '', 'a=&a='); -params.append('', 'b'); -assert.strictEqual(params + '', 'a=&a=&=b'); -params.append('', ''); -assert.strictEqual(params + '', 'a=&a=&=b&='); -params.append('', ''); -assert.strictEqual(params + '', 'a=&a=&=b&=&='); - -// Serialize empty name -params = new URLSearchParams(); -params.append('', 'b'); -assert.strictEqual(params + '', '=b'); -params.append('', 'b'); -assert.strictEqual(params + '', '=b&=b'); - -// Serialize empty name and value -params = new URLSearchParams(); -params.append('', ''); -assert.strictEqual(params + '', '='); -params.append('', ''); -assert.strictEqual(params + '', '=&='); - -// Serialize + -params = new URLSearchParams(); -params.append('a', 'b+c'); -assert.strictEqual(params + '', 'a=b%2Bc'); -params.delete('a'); -params.append('a+b', 'c'); -assert.strictEqual(params + '', 'a%2Bb=c'); - -// Serialize = -params = new URLSearchParams(); -params.append('=', 'a'); -assert.strictEqual(params + '', '%3D=a'); -params.append('b', '='); -assert.strictEqual(params + '', '%3D=a&b=%3D'); - -// Serialize & -params = new URLSearchParams(); -params.append('&', 'a'); -assert.strictEqual(params + '', '%26=a'); -params.append('b', '&'); -assert.strictEqual(params + '', '%26=a&b=%26'); - -// Serialize *-._ -params = new URLSearchParams(); -params.append('a', '*-._'); -assert.strictEqual(params + '', 'a=*-._'); -params.delete('a'); -params.append('*-._', 'c'); -assert.strictEqual(params + '', '*-._=c'); - -// Serialize % -params = new URLSearchParams(); -params.append('a', 'b%c'); -assert.strictEqual(params + '', 'a=b%25c'); -params.delete('a'); -params.append('a%b', 'c'); -assert.strictEqual(params + '', 'a%25b=c'); - -// Serialize \\0 -params = new URLSearchParams(); -params.append('a', 'b\0c'); -assert.strictEqual(params + '', 'a=b%00c'); -params.delete('a'); -params.append('a\0b', 'c'); -assert.strictEqual(params + '', 'a%00b=c'); - -// Serialize \uD83D\uDCA9 -// Unicode Character 'PILE OF POO' (U+1F4A9) -params = new URLSearchParams(); -params.append('a', 'b\uD83D\uDCA9c'); -assert.strictEqual(params + '', 'a=b%F0%9F%92%A9c'); -params.delete('a'); -params.append('a\uD83D\uDCA9b', 'c'); -assert.strictEqual(params + '', 'a%F0%9F%92%A9b=c'); - -// URLSearchParams.toString - -// querystring parses `&&` as {'': ''} -// params = new URLSearchParams('a=b&c=d&&e&&'); -// assert.strictEqual(params.toString(), 'a=b&c=d&e='); - -// querystring does not currently handle spaces intelligently -// params = new URLSearchParams('a = b &a=b&c=d%20'); -// assert.strictEqual(params.toString(), 'a+=+b+&a=b&c=d+'); - -// The lone '=' _does_ survive the roundtrip. -params = new URLSearchParams('a=&a=b'); -assert.strictEqual(params.toString(), 'a=&a=b'); -assert.throws(() => { - params.toString.call(undefined); -}, /^TypeError: Value of `this` is not a URLSearchParams$/); +const { test, assert_equals } = common.WPT; + +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/8791bed/url/urlsearchparams-stringifier.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +// test(function() { +// var params = new URLSearchParams(); +// params.append('a', 'b c'); +// assert_equals(params + '', 'a=b+c'); +// params.delete('a'); +// params.append('a b', 'c'); +// assert_equals(params + '', 'a+b=c'); +// }, 'Serialize space'); + +test(function() { + var params = new URLSearchParams(); + params.append('a', ''); + assert_equals(params + '', 'a='); + params.append('a', ''); + assert_equals(params + '', 'a=&a='); + params.append('', 'b'); + assert_equals(params + '', 'a=&a=&=b'); + params.append('', ''); + assert_equals(params + '', 'a=&a=&=b&='); + params.append('', ''); + assert_equals(params + '', 'a=&a=&=b&=&='); +}, 'Serialize empty value'); + +test(function() { + var params = new URLSearchParams(); + params.append('', 'b'); + assert_equals(params + '', '=b'); + params.append('', 'b'); + assert_equals(params + '', '=b&=b'); +}, 'Serialize empty name'); + +test(function() { + var params = new URLSearchParams(); + params.append('', ''); + assert_equals(params + '', '='); + params.append('', ''); + assert_equals(params + '', '=&='); +}, 'Serialize empty name and value'); + +test(function() { + var params = new URLSearchParams(); + params.append('a', 'b+c'); + assert_equals(params + '', 'a=b%2Bc'); + params.delete('a'); + params.append('a+b', 'c'); + assert_equals(params + '', 'a%2Bb=c'); +}, 'Serialize +'); + +test(function() { + var params = new URLSearchParams(); + params.append('=', 'a'); + assert_equals(params + '', '%3D=a'); + params.append('b', '='); + assert_equals(params + '', '%3D=a&b=%3D'); +}, 'Serialize ='); + +test(function() { + var params = new URLSearchParams(); + params.append('&', 'a'); + assert_equals(params + '', '%26=a'); + params.append('b', '&'); + assert_equals(params + '', '%26=a&b=%26'); +}, 'Serialize &'); + +test(function() { + var params = new URLSearchParams(); + params.append('a', '*-._'); + assert_equals(params + '', 'a=*-._'); + params.delete('a'); + params.append('*-._', 'c'); + assert_equals(params + '', '*-._=c'); +}, 'Serialize *-._'); + +test(function() { + var params = new URLSearchParams(); + params.append('a', 'b%c'); + assert_equals(params + '', 'a=b%25c'); + params.delete('a'); + params.append('a%b', 'c'); + assert_equals(params + '', 'a%25b=c'); +}, 'Serialize %'); + +test(function() { + var params = new URLSearchParams(); + params.append('a', 'b\0c'); + assert_equals(params + '', 'a=b%00c'); + params.delete('a'); + params.append('a\0b', 'c'); + assert_equals(params + '', 'a%00b=c'); +}, 'Serialize \\0'); + +test(function() { + var params = new URLSearchParams(); + params.append('a', 'b\uD83D\uDCA9c'); + assert_equals(params + '', 'a=b%F0%9F%92%A9c'); + params.delete('a'); + params.append('a\uD83D\uDCA9b', 'c'); + assert_equals(params + '', 'a%F0%9F%92%A9b=c'); +}, 'Serialize \uD83D\uDCA9'); // Unicode Character 'PILE OF POO' (U+1F4A9) + +test(function() { + var params; + // params = new URLSearchParams('a=b&c=d&&e&&'); + // assert_equals(params.toString(), 'a=b&c=d&e='); + // params = new URLSearchParams('a = b &a=b&c=d%20'); + // assert_equals(params.toString(), 'a+=+b+&a=b&c=d+'); + // The lone '=' _does_ survive the roundtrip. + params = new URLSearchParams('a=&a=b'); + assert_equals(params.toString(), 'a=&a=b'); +}, 'URLSearchParams.toString'); +/* eslint-enable */ + +// Tests below are not from WPT. +{ + const params = new URLSearchParams(); + assert.throws(() => { + params.toString.call(undefined); + }, /^TypeError: Value of `this` is not a URLSearchParams$/); +} diff --git a/test/parallel/test-whatwg-url-searchparams-values.js b/test/parallel/test-whatwg-url-searchparams-values.js index 36aa1da9f057bb..eb6fa05daf3496 100644 --- a/test/parallel/test-whatwg-url-searchparams-values.js +++ b/test/parallel/test-whatwg-url-searchparams-values.js @@ -4,6 +4,7 @@ require('../common'); const assert = require('assert'); const URLSearchParams = require('url').URLSearchParams; +// Tests below are not from WPT. const params = new URLSearchParams('a=b&c=d'); const values = params.values(); diff --git a/test/parallel/test-whatwg-url-searchparams.js b/test/parallel/test-whatwg-url-searchparams.js index b3885a48be91e7..d855ccee841851 100644 --- a/test/parallel/test-whatwg-url-searchparams.js +++ b/test/parallel/test-whatwg-url-searchparams.js @@ -4,6 +4,7 @@ require('../common'); const assert = require('assert'); const URL = require('url').URL; +// Tests below are not from WPT. const serialized = 'a=a&a=1&a=true&a=undefined&a=null&a=%5Bobject%20Object%5D'; const values = ['a', 1, true, undefined, null, {}]; diff --git a/test/parallel/test-whatwg-url-setters.js b/test/parallel/test-whatwg-url-setters.js index 8cd9fc51d52ae8..409ed1bd00d36c 100644 --- a/test/parallel/test-whatwg-url-setters.js +++ b/test/parallel/test-whatwg-url-setters.js @@ -1,6 +1,9 @@ 'use strict'; const common = require('../common'); +const path = require('path'); +const URL = require('url').URL; +const { test, assert_equals } = common.WPT; if (!common.hasIntl) { // A handful of the tests fail when ICU is not included. @@ -8,25 +11,68 @@ if (!common.hasIntl) { return; } -const path = require('path'); -const URL = require('url').URL; -const assert = require('assert'); -const attrs = require(path.join(common.fixturesDir, 'url-setter-tests.json')); +const request = { + response: require(path.join(common.fixturesDir, 'url-setter-tests.json')) +}; -for (const attr in attrs) { - if (attr === 'comment') - continue; - const tests = attrs[attr]; - let n = 0; - for (const test of tests) { - if (test.skip) continue; - n++; - const url = new URL(test.href); - url[attr] = test.new_value; - for (const test_attr in test.expected) { - assert.strictEqual(test.expected[test_attr], url[test_attr], - `${n} ${attr} ${test_attr} ` + - `${test.href} ${test.comment}`); +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/8791bed/url/url-setters.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +function startURLSettersTests() { +// var setup = async_test("Loading data…") +// setup.step(function() { +// var request = new XMLHttpRequest() +// request.open("GET", "setters_tests.json") +// request.send() +// request.responseType = "json" +// request.onload = setup.step_func(function() { + runURLSettersTests(request.response) +// setup.done() +// }) +// }) +} + +function runURLSettersTests(all_test_cases) { + for (var attribute_to_be_set in all_test_cases) { + if (attribute_to_be_set == "comment") { + continue; + } + var test_cases = all_test_cases[attribute_to_be_set]; + for(var i = 0, l = test_cases.length; i < l; i++) { + var test_case = test_cases[i]; + var name = "Setting <" + test_case.href + ">." + attribute_to_be_set + + " = '" + test_case.new_value + "'"; + if ("comment" in test_case) { + name += " " + test_case.comment; + } + test(function() { + var url = new URL(test_case.href); + url[attribute_to_be_set] = test_case.new_value; + for (var attribute in test_case.expected) { + assert_equals(url[attribute], test_case.expected[attribute]) + } + }, "URL: " + name) + // test(function() { + // var url = document.createElement("a"); + // url.href = test_case.href; + // url[attribute_to_be_set] = test_case.new_value; + // for (var attribute in test_case.expected) { + // assert_equals(url[attribute], test_case.expected[attribute]) + // } + // }, ": " + name) + // test(function() { + // var url = document.createElement("area"); + // url.href = test_case.href; + // url[attribute_to_be_set] = test_case.new_value; + // for (var attribute in test_case.expected) { + // assert_equals(url[attribute], test_case.expected[attribute]) + // } + // }, ": " + name) } } } + +startURLSettersTests() +/* eslint-enable */ diff --git a/test/parallel/test-whatwg-url-tostringtag.js b/test/parallel/test-whatwg-url-tostringtag.js index 83653368a7a4f2..689056fd238dda 100644 --- a/test/parallel/test-whatwg-url-tostringtag.js +++ b/test/parallel/test-whatwg-url-tostringtag.js @@ -3,6 +3,8 @@ require('../common'); const assert = require('assert'); const URL = require('url').URL; + +// Tests below are not from WPT. const toString = Object.prototype.toString; const url = new URL('http://example.org'); From 5a2db157363acb70aa4a33e1e788ff40ebcb4192 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Tue, 24 Jan 2017 12:38:30 -0800 Subject: [PATCH 026/164] doc: add documentation for url.format(URL[, options]); Backport-of: https://github.com/nodejs/node/pull/10857 --- doc/api/url.md | 42 ++++++++++++++++++++++++++++++++++++++++ tools/doc/type-parser.js | 3 ++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/doc/api/url.md b/doc/api/url.md index 50e7433e6110e5..6e3d19ee52d589 100755 --- a/doc/api/url.md +++ b/doc/api/url.md @@ -198,6 +198,47 @@ The formatting process operates as follows: string, an [`Error`][] is thrown. * `result` is returned. +## url.format(URL[, options]) + +> Stability: 1 - Experimental + +* `URL` {URL} A [WHATWG URL][] object +* `options` {Object} + * `auth` {Boolean} `true` if the serialized URL string should include the + username and password, `false` otherwise. Defaults to `true`. + * `fragment` {Boolean} `true` if the serialized URL string should include the + fragment, `false` otherwise. Defaults to `true`. + * `search` {Boolean} `true` if the serialized URL string should include the + search query, `false` otherwise. Defaults to `true`. + * `unicode` (Boolean) `true` if Unicode characters appearing in the host + component of the URL string should be encoded directly as opposed to being + Punycode encoded. Defaults to `false`. + +Returns a customizable serialization of a URL String representation of a +[WHATWG URL][] object. + +The URL object has both a `toString()` method and `href` property that return +string serializations of the URL. These are not, however, customizable in +any way. The `url.format(URL[, options])` method allows for basic customization +of the output. + +For example: + +```js +const myURL = new URL('https://a:b@你好你好?abc#foo'); + +console.log(myURL.href); + // Prints https://a:b@xn--6qqa088eba/?abc#foo + +console.log(myURL.toString()); + // Prints https://a:b@xn--6qqa088eba/?abc#foo + +console.log(url.format(myURL, {fragment: false, unicode: true, auth: false})); + // Prints 'https://你好你好?abc' +``` + +*Note*: This variation of the `url.format()` method is currently considered to +be experimental. ## url.parse(urlString[, parseQueryString[, slashesDenoteHost]]) @@ -305,4 +295,5 @@ The `console.warn()` function is an alias for [`console.error()`][]. [`util.format()`]: util.html#util_util_format_format_args [`util.inspect()`]: util.html#util_util_inspect_object_options [customizing `util.inspect()` colors]: util.html#util_customizing_util_inspect_colors +[note on process I/O]: process.html#process_a_note_on_process_i_o [web-api-assert]: https://developer.mozilla.org/en-US/docs/Web/API/console/assert diff --git a/doc/api/process.md b/doc/api/process.md index 2a413c98c1584e..dd449172ed416e 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -850,10 +850,11 @@ added: v0.1.13 * `code` {Integer} The exit code. Defaults to `0`. -The `process.exit()` method instructs Node.js to terminate the process as -quickly as possible with the specified exit `code`. If the `code` is omitted, -exit uses either the 'success' code `0` or the value of `process.exitCode` if -specified. +The `process.exit()` method instructs Node.js to terminate the process +synchronously with an exit status of `code`. If `code` is omitted, exit uses +either the 'success' code `0` or the value of `process.exitCode` if it has been +set. Node.js will not terminate until all the [`'exit'`] event listeners are +called. To exit with a 'failure' code: @@ -886,7 +887,7 @@ if (someConditionNotMet()) { ``` The reason this is problematic is because writes to `process.stdout` in Node.js -are sometimes *non-blocking* and may occur over multiple ticks of the Node.js +are sometimes *asynchronous* and may occur over multiple ticks of the Node.js event loop. Calling `process.exit()`, however, forces the process to exit *before* those additional writes to `stdout` can be performed. @@ -1475,23 +1476,11 @@ Android) * {Stream} -The `process.stderr` property returns a [Writable][] stream equivalent to or -associated with `stderr` (fd `2`). +The `process.stderr` property returns a [Writable][] stream connected to +`stderr` (fd `2`). -Note: `process.stderr` and `process.stdout` differ from other Node.js streams -in several ways: -1. They cannot be closed ([`end()`][] will throw). -2. They never emit the [`'finish'`][] event. -3. Writes _can_ block when output is redirected to a file. - - Note that disks are fast and operating systems normally employ write-back - caching so this is very uncommon. -4. Writes on UNIX **will** block by default if output is going to a TTY - (a terminal). -5. Windows functionality differs. Writes block except when output is going to a - TTY. - -To check if Node.js is being run in a TTY context, read the `isTTY` property -on `process.stderr`, `process.stdout`, or `process.stdin`: +Note: `process.stderr` differs from other Node.js streams in important ways, +see [note on process I/O][] for more information. ## process.stdin @@ -1529,40 +1518,52 @@ must call `process.stdin.resume()` to read from it. Note also that calling * {Stream} -The `process.stdout` property returns a [Writable][] stream equivalent to or -associated with `stdout` (fd `1`). +The `process.stdout` property returns a [Writable][] stream connected to +`stdout` (fd `2`). -For example: +For example, to copy process.stdin to process.stdout: ```js -console.log = (msg) => { - process.stdout.write(`${msg}\n`); -}; +process.stdin.pipe(process.stdout); ``` -Note: `process.stderr` and `process.stdout` differ from other Node.js streams -in several ways: -1. They cannot be closed ([`end()`][] will throw). -2. They never emit the [`'finish'`][] event. -3. Writes _can_ block when output is redirected to a file. - - Note that disks are fast and operating systems normally employ write-back - caching so this is very uncommon. -4. Writes on UNIX **will** block by default if output is going to a TTY - (a terminal). -5. Windows functionality differs. Writes block except when output is going to a - TTY. +Note: `process.stdout` differs from other Node.js streams in important ways, +see [note on process I/O][] for more information. + +### A note on process I/O -To check if Node.js is being run in a TTY context, read the `isTTY` property -on `process.stderr`, `process.stdout`, or `process.stdin`: +`process.stdout` and `process.stderr` differ from other Node.js streams in +important ways: -### TTY Terminals and `process.stdout` +1. They are used internally by [`console.log()`][] and [`console.error()`][], + respectively. +2. They cannot be closed ([`end()`][] will throw). +3. They will never emit the [`'finish'`][] event. +4. Writes may be synchronous depending on the what the stream is connected to + and whether the system is Windows or Unix: + - Files: *synchronous* on Windows and Linux + - TTYs (Terminals): *asynchronous* on Windows, *synchronous* on Unix + - Pipes (and sockets): *synchronous* on Windows, *asynchronous* on Unix -The `process.stderr` and `process.stdout` streams are blocking when outputting -to TTYs (terminals) on OS X as a workaround for the operating system's small, -1kb buffer size. This is to prevent interleaving between `stdout` and `stderr`. +These behaviours are partly for historical reasons, as changing them would +create backwards incompatibility, but they are also expected by some users. -To check if Node.js is being run in a [TTY][] context, check the `isTTY` -property on `process.stderr`, `process.stdout`, or `process.stdin`. +Synchronous writes avoid problems such as output written with `console.log()` or +`console.write()` being unexpectedly interleaved, or not written at all if +`process.exit()` is called before an asynchronous write completes. See +[`process.exit()`][] for more information. + +***Warning***: Synchronous writes block the event loop until the write has +completed. This can be near instantaneous in the case of output to a file, but +under high system load, pipes that are not being read at the receiving end, or +with slow terminals or file systems, its possible for the event loop to be +blocked often enough and long enough to have severe negative performance +impacts. This may not be a problem when writing to an interactive terminal +session, but consider this particularly careful when doing production logging to +the process output streams. + +To check if a stream is connected to a [TTY][] context, check the `isTTY` +property. For instance: ```console @@ -1570,7 +1571,6 @@ $ node -p "Boolean(process.stdin.isTTY)" true $ echo "foo" | node -p "Boolean(process.stdin.isTTY)" false - $ node -p "Boolean(process.stdout.isTTY)" true $ node -p "Boolean(process.stdout.isTTY)" | cat @@ -1724,6 +1724,7 @@ cases: the high-order bit, and then contain the value of the signal code. +[`'exit'`]: #process_event_exit [`'finish'`]: stream.html#stream_event_finish [`'message'`]: child_process.html#child_process_event_message [`'rejectionHandled'`]: #process_event_rejectionhandled @@ -1745,6 +1746,7 @@ cases: [`promise.catch()`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/catch [`require.main`]: modules.html#modules_accessing_the_main_module [`setTimeout(fn, 0)`]: timers.html#timers_settimeout_callback_delay_args +[note on process I/O]: process.html#process_a_note_on_process_i_o [process_emit_warning]: #process_process_emitwarning_warning_name_ctor [process_warning]: #process_event_warning [Signal Events]: #process_signal_events From aef67cfe39a58f48f5788f9f9dcf8d7f153b8bab Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Wed, 8 Feb 2017 16:02:33 +0200 Subject: [PATCH 035/164] dgram: fix possibly deoptimizing use of arguments This commit adds a guard against an out of bounds access of arguments, and replaces another use of arguments with a named function parameter. Refs: https://github.com/nodejs/node/issues/10323 PR-URL: https://github.com/nodejs/node/pull/11242 Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- lib/dgram.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/dgram.js b/lib/dgram.js index 43efe4665b15df..69bcf5de10343c 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -131,7 +131,7 @@ function replaceHandle(self, newHandle) { self._handle = newHandle; } -Socket.prototype.bind = function(port_ /*, address, callback*/) { +Socket.prototype.bind = function(port_, address_ /*, callback*/) { let port = port_; this._healthCheck(); @@ -141,7 +141,7 @@ Socket.prototype.bind = function(port_ /*, address, callback*/) { this._bindState = BIND_STATE_BINDING; - if (typeof arguments[arguments.length - 1] === 'function') + if (arguments.length && typeof arguments[arguments.length - 1] === 'function') this.once('listening', arguments[arguments.length - 1]); if (port instanceof UDP) { @@ -158,7 +158,7 @@ Socket.prototype.bind = function(port_ /*, address, callback*/) { exclusive = !!port.exclusive; port = port.port; } else { - address = typeof arguments[1] === 'function' ? '' : arguments[1]; + address = typeof address_ === 'function' ? '' : address_; exclusive = false; } From c3c874f514d3a291e565a494a5036b86aa7efbd4 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Mon, 13 Feb 2017 12:04:00 -0800 Subject: [PATCH 036/164] doc: dns examples implied string args were arrays Fix: https://github.com/nodejs/node/pull/11334 PR-URL: https://github.com/nodejs/node/pull/11350 Reviewed-By: Gibson Fahnestock Reviewed-By: James M Snell --- doc/api/dns.md | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/doc/api/dns.md b/doc/api/dns.md index 40f830a3c8e5d8..f705d96246bd87 100644 --- a/doc/api/dns.md +++ b/doc/api/dns.md @@ -15,9 +15,10 @@ For example, looking up `iana.org`. ```js const dns = require('dns'); -dns.lookup('iana.org', (err, addresses, family) => { - console.log('addresses:', addresses); +dns.lookup('iana.org', (err, address, family) => { + console.log('address: %j family: IPv%s', address, family); }); +// address: "192.0.43.8" family: IPv4 ``` 2) Functions that connect to an actual DNS server to perform name resolution, @@ -84,15 +85,7 @@ Alternatively, `options` can be an object containing these properties: * `all`: {Boolean} - When `true`, the callback returns all resolved addresses in an array, otherwise returns a single address. Defaults to `false`. -All properties are optional. An example usage of options is shown below. - -```js -{ - family: 4, - hints: dns.ADDRCONFIG | dns.V4MAPPED, - all: false -} -``` +All properties are optional. The `callback` function has arguments `(err, address, family)`. `address` is a string representation of an IPv4 or IPv6 address. `family` is either the @@ -115,6 +108,25 @@ important consequences on the behavior of any Node.js program. Please take some time to consult the [Implementation considerations section][] before using `dns.lookup()`. +Example usage: + +```js +const dns = require('dns'); +const options = { + family: 6, + hints: dns.ADDRCONFIG | dns.V4MAPPED, +}; +dns.lookup('example.com', options, (err, address, family) => + console.log('address: %j family: IPv%s', address, family)); +// address: "2606:2800:220:1:248:1893:25c8:1946" family: IPv6 + +// When options.all is true, the result will be an Array. +options.all = true; +dns.lookup('example.com', options, (err, addresses) => + console.log('addresses: %j', addresses)); +// addresses: [{"address":"2606:2800:220:1:248:1893:25c8:1946","family":6}] +``` + ### Supported getaddrinfo flags The following flags can be passed as hints to [`dns.lookup()`][]. From 82882f4e90a23f989a4d7c6b9098413b3957a64e Mon Sep 17 00:00:00 2001 From: cjihrig Date: Tue, 14 Feb 2017 14:07:39 -0500 Subject: [PATCH 037/164] test: cover dgram socket close during bind case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit tests the scenario where a dgram socket closes during a call to Socket#bind(). PR-URL: https://github.com/nodejs/node/pull/11383 Reviewed-By: Rich Trott Reviewed-By: Michaël Zasso --- test/parallel/test-dgram-close-during-bind.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 test/parallel/test-dgram-close-during-bind.js diff --git a/test/parallel/test-dgram-close-during-bind.js b/test/parallel/test-dgram-close-during-bind.js new file mode 100644 index 00000000000000..1764f66e7338ac --- /dev/null +++ b/test/parallel/test-dgram-close-during-bind.js @@ -0,0 +1,16 @@ +'use strict'; +const common = require('../common'); +const dgram = require('dgram'); +const socket = dgram.createSocket('udp4'); +const lookup = socket._handle.lookup; + +// Test the scenario where the socket is closed during a bind operation. +socket._handle.bind = common.mustNotCall('bind() should not be called.'); + +socket._handle.lookup = common.mustCall(function(address, callback) { + socket.close(common.mustCall(() => { + lookup.call(this, address, callback); + })); +}); + +socket.bind(common.mustNotCall('Socket should not bind.')); From 4366ab539fdb0606399953cf3ff63d7b22c5d852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Wed, 8 Feb 2017 10:51:07 +0100 Subject: [PATCH 038/164] url: implement URL.prototype.toJSON PR-URL: https://github.com/nodejs/node/pull/11236 Ref: https://github.com/whatwg/url/pull/229 Reviewed-By: Anna Henningsen Reviewed-By: Joyee Cheung Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Timothy Gu --- doc/api/url.md | 24 ++++++++++++++++++++- lib/internal/url.js | 9 ++++++++ test/parallel/test-whatwg-url-properties.js | 2 +- test/parallel/test-whatwg-url-tojson.js | 16 ++++++++++++++ 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-whatwg-url-tojson.js diff --git a/doc/api/url.md b/doc/api/url.md index 61d27c5b68a15e..b71e0b88b21ead 100644 --- a/doc/api/url.md +++ b/doc/api/url.md @@ -652,12 +652,32 @@ and [`url.format()`][] methods would produce. * Returns: {String} The `toString()` method on the `URL` object returns the serialized URL. The -value returned is equivalent to that of [`url.href`][]. +value returned is equivalent to that of [`url.href`][] and [`url.toJSON()`][]. Because of the need for standard compliance, this method does not allow users to customize the serialization process of the URL. For more flexibility, [`require('url').format()`][] method might be of interest. +#### url.toJSON() + +* Returns: {String} + +The `toJSON()` method on the `URL` object returns the serialized URL. The +value returned is equivalent to that of [`url.href`][] and +[`url.toString()`][]. + +This method is automatically called when an `URL` object is serialized +with [`JSON.stringify()`][]. + +```js +const myURLs = [ + new URL('https://www.example.com'), + new URL('https://test.example.org') +]; +console.log(JSON.stringify(myURLs)); + // Prints ["https://www.example.com/","https://test.example.org/"] +``` + ### Class: URLSearchParams The `URLSearchParams` API provides read and write access to the query of a @@ -925,3 +945,5 @@ console.log(myURL.origin); [`urlSearchParams.entries()`]: #url_urlsearchparams_entries [`urlSearchParams@@iterator()`]: #url_urlsearchparams_iterator [stable sorting algorithm]: https://en.wikipedia.org/wiki/Sorting_algorithm#Stability +[`JSON.stringify()`]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify +[`url.toJSON()`]: #url_url_tojson diff --git a/lib/internal/url.js b/lib/internal/url.js index c799ed839b84d8..a8406503cc0909 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -523,6 +523,15 @@ Object.defineProperties(URL.prototype, { binding.parse(hash, binding.kFragment, null, ctx, onParseHashComplete.bind(this)); } + }, + toJSON: { + writable: true, + enumerable: true, + configurable: true, + // eslint-disable-next-line func-name-matching + value: function toJSON() { + return this[kFormat]({}); + } } }); diff --git a/test/parallel/test-whatwg-url-properties.js b/test/parallel/test-whatwg-url-properties.js index f093791b2de867..b5b3119422e668 100644 --- a/test/parallel/test-whatwg-url-properties.js +++ b/test/parallel/test-whatwg-url-properties.js @@ -23,7 +23,7 @@ for (const prop in url) { const expected = ['toString', 'href', 'origin', 'protocol', 'username', 'password', 'host', 'hostname', 'port', - 'pathname', 'search', 'searchParams', 'hash']; + 'pathname', 'search', 'searchParams', 'hash', 'toJSON']; assert.deepStrictEqual(props, expected); diff --git a/test/parallel/test-whatwg-url-tojson.js b/test/parallel/test-whatwg-url-tojson.js new file mode 100644 index 00000000000000..35af93261c79a5 --- /dev/null +++ b/test/parallel/test-whatwg-url-tojson.js @@ -0,0 +1,16 @@ +'use strict'; + +const common = require('../common'); +const URL = require('url').URL; +const { test, assert_equals } = common.WPT; + +/* eslint-disable */ +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/02585db/url/url-tojson.html + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ +test(() => { + const a = new URL("https://example.com/") + assert_equals(JSON.stringify(a), "\"https://example.com/\"") +}) +/* eslint-enable */ From aea0d501d78c486f7cafec58d4726b02ba7b5cbc Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 14 Feb 2017 21:55:50 -0800 Subject: [PATCH 039/164] test: improve message in net-connect-local-error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test-net-connect-local-error can fail with messages that report `AssertionError: undefined === 12346`. Unfortunately, this doesn't provide sufficient information to identify what went wrong with the test. Increase information provided. PR-URL: https://github.com/nodejs/node/pull/11393 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- test/parallel/test-net-connect-local-error.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-net-connect-local-error.js b/test/parallel/test-net-connect-local-error.js index 23bfacde336f36..f23245ac93a49f 100644 --- a/test/parallel/test-net-connect-local-error.js +++ b/test/parallel/test-net-connect-local-error.js @@ -10,6 +10,14 @@ const client = net.connect({ }); client.on('error', common.mustCall(function onError(err) { - assert.strictEqual(err.localPort, common.PORT); - assert.strictEqual(err.localAddress, common.localhostIPv4); + assert.strictEqual( + err.localPort, + common.PORT, + `${err.localPort} !== ${common.PORT} in ${err}` + ); + assert.strictEqual( + err.localAddress, + common.localhostIPv4, + `${err.localAddress} !== ${common.localhostIPv4} in ${err}` + ); })); From 5723087cdd4b917fd4d26cb00f3b1b7d286ba871 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 14 Feb 2017 13:45:58 -0800 Subject: [PATCH 040/164] test: refactor test-dgram-membership MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * match full error message in assert.throws() * wrapped function -> .bind() PR-URL: https://github.com/nodejs/node/pull/11388 Reviewed-By: Colin Ihrig Reviewed-By: Yuta Hiroto Reviewed-By: Gibson Fahnestock Reviewed-By: Michaël Zasso Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- test/parallel/test-dgram-membership.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/parallel/test-dgram-membership.js b/test/parallel/test-dgram-membership.js index 7f38b6005bc7af..1543b9043f7738 100644 --- a/test/parallel/test-dgram-membership.js +++ b/test/parallel/test-dgram-membership.js @@ -5,9 +5,7 @@ const assert = require('assert'); const dgram = require('dgram'); const multicastAddress = '224.0.0.114'; -const setup = () => { - return dgram.createSocket({type: 'udp4', reuseAddr: true}); -}; +const setup = dgram.createSocket.bind(dgram, {type: 'udp4', reuseAddr: true}); // addMembership() on closed socket should throw { @@ -46,14 +44,16 @@ const setup = () => { // addMembership() with invalid multicast address should throw { const socket = setup(); - assert.throws(() => { socket.addMembership('256.256.256.256'); }, /EINVAL/); + assert.throws(() => { socket.addMembership('256.256.256.256'); }, + /^Error: addMembership EINVAL$/); socket.close(); } // dropMembership() with invalid multicast address should throw { const socket = setup(); - assert.throws(() => { socket.dropMembership('256.256.256.256'); }, /EINVAL/); + assert.throws(() => { socket.dropMembership('256.256.256.256'); }, + /^Error: dropMembership EINVAL$/); socket.close(); } From ef1731d972f9285226daf5bf8037c0c89bc304b1 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 14 Feb 2017 11:00:34 -0800 Subject: [PATCH 041/164] doc: add missing function to test common doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add documentation for `common.expectsError()` to `test/README.md`. PR-URL: https://github.com/nodejs/node/pull/11382 Reviewed-By: James M Snell Reviewed-By: Gibson Fahnestock Reviewed-By: Michaël Zasso Reviewed-By: Joyee Cheung Reviewed-By: Luigi Pinca --- test/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/README.md b/test/README.md index 5ed028a19631d6..8affd257a7628e 100644 --- a/test/README.md +++ b/test/README.md @@ -180,6 +180,22 @@ Platform normalizes the `dd` command Check if there is more than 1gb of total memory. +### expectsError(code[, type[, message]]) +* `code` [<String>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) + expected error must have this value for its `code` property +* `type` [<Function>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function) + expected error must be an instance of `type` +* `message` [<String>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) + or [<RegExp>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) + if a string is provided for `message`, expected error must have it for its + `message` property; if a regular expression is provided for `message`, the + regular expression must match the `message` property of the expected error + +* return function suitable for use as a validation function passed as the second + argument to `assert.throws()` + +The expected error should be [subclassed by the `internal/errors` module](https://github.com/nodejs/node/blob/master/doc/guides/using-internal-errors.md#api). + ### expectWarning(name, expected) * `name` [<String>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) * `expected` [<String>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) | [<Array>](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) From 60fc56795284f22d8e12d743f4dc66aeb3bd7ea2 Mon Sep 17 00:00:00 2001 From: Jackson Tian Date: Sat, 4 Feb 2017 00:23:10 +0800 Subject: [PATCH 042/164] child_process: move anonymous class to top level Move the anonymous class out of setupChannel to clarify code. PR-URL: https://github.com/nodejs/node/pull/11147 Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: Anna Henningsen --- lib/internal/child_process.js | 37 ++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 3017cd5889a037..b3023f6a46d9b7 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -407,6 +407,24 @@ ChildProcess.prototype.unref = function() { if (this._handle) this._handle.unref(); }; +class Control extends EventEmitter { + constructor(channel) { + super(); + this.channel = channel; + this.refs = 0; + } + ref() { + if (++this.refs === 1) { + this.channel.ref(); + } + } + unref() { + if (--this.refs === 0) { + this.channel.unref(); + this.emit('unref'); + } + } +} function setupChannel(target, channel) { target.channel = channel; @@ -421,24 +439,7 @@ function setupChannel(target, channel) { target._handleQueue = null; target._pendingHandle = null; - const control = new class extends EventEmitter { - constructor() { - super(); - this.channel = channel; - this.refs = 0; - } - ref() { - if (++this.refs === 1) { - this.channel.ref(); - } - } - unref() { - if (--this.refs === 0) { - this.channel.unref(); - this.emit('unref'); - } - } - }(); + const control = new Control(channel); var decoder = new StringDecoder('utf8'); var jsonBuffer = ''; From 5b5dca9076af60cf14463636851992ca41332d8c Mon Sep 17 00:00:00 2001 From: Roman Reiss Date: Wed, 15 Feb 2017 12:30:40 +0100 Subject: [PATCH 043/164] tools: suggest python2 command in configure Try and find a suitable python2 binary and suggest it to the user in case they start the configure script with a incompatible version. PR-URL: https://github.com/nodejs/node/pull/11375 Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel Reviewed-By: Colin Ihrig Reviewed-By: Gibson Fahnestock --- configure | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/configure b/configure index d0b50f80f9f07d..50078df43a9ed5 100755 --- a/configure +++ b/configure @@ -2,7 +2,16 @@ import sys if sys.version_info[0] != 2 or sys.version_info[1] not in (6, 7): - sys.stdout.write("Please use either Python 2.6 or 2.7\n") + sys.stderr.write('Please use either Python 2.6 or 2.7') + + from distutils.spawn import find_executable as which + python2 = which('python2') or which('python2.6') or which('python2.7') + + if python2: + sys.stderr.write(':\n\n') + sys.stderr.write(' ' + python2 + ' ' + ' '.join(sys.argv)) + + sys.stderr.write('\n') sys.exit(1) import errno From 3bdac54e670ad21a24f529a8065204c961ea7e64 Mon Sep 17 00:00:00 2001 From: Shinnosuke Watanabe Date: Mon, 13 Feb 2017 17:15:26 +0900 Subject: [PATCH 044/164] util: use ES2015+ Object.is to check negative zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use `Object.is` to check whether the value is negative zero or not. Ref: https://github.com/nodejs/node/commit/b3e4fc6a48b97b52bd19de43c76b7082dcab4988 PR-URL: https://github.com/nodejs/node/pull/11332 Reviewed-By: Ben Noordhuis Reviewed-By: Michaël Zasso Reviewed-By: Evan Lucas Reviewed-By: Joyee Cheung Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Luigi Pinca --- lib/util.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/util.js b/lib/util.js index ca07dff94909f8..71f4def2b84ea9 100644 --- a/lib/util.js +++ b/lib/util.js @@ -604,9 +604,8 @@ function formatValue(ctx, value, recurseTimes) { function formatNumber(ctx, value) { - // Format -0 as '-0'. Strict equality won't distinguish 0 from -0, - // so instead we use the fact that 1 / -0 < 0 whereas 1 / 0 > 0 . - if (value === 0 && 1 / value < 0) + // Format -0 as '-0'. Strict equality won't distinguish 0 from -0. + if (Object.is(value, -0)) return ctx.stylize('-0', 'number'); return ctx.stylize('' + value, 'number'); } From e416967244770b0d3f750f833e6ac6cb6941862f Mon Sep 17 00:00:00 2001 From: Daijiro Wachi Date: Mon, 13 Feb 2017 21:51:19 +0100 Subject: [PATCH 045/164] test: cases to querystring related to empty string + Add cases to `qs.stringify` that return empty string + Add cases to `qs.parse` when `sep` or `eq` is empty PR-URL: https://github.com/nodejs/node/pull/11329 Reviewed-By: Yuta Hiroto Reviewed-By: James M Snell Reviewed-By: Luigi Pinca --- test/parallel/test-querystring.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/parallel/test-querystring.js b/test/parallel/test-querystring.js index 6dbd9176c26693..988e210c4f2194 100644 --- a/test/parallel/test-querystring.js +++ b/test/parallel/test-querystring.js @@ -224,8 +224,20 @@ assert.doesNotThrow(function() { assert.strictEqual(f, 'a:b;q:x%3Ay%3By%3Az'); } +// empty string +assert.strictEqual(qs.stringify(), ''); +assert.strictEqual(qs.stringify(0), ''); +assert.strictEqual(qs.stringify([]), ''); +assert.strictEqual(qs.stringify(null), ''); +assert.strictEqual(qs.stringify(true), ''); + check(qs.parse(), {}); +// empty sep +check(qs.parse('a', []), { a: '' }); + +// empty eq +check(qs.parse('a', null, []), { '': 'a' }); // Test limiting assert.strictEqual( From 83fe819131917fe12b84b5ca82050292154bf16e Mon Sep 17 00:00:00 2001 From: Gibson Fahnestock Date: Sun, 12 Feb 2017 17:12:11 +0800 Subject: [PATCH 046/164] doc: add STYLE_GUIDE (moved from nodejs/docs) Also add a reference in CONTRIBUTING.md to it. PR-URL: https://github.com/nodejs/node/pull/11321 Reviewed-By: James M Snell --- CONTRIBUTING.md | 3 +++ doc/STYLE-GUIDE.md | 63 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 doc/STYLE-GUIDE.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6965f78b4d3e21..bf3dbd0ad0e163 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -85,6 +85,9 @@ Create a branch and start hacking: $ git checkout -b my-branch -t origin/master ``` +Any text you write should follow the [Style Guide](doc/STYLE_GUIDE.md), +including comments and API documentation. + ### Step 3: Commit Make sure git knows your name and email address: diff --git a/doc/STYLE-GUIDE.md b/doc/STYLE-GUIDE.md new file mode 100644 index 00000000000000..10f26421a4ceb5 --- /dev/null +++ b/doc/STYLE-GUIDE.md @@ -0,0 +1,63 @@ +# Style Guide + +* Documents are written in markdown files. +* Those files should be written in **`lowercase-with-dashes.md`.** + * Underscores in filenames are allowed only when they are present in the + topic the document will describe (e.g., `child_process`.) + * Filenames should be **lowercase**. + * Some files, such as top-level markdown files, are exceptions. + * Older files may use the `.markdown` extension. These may be ported to `.md` + at will. **Prefer `.md` for all new documents.** +* Documents should be word-wrapped at 80 characters. +* The formatting described in `.editorconfig` is preferred. + * A [plugin][] is available for some editors to automatically apply these rules. +* Mechanical issues, like spelling and grammar, should be identified by tools, + insofar as is possible. If not caught by a tool, they should be pointed out by + human reviewers. +* American English spelling is preferred. "Capitalize" vs. "Capitalise", + "color" vs. "colour", etc. +* Though controversial, the [Oxford comma][] is preferred for clarity's sake. +* Generally avoid personal pronouns in reference documentation ("I", "you", + "we".) + * Pronouns are acceptable in more colloquial documentation, like guides. + * Use **gender-neutral pronouns** and **mass nouns**. Non-comprehensive + examples: + * **OK**: "they", "their", "them", "folks", "people", "developers", "cats" + * **NOT OK**: "his", "hers", "him", "her", "guys", "dudes". +* When combining wrapping elements (parentheses and quotes), terminal + punctuation should be placed: + * Inside the wrapping element if the wrapping element contains a complete + clause — a subject, verb, and an object. + * Outside of the wrapping element if the wrapping element contains only a + fragment of a clause. +* Place end-of-sentence punctuation inside wrapping elements — periods go + inside parentheses and quotes, not after. +* Documents must start with a level-one heading. An example document will be + linked here eventually. +* Prefer affixing links to inlining links — prefer `[a link][]` to + `[a link](http://example.com)`. +* When documenting APIs, note the version the API was introduced in at + the end of the section. If an API has been deprecated, also note the first + version that the API appeared deprecated in. +* When using dashes, use emdashes ("—", Ctrl+Alt+"-" on OSX) surrounded by + spaces, per the New York Times usage. +* Including assets: + * If you wish to add an illustration or full program, add it to the + appropriate sub-directory in the `assets/` dir. + * Link to it like so: `[Asset](/assets/{subdir}/{filename})` for file-based + assets, and `![Asset](/assets/{subdir}/{filename})` for image-based assets. + * For illustrations, prefer SVG to other assets. When SVG is not feasible, + please keep a close eye on the filesize of the asset you're introducing. +* For code blocks: + * Use language aware fences. ("```js") + * Code need not be complete — treat code blocks as an illustration or aid to + your point, not as complete running programs. If a complete running program + is necessary, include it as an asset in `assets/code-examples` and link to + it. +* When using underscores, asterisks and backticks please use proper escaping (**\\\_**, **\\\*** and **\\\`** instead of **\_**, **\*** and **\`**) +* References to constructor functions should use PascalCase +* References to constructor instances should be camelCased +* References to methods should be used with parenthesis: `socket.end()` instead of `socket.end` + +[plugin]: http://editorconfig.org/#download +[Oxford comma]: https://en.wikipedia.org/wiki/Serial_comma From add762550c3cd52ec2e010955be31eae43faeefa Mon Sep 17 00:00:00 2001 From: larissayvette Date: Fri, 10 Feb 2017 17:18:38 +0100 Subject: [PATCH 047/164] test: consolidate buffer.read() in a file PR-URL: https://github.com/nodejs/node/pull/11297 Reviewed-By: James M Snell Reviewed-By: Rich Trott --- test/parallel/test-buffer-alloc.js | 78 ----------- test/parallel/test-buffer-read-noassert.js | 59 --------- test/parallel/test-buffer-read.js | 142 +++++++++++++++++++++ 3 files changed, 142 insertions(+), 137 deletions(-) delete mode 100644 test/parallel/test-buffer-read-noassert.js create mode 100644 test/parallel/test-buffer-read.js diff --git a/test/parallel/test-buffer-alloc.js b/test/parallel/test-buffer-alloc.js index 7f85943fa1898a..e9dfd9d895bb77 100644 --- a/test/parallel/test-buffer-alloc.js +++ b/test/parallel/test-buffer-alloc.js @@ -776,94 +776,16 @@ assert.throws(() => Buffer.alloc(8).writeFloatLE(0, 5), RangeError); assert.throws(() => Buffer.alloc(16).writeDoubleLE(0, 9), RangeError); // attempt to overflow buffers, similar to previous bug in array buffers -assert.throws(() => Buffer.allocUnsafe(8).readFloatLE(0xffffffff), - RangeError); assert.throws(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, 0xffffffff), RangeError); -assert.throws(() => Buffer.allocUnsafe(8).readFloatLE(0xffffffff), - RangeError); assert.throws(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, 0xffffffff), RangeError); // ensure negative values can't get past offset -assert.throws(() => Buffer.allocUnsafe(8).readFloatLE(-1), RangeError); assert.throws(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, -1), RangeError); -assert.throws(() => Buffer.allocUnsafe(8).readFloatLE(-1), RangeError); assert.throws(() => Buffer.allocUnsafe(8).writeFloatLE(0.0, -1), RangeError); -// offset checks -{ - const buf = Buffer.allocUnsafe(0); - - assert.throws(() => buf.readUInt8(0), RangeError); - assert.throws(() => buf.readInt8(0), RangeError); -} - -{ - const buf = Buffer.from([0xFF]); - - assert.strictEqual(buf.readUInt8(0), 255); - assert.strictEqual(buf.readInt8(0), -1); -} - -[16, 32].forEach((bits) => { - const buf = Buffer.allocUnsafe(bits / 8 - 1); - - assert.throws(() => buf[`readUInt${bits}BE`](0), - RangeError, - `readUInt${bits}BE()`); - - assert.throws(() => buf[`readUInt${bits}LE`](0), - RangeError, - `readUInt${bits}LE()`); - - assert.throws(() => buf[`readInt${bits}BE`](0), - RangeError, - `readInt${bits}BE()`); - - assert.throws(() => buf[`readInt${bits}LE`](0), - RangeError, - `readInt${bits}LE()`); -}); - -[16, 32].forEach((bits) => { - const buf = Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]); - - assert.strictEqual(buf[`readUInt${bits}BE`](0), - (0xFFFFFFFF >>> (32 - bits))); - - assert.strictEqual(buf[`readUInt${bits}LE`](0), - (0xFFFFFFFF >>> (32 - bits))); - - assert.strictEqual(buf[`readInt${bits}BE`](0), - (0xFFFFFFFF >> (32 - bits))); - - assert.strictEqual(buf[`readInt${bits}LE`](0), - (0xFFFFFFFF >> (32 - bits))); -}); - -// test for common read(U)IntLE/BE -{ - const buf = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]); - - assert.strictEqual(buf.readUIntLE(0, 1), 0x01); - assert.strictEqual(buf.readUIntBE(0, 1), 0x01); - assert.strictEqual(buf.readUIntLE(0, 3), 0x030201); - assert.strictEqual(buf.readUIntBE(0, 3), 0x010203); - assert.strictEqual(buf.readUIntLE(0, 5), 0x0504030201); - assert.strictEqual(buf.readUIntBE(0, 5), 0x0102030405); - assert.strictEqual(buf.readUIntLE(0, 6), 0x060504030201); - assert.strictEqual(buf.readUIntBE(0, 6), 0x010203040506); - assert.strictEqual(buf.readIntLE(0, 1), 0x01); - assert.strictEqual(buf.readIntBE(0, 1), 0x01); - assert.strictEqual(buf.readIntLE(0, 3), 0x030201); - assert.strictEqual(buf.readIntBE(0, 3), 0x010203); - assert.strictEqual(buf.readIntLE(0, 5), 0x0504030201); - assert.strictEqual(buf.readIntBE(0, 5), 0x0102030405); - assert.strictEqual(buf.readIntLE(0, 6), 0x060504030201); - assert.strictEqual(buf.readIntBE(0, 6), 0x010203040506); -} // test for common write(U)IntLE/BE { diff --git a/test/parallel/test-buffer-read-noassert.js b/test/parallel/test-buffer-read-noassert.js deleted file mode 100644 index 83d533a32031cb..00000000000000 --- a/test/parallel/test-buffer-read-noassert.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; -require('../common'); -const assert = require('assert'); - -// testing basic buffer read functions -const buf = Buffer.from([0xa4, 0xfd, 0x48, 0xea, 0xcf, 0xff, 0xd9, 0x01, 0xde]); - -function read(buff, funx, args, expected) { - - assert.strictEqual(buff[funx](...args), expected); - assert.throws( - () => buff[funx](-1), - /^RangeError: Index out of range$/ - ); - - assert.doesNotThrow( - () => assert.strictEqual(buff[funx](...args, true), expected), - 'noAssert does not change return value for valid ranges' -); - -} - -// testing basic functionality of readDoubleBE() and readDOubleLE() -read(buf, 'readDoubleBE', [1], -3.1827727774563287e+295); -read(buf, 'readDoubleLE', [1], -6.966010051009108e+144); - -// testing basic functionality of readFLoatBE() and readFloatLE() -read(buf, 'readFloatBE', [1], -1.6691549692541768e+37); -read(buf, 'readFloatLE', [1], -7861303808); - -// testing basic functionality of readInt8() -read(buf, 'readInt8', [1], -3); - -// testing basic functionality of readInt16BE() and readInt16LE() -read(buf, 'readInt16BE', [1], -696); -read(buf, 'readInt16LE', [1], 0x48fd); - -// testing basic functionality of readInt32BE() and readInt32LE() -read(buf, 'readInt32BE', [1], -45552945); -read(buf, 'readInt32LE', [1], -806729475); - -// testing basic functionality of readIntBE() and readIntLE() -read(buf, 'readIntBE', [1, 1], -3); -read(buf, 'readIntLE', [2, 1], 0x48); - -// testing basic functionality of readUInt8() -read(buf, 'readUInt8', [1], 0xfd); - -// testing basic functionality of readUInt16BE() and readUInt16LE() -read(buf, 'readUInt16BE', [2], 0x48ea); -read(buf, 'readUInt16LE', [2], 0xea48); - -// testing basic functionality of readUInt32BE() and readUInt32LE() -read(buf, 'readUInt32BE', [1], 0xfd48eacf); -read(buf, 'readUInt32LE', [1], 0xcfea48fd); - -// testing basic functionality of readUIntBE() and readUIntLE() -read(buf, 'readUIntBE', [2, 0], 0xfd); -read(buf, 'readUIntLE', [2, 0], 0x48); diff --git a/test/parallel/test-buffer-read.js b/test/parallel/test-buffer-read.js new file mode 100644 index 00000000000000..53e53dd49e2a84 --- /dev/null +++ b/test/parallel/test-buffer-read.js @@ -0,0 +1,142 @@ +'use strict'; +require('../common'); +const assert = require('assert'); + +// testing basic buffer read functions +const buf = Buffer.from([0xa4, 0xfd, 0x48, 0xea, 0xcf, 0xff, 0xd9, 0x01, 0xde]); + +function read(buff, funx, args, expected) { + + assert.strictEqual(buff[funx](...args), expected); + assert.throws( + () => buff[funx](-1), + /^RangeError: Index out of range$/ + ); + + assert.doesNotThrow( + () => assert.strictEqual(buff[funx](...args, true), expected), + 'noAssert does not change return value for valid ranges' +); + +} + +// testing basic functionality of readDoubleBE() and readDOubleLE() +read(buf, 'readDoubleBE', [1], -3.1827727774563287e+295); +read(buf, 'readDoubleLE', [1], -6.966010051009108e+144); + +// testing basic functionality of readFLoatBE() and readFloatLE() +read(buf, 'readFloatBE', [1], -1.6691549692541768e+37); +read(buf, 'readFloatLE', [1], -7861303808); + +// testing basic functionality of readInt8() +read(buf, 'readInt8', [1], -3); + +// testing basic functionality of readInt16BE() and readInt16LE() +read(buf, 'readInt16BE', [1], -696); +read(buf, 'readInt16LE', [1], 0x48fd); + +// testing basic functionality of readInt32BE() and readInt32LE() +read(buf, 'readInt32BE', [1], -45552945); +read(buf, 'readInt32LE', [1], -806729475); + +// testing basic functionality of readIntBE() and readIntLE() +read(buf, 'readIntBE', [1, 1], -3); +read(buf, 'readIntLE', [2, 1], 0x48); + +// testing basic functionality of readUInt8() +read(buf, 'readUInt8', [1], 0xfd); + +// testing basic functionality of readUInt16BE() and readUInt16LE() +read(buf, 'readUInt16BE', [2], 0x48ea); +read(buf, 'readUInt16LE', [2], 0xea48); + +// testing basic functionality of readUInt32BE() and readUInt32LE() +read(buf, 'readUInt32BE', [1], 0xfd48eacf); +read(buf, 'readUInt32LE', [1], 0xcfea48fd); + +// testing basic functionality of readUIntBE() and readUIntLE() +read(buf, 'readUIntBE', [2, 0], 0xfd); +read(buf, 'readUIntLE', [2, 0], 0x48); + +// attempt to overflow buffers, similar to previous bug in array buffers +assert.throws(() => Buffer.allocUnsafe(8).readFloatLE(0xffffffff), + RangeError); +assert.throws(() => Buffer.allocUnsafe(8).readFloatLE(0xffffffff), + RangeError); + +// ensure negative values can't get past offset +assert.throws(() => Buffer.allocUnsafe(8).readFloatLE(-1), RangeError); +assert.throws(() => Buffer.allocUnsafe(8).readFloatLE(-1), RangeError); + +// offset checks +{ + const buf = Buffer.allocUnsafe(0); + + assert.throws(() => buf.readUInt8(0), RangeError); + assert.throws(() => buf.readInt8(0), RangeError); +} + +{ + const buf = Buffer.from([0xFF]); + + assert.strictEqual(buf.readUInt8(0), 255); + assert.strictEqual(buf.readInt8(0), -1); +} + +[16, 32].forEach((bits) => { + const buf = Buffer.allocUnsafe(bits / 8 - 1); + + assert.throws(() => buf[`readUInt${bits}BE`](0), + RangeError, + `readUInt${bits}BE()`); + + assert.throws(() => buf[`readUInt${bits}LE`](0), + RangeError, + `readUInt${bits}LE()`); + + assert.throws(() => buf[`readInt${bits}BE`](0), + RangeError, + `readInt${bits}BE()`); + + assert.throws(() => buf[`readInt${bits}LE`](0), + RangeError, + `readInt${bits}LE()`); +}); + +[16, 32].forEach((bits) => { + const buf = Buffer.from([0xFF, 0xFF, 0xFF, 0xFF]); + + assert.strictEqual(buf[`readUInt${bits}BE`](0), + (0xFFFFFFFF >>> (32 - bits))); + + assert.strictEqual(buf[`readUInt${bits}LE`](0), + (0xFFFFFFFF >>> (32 - bits))); + + assert.strictEqual(buf[`readInt${bits}BE`](0), + (0xFFFFFFFF >> (32 - bits))); + + assert.strictEqual(buf[`readInt${bits}LE`](0), + (0xFFFFFFFF >> (32 - bits))); +}); + +// test for common read(U)IntLE/BE +{ + const buf = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]); + + assert.strictEqual(buf.readUIntLE(0, 1), 0x01); + assert.strictEqual(buf.readUIntBE(0, 1), 0x01); + assert.strictEqual(buf.readUIntLE(0, 3), 0x030201); + assert.strictEqual(buf.readUIntBE(0, 3), 0x010203); + assert.strictEqual(buf.readUIntLE(0, 5), 0x0504030201); + assert.strictEqual(buf.readUIntBE(0, 5), 0x0102030405); + assert.strictEqual(buf.readUIntLE(0, 6), 0x060504030201); + assert.strictEqual(buf.readUIntBE(0, 6), 0x010203040506); + assert.strictEqual(buf.readIntLE(0, 1), 0x01); + assert.strictEqual(buf.readIntBE(0, 1), 0x01); + assert.strictEqual(buf.readIntLE(0, 3), 0x030201); + assert.strictEqual(buf.readIntBE(0, 3), 0x010203); + assert.strictEqual(buf.readIntLE(0, 5), 0x0504030201); + assert.strictEqual(buf.readIntBE(0, 5), 0x0102030405); + assert.strictEqual(buf.readIntLE(0, 6), 0x060504030201); + assert.strictEqual(buf.readIntBE(0, 6), 0x010203040506); +} From 8ee236f85a4890e5a2992c0829fc3a2d3a654ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A8=8B=E5=8F=A3=E3=80=80=E5=BD=B0?= Date: Fri, 10 Feb 2017 13:06:10 +0900 Subject: [PATCH 048/164] test: improve crypto coverage * check exception when ECDH curve is undefined * check exception when getPublicKey format is invalid PR-URL: https://github.com/nodejs/node/pull/11279 Reviewed-By: Colin Ihrig Reviewed-By: Yuta Hiroto Reviewed-By: Santiago Gimeno Reviewed-By: James M Snell --- test/parallel/test-crypto-dh.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/parallel/test-crypto-dh.js b/test/parallel/test-crypto-dh.js index 95a6df6fee58bb..b95863a13ff9e7 100644 --- a/test/parallel/test-crypto-dh.js +++ b/test/parallel/test-crypto-dh.js @@ -182,6 +182,10 @@ let firstByte = ecdh1.getPublicKey('buffer', 'compressed')[0]; assert(firstByte === 2 || firstByte === 3); firstByte = ecdh1.getPublicKey('buffer', 'hybrid')[0]; assert(firstByte === 6 || firstByte === 7); +// format value should be string +assert.throws(() => { + ecdh1.getPublicKey('buffer', 10); +}, /^TypeError: Bad format: 10$/); // ECDH should check that point is on curve const ecdh3 = crypto.createECDH('secp256k1'); @@ -277,3 +281,8 @@ ecdh5.setPrivateKey(cafebabeKey, 'hex'); // Verify object state did not change. assert.strictEqual(ecdh5.getPrivateKey('hex'), cafebabeKey); }); + +// invalid test: curve argument is undefined +assert.throws(() => { + crypto.createECDH(); +}, /^TypeError: "curve" argument should be a string$/); From 48f6660d78fba69b5cdf419be6ead9a29ddd5777 Mon Sep 17 00:00:00 2001 From: Brian White Date: Wed, 8 Feb 2017 03:27:35 -0500 Subject: [PATCH 049/164] benchmark: fix timer display in progress output This commit fixes an issue where the minutes would not display properly on the benchmark timer once an hour had elapsed. PR-URL: https://github.com/nodejs/node/pull/11235 Reviewed-By: Joyee Cheung Reviewed-By: Andreas Madsen Reviewed-By: James M Snell --- benchmark/_benchmark_progress.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/benchmark/_benchmark_progress.js b/benchmark/_benchmark_progress.js index 2a2a458c5c4e4b..4b42248f246858 100644 --- a/benchmark/_benchmark_progress.js +++ b/benchmark/_benchmark_progress.js @@ -15,9 +15,9 @@ function fraction(numerator, denominator) { function getTime(diff) { const time = Math.ceil(diff[0] + diff[1] / 1e9); - const seconds = pad(time % 60, 2, '0'); - const minutes = pad(Math.floor(time / 60) % (60 * 60), 2, '0'); - const hours = pad(Math.floor(time / (60 * 60)), 2, '0'); + const hours = pad(Math.floor(time / 3600), 2, '0'); + const minutes = pad(Math.floor((time % 3600) / 60), 2, '0'); + const seconds = pad((time % 3600) % 60, 2, '0'); return `${hours}:${minutes}:${seconds}`; } From d1549bf8d94bd788ab5d06aadd0087c3c23d9ed3 Mon Sep 17 00:00:00 2001 From: Daniel Bevenius Date: Fri, 3 Feb 2017 12:46:23 +0100 Subject: [PATCH 050/164] lib: add constant kMaxCallbacksUntilQueueIsShortened Currently the maximum number of tick is duplicated in two places. This commit introduces a constant that both can use. PR-URL: https://github.com/nodejs/node/pull/11199 Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Trevor Norris --- lib/internal/process/next_tick.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/internal/process/next_tick.js b/lib/internal/process/next_tick.js index f27ef622a96e6a..bc89c6e8b269e3 100644 --- a/lib/internal/process/next_tick.js +++ b/lib/internal/process/next_tick.js @@ -1,5 +1,11 @@ 'use strict'; +// This value is used to prevent the nextTickQueue from becoming too +// large and cause the process to run out of memory. When this value +// is reached the nextTimeQueue array will be shortend (see tickDone +// for details). +const kMaxCallbacksUntilQueueIsShortened = 1e4; + exports.setup = setupNextTick; function setupNextTick() { @@ -96,7 +102,7 @@ function setupNextTick() { // callback invocation with small numbers of arguments to avoid the // performance hit associated with using `fn.apply()` _combinedTickCallback(args, callback); - if (1e4 < tickInfo[kIndex]) + if (kMaxCallbacksUntilQueueIsShortened < tickInfo[kIndex]) tickDone(); } tickDone(); @@ -120,7 +126,7 @@ function setupNextTick() { // callback invocation with small numbers of arguments to avoid the // performance hit associated with using `fn.apply()` _combinedTickCallback(args, callback); - if (1e4 < tickInfo[kIndex]) + if (kMaxCallbacksUntilQueueIsShortened < tickInfo[kIndex]) tickDone(); if (domain) domain.exit(); From 12cf3594235e6c4c6838ae7588b5e73ad9775dfa Mon Sep 17 00:00:00 2001 From: QianJin2013 Date: Sun, 12 Feb 2017 19:09:34 +0900 Subject: [PATCH 051/164] doc: add comment for net.Server.listen IPv6 '::' Fixes: https://github.com/nodejs/node/issues/9390 PR-URL: https://github.com/nodejs/node/pull/11134 Reviewed-By: James M Snell Reviewed-By: Gibson Fahnestock --- doc/api/http.md | 12 ++++++++++-- doc/api/net.md | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/doc/api/http.md b/doc/api/http.md index 574bfe038b01b8..681fb21eb511ff 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -745,8 +745,14 @@ added: v0.1.90 * `callback` {Function} Begin accepting connections on the specified `port` and `hostname`. If the -`hostname` is omitted, the server will accept connections on any IPv6 address -(`::`) when IPv6 is available, or any IPv4 address (`0.0.0.0`) otherwise. +`hostname` is omitted, the server will accept connections on the +[unspecified IPv6 address][] (`::`) when IPv6 is available, or the +[unspecified IPv4 address][] (`0.0.0.0`) otherwise. + +*Note*: in most operating systems, listening to the +[unspecified IPv6 address][] (`::`) may cause the `net.Server` to also listen on +the [unspecified IPv4 address][] (`0.0.0.0`). + Omit the port argument, or use a port value of `0`, to have the operating system assign a random port, which can be retrieved by using `server.address().port` after the `'listening'` event has been emitted. @@ -1659,3 +1665,5 @@ There are a few special headers that should be noted. [Readable Stream]: stream.html#stream_class_stream_readable [Writable Stream]: stream.html#stream_class_stream_writable [socket.unref()]: net.html#net_socket_unref +[unspecified IPv6 address]: https://en.wikipedia.org/wiki/IPv6_address#Unspecified_address +[unspecified IPv4 address]: https://en.wikipedia.org/wiki/0.0.0.0 diff --git a/doc/api/net.md b/doc/api/net.md index 02afc949f99c53..49e8b6126895d0 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -224,8 +224,14 @@ added: v0.1.90 --> Begin accepting connections on the specified `port` and `hostname`. If the -`hostname` is omitted, the server will accept connections on any IPv6 address -(`::`) when IPv6 is available, or any IPv4 address (`0.0.0.0`) otherwise. +`hostname` is omitted, the server will accept connections on the +[unspecified IPv6 address][] (`::`) when IPv6 is available, or the +[unspecified IPv4 address][] (`0.0.0.0`) otherwise. + +*Note*: in most operating systems, listening to the +[unspecified IPv6 address][] (`::`) may cause the `net.Server` to also listen on +the [unspecified IPv4 address][] (`0.0.0.0`). + Omit the port argument, or use a port value of `0`, to have the operating system assign a random port, which can be retrieved by using `server.address().port` after the `'listening'` event has been emitted. @@ -941,3 +947,5 @@ Returns true if input is a version 6 IP address, otherwise returns false. [`socket.setTimeout()`]: #net_socket_settimeout_timeout_callback [`stream.setEncoding()`]: stream.html#stream_readable_setencoding_encoding [Readable Stream]: stream.html#stream_class_stream_readable +[unspecified IPv6 address]: https://en.wikipedia.org/wiki/IPv6_address#Unspecified_address +[unspecified IPv4 address]: https://en.wikipedia.org/wiki/0.0.0.0 From 72da362d6e7dbdbd0d314d8ebf68ea6eeca26271 Mon Sep 17 00:00:00 2001 From: Daijiro Wachi Date: Tue, 7 Feb 2017 18:45:27 +0100 Subject: [PATCH 052/164] url: fix file state clarification in binding An empty file URL `file:` should be parsed to `file:///` instead of `file://`. In the `kFile` state, the process was braked immediately when the ch is EOL, but it should work as `default` in the kFile state to adjust slashes. Applicable cases: * `file:#foo` => `file:///#foo` * `file:?bar` => `file:///?bar` PR-URL: https://github.com/nodejs/node/pull/11123 Fixes: https://github.com/nodejs/node/issues/10978 Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- src/node_url.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/node_url.cc b/src/node_url.cc index 0d5e695a3c13a5..5027399e89dd71 100644 --- a/src/node_url.cc +++ b/src/node_url.cc @@ -1074,8 +1074,10 @@ namespace url { SET_HAVE_QUERY() url.query = base.query; } + break; } - break; + state = kPath; + continue; case '\\': case '/': state = kFileSlash; @@ -1092,8 +1094,8 @@ namespace url { } SET_HAVE_QUERY() state = kQuery; + break; } - break; case '#': if (base_is_file) { if (DOES_HAVE_HOST(base)) { @@ -1109,8 +1111,8 @@ namespace url { url.query = base.query; } state = kFragment; + break; } - break; default: if (base_is_file && (!WINDOWS_DRIVE_LETTER(ch, p[1]) || From d8cb65aa6e4583085c3895ea0898719e5ee8ceb2 Mon Sep 17 00:00:00 2001 From: Daijiro Wachi Date: Tue, 7 Feb 2017 19:02:22 +0100 Subject: [PATCH 053/164] url, test: synchronize WPT url tests for file URL Added at the following PR: * https://github.com/w3c/web-platform-tests/pull/4382 * https://github.com/w3c/web-platform-tests/pull/4700 PR-URL: https://github.com/nodejs/node/pull/11123 Fixes: https://github.com/nodejs/node/issues/10978 Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- test/fixtures/url-tests.json | 114 +++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/test/fixtures/url-tests.json b/test/fixtures/url-tests.json index 634a8e3f663985..fb286ed91fcbd7 100644 --- a/test/fixtures/url-tests.json +++ b/test/fixtures/url-tests.json @@ -4649,5 +4649,119 @@ "pathname": "/", "search": "", "hash": "" + }, + "# More file URL tests by zcorpan", + { + "input": "/", + "base": "file:///C:/a/b", + "href": "file:///C:/", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/C:/", + "search": "", + "hash": "" + }, + { + "input": "//d:", + "base": "file:///C:/a/b", + "href": "file:///d:", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/d:", + "search": "", + "hash": "" + }, + { + "input": "//d:/..", + "base": "file:///C:/a/b", + "href": "file:///d:/", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/d:/", + "search": "", + "hash": "" + }, + { + "input": "..", + "base": "file:///ab:/", + "href": "file:///", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + { + "input": "..", + "base": "file:///1:/", + "href": "file:///", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + "# file URLs without base URL by Rimas Misevičius", + { + "input": "file:", + "base": "about:blank", + "href": "file:///", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + { + "input": "file:?q=v", + "base": "about:blank", + "href": "file:///?q=v", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/", + "search": "?q=v", + "hash": "" + }, + { + "input": "file:#frag", + "base": "about:blank", + "href": "file:///#frag", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/", + "search": "", + "hash": "#frag" } ] From 9c45758cdf9dc610652a0e0dc753a221ee212a63 Mon Sep 17 00:00:00 2001 From: Kenan Yildirim Date: Mon, 13 Feb 2017 13:31:56 -0500 Subject: [PATCH 054/164] build: fix building with ninja on linux On Linux, `ninja` appears to place `libv8_base.a` inside `OBJ_DIR`, as opposed to `ninja` on OS X which places it outside of that directory. Furthermore, the expected `OBJ_DIR` value (`obj.target/`) is actually just `obj/` for `ninja`. This patch solves both of these issues by setting `OBJ_DIR` and `V8_BASE` to the correct values for `ninja` on Linux specifically. PR-URL: https://github.com/nodejs/node/pull/11348 Fixes: https://github.com/nodejs/node/issues/9861 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Gibson Fahnestock Reviewed-By: James M Snell --- common.gypi | 13 ++++++++++--- node.gyp | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/common.gypi b/common.gypi index 0fa36197be97a9..a52915d59a7ac4 100644 --- a/common.gypi +++ b/common.gypi @@ -42,12 +42,19 @@ 'os_posix': 1, 'v8_postmortem_support%': 'true', }], - ['GENERATOR == "ninja" or OS== "mac"', { + ['OS== "mac"', { 'OBJ_DIR': '<(PRODUCT_DIR)/obj', 'V8_BASE': '<(PRODUCT_DIR)/libv8_base.a', }, { - 'OBJ_DIR': '<(PRODUCT_DIR)/obj.target', - 'V8_BASE': '<(PRODUCT_DIR)/obj.target/deps/v8/src/libv8_base.a', + 'conditions': [ + ['GENERATOR=="ninja"', { + 'OBJ_DIR': '<(PRODUCT_DIR)/obj', + 'V8_BASE': '<(PRODUCT_DIR)/obj/deps/v8/src/libv8_base.a', + }, { + 'OBJ_DIR': '<(PRODUCT_DIR)/obj.target', + 'V8_BASE': '<(PRODUCT_DIR)/obj.target/deps/v8/src/libv8_base.a', + }], + ], }], ['openssl_fips != ""', { 'OPENSSL_PRODUCT': 'libcrypto.a', diff --git a/node.gyp b/node.gyp index d14e7ff8f13d62..50d66837a62f33 100644 --- a/node.gyp +++ b/node.gyp @@ -383,7 +383,7 @@ ['OS in "linux freebsd" and node_shared=="false"', { 'ldflags': [ '-Wl,--whole-archive,' - '<(PRODUCT_DIR)/obj.target/deps/openssl/' + '<(OBJ_DIR)/deps/openssl/' '<(OPENSSL_PRODUCT)', '-Wl,--no-whole-archive', ], From bc9c381027499b53e26301d3f55a8d6321d3e3a2 Mon Sep 17 00:00:00 2001 From: Wayne Andrews Date: Tue, 10 Jan 2017 09:21:30 +0000 Subject: [PATCH 055/164] build: add code coverage to make PR-URL: https://github.com/nodejs/node/pull/10856 Reviewed-By: Jeremiah Senkpiel Reviewed-By: Anna Henningsen Reviewed-By: Michael Dawson --- Makefile | 67 +++++++++++++++++++++++++- lib/internal/bootstrap_node.js | 2 + lib/internal/process/write-coverage.js | 46 ++++++++++++++++++ node.gyp | 1 + test/common.js | 9 +++- 5 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 lib/internal/process/write-coverage.js diff --git a/Makefile b/Makefile index 4aaef26da24d23..9c28a3e4f4f88e 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ TEST_CI_ARGS ?= STAGINGSERVER ?= node-www LOGLEVEL ?= silent OSTYPE := $(shell uname -s | tr '[A-Z]' '[a-z]') +COVTESTS ?= test ifdef JOBS PARALLEL_ARGS = -j $(JOBS) @@ -113,6 +114,69 @@ distclean: check: test +# Remove files generated by running coverage, put the non-instrumented lib back +# in place +coverage-clean: + if [ -d lib_ ]; then rm -rf lib; mv lib_ lib; fi + -rm -rf node_modules + -rm -rf gcovr testing + -rm -rf out/$(BUILDTYPE)/.coverage + -rm -rf .cov_tmp coverage + -rm -f out/$(BUILDTYPE)/obj.target/node/src/*.gcda + -rm -f out/$(BUILDTYPE)/obj.target/node/src/tracing/*.gcda + -rm -f out/$(BUILDTYPE)/obj.target/node/src/*.gcno + -rm -f out/$(BUILDTYPE)/obj.target/node/src/tracing*.gcno + +# Build and test with code coverage reporting. Leave the lib directory +# instrumented for any additional runs the user may want to make. +# For C++ coverage reporting, this needs to be run in conjunction with configure +# --coverage. html coverage reports will be created under coverage/ + +coverage: coverage-test + +coverage-build: all + mkdir -p node_modules + if [ ! -d node_modules/istanbul-merge ]; then \ + $(NODE) ./deps/npm install istanbul-merge; fi + if [ ! -d node_modules/nyc ]; then $(NODE) ./deps/npm install nyc; fi + if [ ! -d gcovr ]; then git clone --depth=1 \ + --single-branch git://github.com/gcovr/gcovr.git; fi + if [ ! -d testing ]; then git clone --depth=1 \ + --single-branch https://github.com/nodejs/testing.git; fi + if [ ! -f gcovr/scripts/gcovr.orig ]; then \ + (cd gcovr && patch -N -p1 < \ + "$(CURDIR)/testing/coverage/gcovr-patches.diff"); fi + if [ -d lib_ ]; then rm -rf lib; mv lib_ lib; fi + mv lib lib_ + $(NODE) ./node_modules/.bin/nyc instrument lib_/ lib/ + $(MAKE) + +coverage-test: coverage-build + -rm -rf out/$(BUILDTYPE)/.coverage + -rm -rf .cov_tmp + -rm -f out/$(BUILDTYPE)/obj.target/node/src/*.gcda + -rm -f out/$(BUILDTYPE)/obj.target/node/src/tracing/*.gcda + -$(MAKE) $(COVTESTS) + mv lib lib__ + mv lib_ lib + mkdir -p coverage .cov_tmp + $(NODE) ./node_modules/.bin/istanbul-merge --out \ + .cov_tmp/libcov.json 'out/Release/.coverage/coverage-*.json' + (cd lib && .$(NODE) ../node_modules/.bin/nyc report \ + --temp-directory "$(CURDIR)/.cov_tmp" -r html \ + --report-dir "../coverage") + -(cd out && "../gcovr/scripts/gcovr" --gcov-exclude='.*deps' \ + --gcov-exclude='.*usr' -v -r Release/obj.target/node \ + --html --html-detail -o ../coverage/cxxcoverage.html) + mv lib lib_ + mv lib__ lib + @echo -n "Javascript coverage %: " + @grep -B1 Lines coverage/index.html | head -n1 \ + | sed 's/<[^>]*>//g'| sed 's/ //g' + @echo -n "C++ coverage %: " + @grep -A3 Lines coverage/cxxcoverage.html | grep style \ + | sed 's/<[^>]*>//g'| sed 's/ //g' + cctest: all @out/$(BUILDTYPE)/$@ @@ -781,4 +845,5 @@ endif bench-all bench bench-misc bench-array bench-buffer bench-net \ bench-http bench-fs bench-tls cctest run-ci test-v8 test-v8-intl \ test-v8-benchmarks test-v8-all v8 lint-ci bench-ci jslint-ci doc-only \ - $(TARBALL)-headers test-ci test-ci-native test-ci-js build-ci clear-stalled + $(TARBALL)-headers test-ci test-ci-native test-ci-js build-ci clear-stalled \ + coverage-clean coverage-build coverage-test coverage diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js index ccabffd8a6e342..be069d67a31816 100644 --- a/lib/internal/bootstrap_node.js +++ b/lib/internal/bootstrap_node.js @@ -44,6 +44,8 @@ NativeModule.require('internal/process/stdio').setup(); _process.setupKillAndExit(); _process.setupSignalHandlers(); + if (global.__coverage__) + NativeModule.require('internal/process/write-coverage').setup(); // Do not initialize channel in debugger agent, it deletes env variable // and the main thread won't see it. diff --git a/lib/internal/process/write-coverage.js b/lib/internal/process/write-coverage.js new file mode 100644 index 00000000000000..6bbc59a6e981be --- /dev/null +++ b/lib/internal/process/write-coverage.js @@ -0,0 +1,46 @@ +'use strict'; +const process = require('process'); +const path = require('path'); +const fs = require('fs'); +const mkdirSync = fs.mkdirSync; +const writeFileSync = fs.writeFileSync; + +var isWritingCoverage = false; +function writeCoverage() { + if (isWritingCoverage || !global.__coverage__) { + return; + } + isWritingCoverage = true; + + const dirname = path.join(path.dirname(process.execPath), '.coverage'); + const filename = `coverage-${process.pid}-${Date.now()}.json`; + try { + mkdirSync(dirname); + } catch (err) { + if (err.code !== 'EEXIST') { + console.error(err); + return; + } + } + + const target = path.join(dirname, filename); + const coverageInfo = JSON.stringify(global.__coverage__); + try { + writeFileSync(target, coverageInfo); + } catch (err) { + console.error(err); + } +} + +function setup() { + const reallyReallyExit = process.reallyExit; + + process.reallyExit = function(code) { + writeCoverage(); + reallyReallyExit(code); + }; + + process.on('exit', writeCoverage); +} + +exports.setup = setup; diff --git a/node.gyp b/node.gyp index 50d66837a62f33..d877bb22b69db7 100644 --- a/node.gyp +++ b/node.gyp @@ -93,6 +93,7 @@ 'lib/internal/process/warning.js', 'lib/internal/process.js', 'lib/internal/querystring.js', + 'lib/internal/process/write-coverage.js', 'lib/internal/readline.js', 'lib/internal/repl.js', 'lib/internal/socket_list.js', diff --git a/test/common.js b/test/common.js index 6cdf698fb5e839..8fe1d3c91e7b4f 100644 --- a/test/common.js +++ b/test/common.js @@ -284,6 +284,9 @@ exports.platformTimeout = function(ms) { if (process.config.target_defaults.default_configuration === 'Debug') ms = 2 * ms; + if (global.__coverage__) + ms = 4 * ms; + if (exports.isAix) return 2 * ms; // default localhost speed is slower on AIX @@ -381,7 +384,11 @@ function leakedGlobals() { if (!knownGlobals.includes(global[val])) leaked.push(val); - return leaked; + if (global.__coverage__) { + return leaked.filter((varname) => !/^(cov_|__cov)/.test(varname)); + } else { + return leaked; + } } exports.leakedGlobals = leakedGlobals; From 22a6eddc5cc17866105780063cf7e050ca5c6ac9 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 7 Feb 2017 23:56:10 +0800 Subject: [PATCH 056/164] doc: move benchmark/README.md to doc/guides Since benchmark/README.md is in fact a guide on how to write and run benchmarks, move it to doc/guides. PR-URL: https://github.com/nodejs/node/pull/11237 Fixes: https://github.com/nodejs/node/issues/11190 Reviewed-By: James M Snell Reviewed-By: Andreas Madsen --- .../guides}/doc_img/compare-boxplot.png | Bin {benchmark => doc/guides}/doc_img/scatter-plot.png | Bin .../guides/writing-and-running-benchmarks.md | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename {benchmark => doc/guides}/doc_img/compare-boxplot.png (100%) rename {benchmark => doc/guides}/doc_img/scatter-plot.png (100%) rename benchmark/README.md => doc/guides/writing-and-running-benchmarks.md (100%) diff --git a/benchmark/doc_img/compare-boxplot.png b/doc/guides/doc_img/compare-boxplot.png similarity index 100% rename from benchmark/doc_img/compare-boxplot.png rename to doc/guides/doc_img/compare-boxplot.png diff --git a/benchmark/doc_img/scatter-plot.png b/doc/guides/doc_img/scatter-plot.png similarity index 100% rename from benchmark/doc_img/scatter-plot.png rename to doc/guides/doc_img/scatter-plot.png diff --git a/benchmark/README.md b/doc/guides/writing-and-running-benchmarks.md similarity index 100% rename from benchmark/README.md rename to doc/guides/writing-and-running-benchmarks.md From 5d12fd9a4bc146df86f90d5567b06473e984bc38 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 8 Feb 2017 01:10:09 +0800 Subject: [PATCH 057/164] doc: add benchmark/README.md and fix guide * Write a new benchmark/README.md describing the benchmark directory layout and common API. * Fix the moved benchmarking guide accordingly, add tips about how to get the help text from the benchmarking tools. PR-URL: https://github.com/nodejs/node/pull/11237 Fixes: https://github.com/nodejs/node/issues/11190 Reviewed-By: James M Snell Reviewed-By: Andreas Madsen --- benchmark/README.md | 246 +++++++++++++++++++ doc/guides/writing-and-running-benchmarks.md | 54 ++-- 2 files changed, 278 insertions(+), 22 deletions(-) create mode 100644 benchmark/README.md diff --git a/benchmark/README.md b/benchmark/README.md new file mode 100644 index 00000000000000..6fd9a97bdfb3bb --- /dev/null +++ b/benchmark/README.md @@ -0,0 +1,246 @@ +# Node.js Core Benchmarks + +This folder contains code and data used to measure performance +of different Node.js implementations and different ways of +writing JavaScript run by the built-in JavaScript engine. + +For a detailed guide on how to write and run benchmarks in this +directory, see [the guide on benchmarks](../doc/guides/writing-and-running-benchmarks.md). + +## Table of Contents + +* [Benchmark directories](#benchmark-directories) +* [Common API](#common-api) + +## Benchmark Directories + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectoryPurpose
arrays + Benchmarks for various operations on array-like objects, + including Array, Buffer, and typed arrays. +
assert + Benchmarks for the assert subsystem. +
buffers + Benchmarks for the buffer subsystem. +
child_process + Benchmarks for the child_process subsystem. +
crypto + Benchmarks for the crypto subsystem. +
dgram + Benchmarks for the dgram subsystem. +
domain + Benchmarks for the domain subsystem. +
es + Benchmarks for various new ECMAScript features and their + pre-ES2015 counterparts. +
events + Benchmarks for the events subsystem. +
fixtures + Benchmarks fixtures used in various benchmarks throughout + the benchmark suite. +
fs + Benchmarks for the fs subsystem. +
http + Benchmarks for the http subsystem. +
misc + Miscellaneous benchmarks and benchmarks for shared + internal modules. +
module + Benchmarks for the module subsystem. +
net + Benchmarks for the net subsystem. +
path + Benchmarks for the path subsystem. +
process + Benchmarks for the process subsystem. +
querystring + Benchmarks for the querystring subsystem. +
streams + Benchmarks for the streams subsystem. +
string_decoder + Benchmarks for the string_decoder subsystem. +
timers + Benchmarks for the timers subsystem, including + setTimeout, setInterval, .etc. +
tls + Benchmarks for the tls subsystem. +
url + Benchmarks for the url subsystem, including the legacy + url implementation and the WHATWG URL implementation. +
util + Benchmarks for the util subsystem. +
vm + Benchmarks for the vm subsystem. +
+ +### Other Top-level files + +The top-level files include common dependencies of the benchmarks +and the tools for launching benchmarks and visualizing their output. +The actual benchmark scripts should be placed in their corresponding +directories. + +* `_benchmark_progress.js`: implements the progress bar displayed + when running `compare.js` +* `_cli.js`: parses the command line arguments passed to `compare.js`, + `run.js` and `scatter.js` +* `_cli.R`: parses the command line arguments passed to `compare.R` +* `_http-benchmarkers.js`: selects and runs external tools for benchmarking + the `http` subsystem. +* `common.js`: see [Common API](#common-api). +* `compare.js`: command line tool for comparing performance between different + Node.js binaries. +* `compare.R`: R script for statistically analyzing the output of + `compare.js` +* `run.js`: command line tool for running individual benchmark suite(s). +* `scatter.js`: command line tool for comparing the performance + between different parameters in benchmark configurations, + for example to analyze the time complexity. +* `scatter.R`: R script for visualizing the output of `scatter.js` with + scatter plots. + +## Common API + +The common.js module is used by benchmarks for consistency across repeated +tasks. It has a number of helpful functions and properties to help with +writing benchmarks. + +### createBenchmark(fn, configs[, options]) + +See [the guide on writing benchmarks](../doc/guides/writing-and-running-benchmarks.md#basics-of-a-benchmark). + +### default\_http\_benchmarker + +The default benchmarker used to run HTTP benchmarks. +See [the guide on writing HTTP benchmarks](../doc/guides/writing-and-running-benchmarks.md#creating-an-http-benchmark). + + +### PORT + +The default port used to run HTTP benchmarks. +See [the guide on writing HTTP benchmarks](../doc/guides/writing-and-running-benchmarks.md#creating-an-http-benchmark). + +### sendResult(data) + +Used in special benchmarks that can't use `createBenchmark` and the object +it returns to accomplish what they need. This function reports timing +data to the parent process (usually created by running `compare.js`, `run.js` or +`scatter.js`). + +### v8ForceOptimization(method[, ...args]) + +Force V8 to mark the `method` for optimization with the native function +`%OptimizeFunctionOnNextCall()` and return the optimization status +after that. + +It can be used to prevent the benchmark from getting disrupted by the optimizer +kicking in halfway through. However, this could result in a less effective +optimization. In general, only use it if you know what it actually does. diff --git a/doc/guides/writing-and-running-benchmarks.md b/doc/guides/writing-and-running-benchmarks.md index d1233470757f20..a20f321b7c2408 100644 --- a/doc/guides/writing-and-running-benchmarks.md +++ b/doc/guides/writing-and-running-benchmarks.md @@ -1,26 +1,34 @@ -# Node.js core benchmark +# How to Write and Run Benchmarks in Node.js Core -This folder contains benchmarks to measure the performance of the Node.js APIs. - -## Table of Content +## Table of Contents * [Prerequisites](#prerequisites) + * [HTTP Benchmark Requirements](#http-benchmark-requirements) + * [Benchmark Analysis Requirements](#benchmark-analysis-requirements) * [Running benchmarks](#running-benchmarks) - * [Running individual benchmarks](#running-individual-benchmarks) - * [Running all benchmarks](#running-all-benchmarks) - * [Comparing node versions](#comparing-node-versions) - * [Comparing parameters](#comparing-parameters) + * [Running individual benchmarks](#running-individual-benchmarks) + * [Running all benchmarks](#running-all-benchmarks) + * [Comparing Node.js versions](#comparing-nodejs-versions) + * [Comparing parameters](#comparing-parameters) * [Creating a benchmark](#creating-a-benchmark) + * [Basics of a benchmark](#basics-of-a-benchmark) + * [Creating an HTTP benchmark](#creating-an-http-benchmark) ## Prerequisites +Basic Unix tools are required for some benchmarks. +[Git for Windows][git-for-windows] includes Git Bash and the necessary tools, +which need to be included in the global Windows `PATH`. + +### HTTP Benchmark Requirements + Most of the HTTP benchmarks require a benchmarker to be installed, this can be either [`wrk`][wrk] or [`autocannon`][autocannon]. -`Autocannon` is a Node script that can be installed using -`npm install -g autocannon`. It will use the Node executable that is in the +`Autocannon` is a Node.js script that can be installed using +`npm install -g autocannon`. It will use the Node.js executable that is in the path, hence if you want to compare two HTTP benchmark runs make sure that the -Node version in the path is not altered. +Node.js version in the path is not altered. `wrk` may be available through your preferred package manager. If not, you can easily build it [from source][wrk] via `make`. @@ -34,9 +42,7 @@ benchmarker to be used by providing it as an argument, e. g.: `node benchmark/http/simple.js benchmarker=autocannon` -Basic Unix tools are required for some benchmarks. -[Git for Windows][git-for-windows] includes Git Bash and the necessary tools, -which need to be included in the global Windows `PATH`. +### Benchmark Analysis Requirements To analyze the results `R` should be installed. Check you package manager or download it from https://www.r-project.org/. @@ -50,7 +56,6 @@ install.packages("ggplot2") install.packages("plyr") ``` -### CRAN Mirror Issues In the event you get a message that you need to select a CRAN mirror first. You can specify a mirror by adding in the repo parameter. @@ -108,7 +113,8 @@ buffers/buffer-tostring.js n=10000000 len=1024 arg=false: 3783071.1678948295 ### Running all benchmarks Similar to running individual benchmarks, a group of benchmarks can be executed -by using the `run.js` tool. Again this does not provide the statistical +by using the `run.js` tool. To see how to use this script, +run `node benchmark/run.js`. Again this does not provide the statistical information to make any conclusions. ```console @@ -135,18 +141,19 @@ It is possible to execute more groups by adding extra process arguments. $ node benchmark/run.js arrays buffers ``` -### Comparing node versions +### Comparing Node.js versions -To compare the effect of a new node version use the `compare.js` tool. This +To compare the effect of a new Node.js version use the `compare.js` tool. This will run each benchmark multiple times, making it possible to calculate -statistics on the performance measures. +statistics on the performance measures. To see how to use this script, +run `node benchmark/compare.js`. As an example on how to check for a possible performance improvement, the [#5134](https://github.com/nodejs/node/pull/5134) pull request will be used as an example. This pull request _claims_ to improve the performance of the `string_decoder` module. -First build two versions of node, one from the master branch (here called +First build two versions of Node.js, one from the master branch (here called `./node-master`) and another with the pull request applied (here called `./node-pr-5135`). @@ -219,7 +226,8 @@ It can be useful to compare the performance for different parameters, for example to analyze the time complexity. To do this use the `scatter.js` tool, this will run a benchmark multiple times -and generate a csv with the results. +and generate a csv with the results. To see how to use this script, +run `node benchmark/scatter.js`. ```console $ node benchmark/scatter.js benchmark/string_decoder/string-decoder.js > scatter.csv @@ -286,6 +294,8 @@ chunk encoding mean confidence.interval ## Creating a benchmark +### Basics of a benchmark + All benchmarks use the `require('../common.js')` module. This contains the `createBenchmark(main, configs[, options])` method which will setup your benchmark. @@ -369,7 +379,7 @@ function main(conf) { } ``` -## Creating HTTP benchmark +### Creating an HTTP benchmark The `bench` object returned by `createBenchmark` implements `http(options, callback)` method. It can be used to run external tool to From 66f9506c637887fc6e8b6c3d3aaff76d52822405 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 8 Feb 2017 01:15:03 +0800 Subject: [PATCH 058/164] doc: improve test/README.md * Add description about the test directory * Add link to the test writing guide and the contributing guide * Use table to describe the directory layout and CI info PR-URL: https://github.com/nodejs/node/pull/11237 Fixes: https://github.com/nodejs/node/issues/11190 Reviewed-By: James M Snell Reviewed-By: Andreas Madsen --- test/README.md | 281 +++++++++++++++++++++++++------------------------ 1 file changed, 144 insertions(+), 137 deletions(-) diff --git a/test/README.md b/test/README.md index 8affd257a7628e..b79a8efb795f44 100644 --- a/test/README.md +++ b/test/README.md @@ -1,147 +1,154 @@ -# Table of Contents -* [Test directories](#test-directories) -* [Common module API](#common-module-api) - -## Test Directories - -### abort - -Tests for when the `--abort-on-uncaught-exception` flag is used. - -| Runs on CI | -|:----------:| -| No | - -### addons - -Tests for [addon](https://nodejs.org/api/addons.html) functionality along with -some tests that require an addon to function properly. - - -| Runs on CI | -|:----------:| -| Yes | - -### cctest - -C++ test that is run as part of the build process. - -| Runs on CI | -|:----------:| -| Yes | - -### debugger - -Tests for [debugger](https://nodejs.org/api/debugger.html) functionality. - -| Runs on CI | -|:----------:| -| No | - -### disabled - -Tests that have been disabled from running for various reasons. - -| Runs on CI | -|:----------:| -| No | - -### fixtures - -Test fixtures used in various tests throughout the test suite. - -### gc - -Tests for garbage collection related functionality. - -| Runs on CI | -|:----------:| -| No | - +# Node.js Core Tests -### inspector +This folder contains code and data used to test the Node.js implementation. -Tests for the V8 inspector integration. +For a detailed guide on how to write tests in this +directory, see [the guide on writing tests](../doc/guides/writing-tests.md). -| Runs on CI | -|:----------:| -| Yes | +On how to run tests in this direcotry, see +[the contributing guide](../CONTRIBUTING.md#step-5-test). -### internet +## Table of Contents -Tests that make real outbound connections (mainly networking related modules). -Tests for networking related modules may also be present in other directories, -but those tests do not make outbound connections. - -| Runs on CI | -|:----------:| -| No | - -### known_issues - -Tests reproducing known issues within the system. - -| Runs on CI | -|:----------:| -| No | - -### message - -Tests for messages that are output for various conditions (`console.log`, -error messages etc.) - -| Runs on CI | -|:----------:| -| Yes | - -### parallel - -Various tests that are able to be run in parallel. - -| Runs on CI | -|:----------:| -| Yes | - -### pummel - -Various tests for various modules / system functionality operating under load. - -| Runs on CI | -|:----------:| -| No | - -### sequential - -Various tests that are run sequentially. - -| Runs on CI | -|:----------:| -| Yes | - -### testpy - -Test configuration utility used by various test suites. - -### tick-processor - -Tests for the V8 tick processor integration. The tests are for the logic in -`lib/internal/v8_prof_processor.js` and `lib/internal/v8_prof_polyfill.js`. The -tests confirm that the profile processor packages the correct set of scripts -from V8 and introduces the correct platform specific logic. - -| Runs on CI | -|:----------:| -| No | - -### timers - -Tests for [timing utilities](https://nodejs.org/api/timers.html) (`setTimeout` -and `setInterval`). +* [Test directories](#test-directories) +* [Common module API](#common-module-api) -| Runs on CI | -|:----------:| -| No | +## Test Directories + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectoryRuns on CIPurpose
abortNo + Tests for when the --abort-on-uncaught-exception + flag is used. +
addonsYes + Tests for addon + functionality along with some tests that require an addon to function + properly. +
cctestYes + C++ test that is run as part of the build process. +
debuggerNo + Tests for debugger + functionality along with some tests that require an addon to function + properly. +
disabledNo + Tests that have been disabled from running for various reasons. +
fixturesTest fixtures used in various tests throughout the test suite.
gcNoTests for garbage collection related functionality.
inspectorYesTests for the V8 inspector integration.
internetNo + Tests that make real outbound connections (mainly networking related + modules). Tests for networking related modules may also be present in + other directories, but those tests do not make outbound connections. +
known_issuesNoTests reproducing known issues within the system.
messageYes + Tests for messages that are output for various conditions + (console.log, error messages etc.)
parallelYesVarious tests that are able to be run in parallel.
pummelNo + Various tests for various modules / system functionality operating + under load. +
sequentialYes + Various tests that are run sequentially. +
testpy + Test configuration utility used by various test suites. +
tick-processorNo + Tests for the V8 tick processor integration. The tests are for the + logic in lib/internal/v8_prof_processor.js and + lib/internal/v8_prof_polyfill.js. The tests confirm that + the profile processor packages the correct set of scripts from V8 and + introduces the correct platform specific logic. +
timersNo + Tests for + timing utilities + (setTimeout and setInterval). +
## Common module API From ca1bae6f3eebab5ccbb22f6ea8676378d4946549 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 14 Feb 2017 12:46:21 +0300 Subject: [PATCH 059/164] test: remove unused args and comparison fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unused arguments and change non-strict comparison to the strict one in test. PR-URL: https://github.com/nodejs/node/pull/11396 Reviewed-By: Michaël Zasso Reviewed-By: Yuta Hiroto Reviewed-By: James M Snell Reviewed-By: Rich Trott Reviewed-By: Colin Ihrig --- test/internet/test-dgram-multicast-multi-process.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/internet/test-dgram-multicast-multi-process.js b/test/internet/test-dgram-multicast-multi-process.js index 46f47a5982977e..793d22bd4c137e 100644 --- a/test/internet/test-dgram-multicast-multi-process.js +++ b/test/internet/test-dgram-multicast-multi-process.js @@ -22,14 +22,14 @@ if (common.inFreeBSDJail) { return; } -function launchChildProcess(index) { +function launchChildProcess() { const worker = fork(__filename, ['child']); workers[worker.pid] = worker; worker.messagesReceived = []; // Handle the death of workers. - worker.on('exit', function(code, signal) { + worker.on('exit', function(code) { // Don't consider this the true death if the worker has finished // successfully or if the exit code is 0. if (worker.isDone || code === 0) { @@ -189,7 +189,7 @@ if (process.argv[2] === 'child') { process.send({ message: buf.toString() }); - if (receivedMessages.length == messages.length) { + if (receivedMessages.length === messages.length) { // .dropMembership() not strictly needed but here as a sanity check. listenSocket.dropMembership(LOCAL_BROADCAST_HOST); process.nextTick(function() { From f55c628b2ab60d6db6e75eb5f1af86be7d821c1b Mon Sep 17 00:00:00 2001 From: James M Snell Date: Tue, 14 Feb 2017 21:02:50 -0800 Subject: [PATCH 060/164] vm: refactor vm module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch to the more efficient module.exports = {} pattern. PR-URL: https://github.com/nodejs/node/pull/11392 Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig --- lib/vm.js | 63 ++++++++++--------- test/message/eval_messages.out | 14 +++-- test/message/stdin_messages.out | 18 +++--- .../undefined_reference_in_new_context.out | 4 +- test/message/vm_display_runtime_error.out | 4 +- test/message/vm_display_syntax_error.out | 9 ++- .../message/vm_dont_display_runtime_error.out | 3 +- test/message/vm_dont_display_syntax_error.out | 5 +- 8 files changed, 66 insertions(+), 54 deletions(-) diff --git a/lib/vm.js b/lib/vm.js index cf672fbbc14871..e2b6c60d1a83f6 100644 --- a/lib/vm.js +++ b/lib/vm.js @@ -34,17 +34,11 @@ Script.prototype.runInContext = function(contextifiedSandbox, options) { }; Script.prototype.runInNewContext = function(sandbox, options) { - var context = exports.createContext(sandbox); + var context = createContext(sandbox); return this.runInContext(context, options); }; -exports.Script = Script; - -exports.createScript = function(code, options) { - return new Script(code, options); -}; - -exports.createContext = function(sandbox) { +function createContext(sandbox) { if (sandbox === undefined) { sandbox = {}; } else if (binding.isContext(sandbox)) { @@ -53,28 +47,11 @@ exports.createContext = function(sandbox) { binding.makeContext(sandbox); return sandbox; -}; - -exports.runInDebugContext = function(code) { - return binding.runInDebugContext(code); -}; - -exports.runInContext = function(code, contextifiedSandbox, options) { - var script = new Script(code, options); - return script.runInContext(contextifiedSandbox, options); -}; - -exports.runInNewContext = function(code, sandbox, options) { - var script = new Script(code, options); - return script.runInNewContext(sandbox, options); -}; - -exports.runInThisContext = function(code, options) { - var script = new Script(code, options); - return script.runInThisContext(options); -}; +} -exports.isContext = binding.isContext; +function createScript(code, options) { + return new Script(code, options); +} // Remove all SIGINT listeners and re-attach them after the wrapped function // has executed, so that caught SIGINT are handled by the listeners again. @@ -100,3 +77,31 @@ function sigintHandlersWrap(fn, thisArg, argsArray) { } } } + +function runInDebugContext(code) { + return binding.runInDebugContext(code); +} + +function runInContext(code, contextifiedSandbox, options) { + return createScript(code, options) + .runInContext(contextifiedSandbox, options); +} + +function runInNewContext(code, sandbox, options) { + return createScript(code, options).runInNewContext(sandbox, options); +} + +function runInThisContext(code, options) { + return createScript(code, options).runInThisContext(options); +} + +module.exports = { + Script, + createContext, + createScript, + runInDebugContext, + runInContext, + runInNewContext, + runInThisContext, + isContext: binding.isContext +}; diff --git a/test/message/eval_messages.out b/test/message/eval_messages.out index 44965be374bac5..ba0c35431c6907 100644 --- a/test/message/eval_messages.out +++ b/test/message/eval_messages.out @@ -3,7 +3,8 @@ with(this){__filename} ^^^^ SyntaxError: Strict mode code may not include a with statement - at Object.exports.runInThisContext (vm.js:*) + at createScript (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at Immediate. (bootstrap_node.js:*:*) @@ -15,10 +16,11 @@ SyntaxError: Strict mode code may not include a with statement [eval]:1 throw new Error("hello") ^ + Error: hello at [eval]:1:7 at ContextifyScript.Script.runInThisContext (vm.js:*) - at Object.exports.runInThisContext (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at Immediate. (bootstrap_node.js:*:*) @@ -28,10 +30,11 @@ Error: hello [eval]:1 throw new Error("hello") ^ + Error: hello at [eval]:1:7 at ContextifyScript.Script.runInThisContext (vm.js:*) - at Object.exports.runInThisContext (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at Immediate. (bootstrap_node.js:*:*) @@ -42,20 +45,23 @@ Error: hello [eval]:1 var x = 100; y = x; ^ + ReferenceError: y is not defined at [eval]:1:16 at ContextifyScript.Script.runInThisContext (vm.js:*) - at Object.exports.runInThisContext (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. ([eval]-wrapper:*:*) at Module._compile (module.js:*:*) at Immediate. (bootstrap_node.js:*:*) at runCallback (timers.js:*:*) at tryOnImmediate (timers.js:*:*) at processImmediate [as _immediateCallback] (timers.js:*:*) + [eval]:1 var ______________________________________________; throw 10 ^ 10 + [eval]:1 var ______________________________________________; throw 10 ^ diff --git a/test/message/stdin_messages.out b/test/message/stdin_messages.out index 828bee92cb6f7f..b4c51d7ad567f0 100644 --- a/test/message/stdin_messages.out +++ b/test/message/stdin_messages.out @@ -1,10 +1,10 @@ [stdin] - [stdin]:1 with(this){__filename} ^^^^ SyntaxError: Strict mode code may not include a with statement - at Object.exports.runInThisContext (vm.js:*) + at createScript (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at Immediate. (bootstrap_node.js:*:*) @@ -13,28 +13,28 @@ SyntaxError: Strict mode code may not include a with statement at processImmediate [as _immediateCallback] (timers.js:*:*) 42 42 - [stdin]:1 throw new Error("hello") ^ + Error: hello - at [stdin]:1:* + at [stdin]:1:7 at ContextifyScript.Script.runInThisContext (vm.js:*) - at Object.exports.runInThisContext (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at Immediate. (bootstrap_node.js:*:*) at runCallback (timers.js:*:*) at tryOnImmediate (timers.js:*:*) at processImmediate [as _immediateCallback] (timers.js:*:*) - [stdin]:1 throw new Error("hello") ^ + Error: hello at [stdin]:1:* at ContextifyScript.Script.runInThisContext (vm.js:*) - at Object.exports.runInThisContext (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at Immediate. (bootstrap_node.js:*:*) @@ -42,14 +42,14 @@ Error: hello at tryOnImmediate (timers.js:*:*) at processImmediate [as _immediateCallback] (timers.js:*:*) 100 - [stdin]:1 var x = 100; y = x; ^ + ReferenceError: y is not defined at [stdin]:1:16 at ContextifyScript.Script.runInThisContext (vm.js:*) - at Object.exports.runInThisContext (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. ([stdin]-wrapper:*:*) at Module._compile (module.js:*:*) at Immediate. (bootstrap_node.js:*:*) diff --git a/test/message/undefined_reference_in_new_context.out b/test/message/undefined_reference_in_new_context.out index 04b9a21acdeb1f..93bc1dcc99c3e1 100644 --- a/test/message/undefined_reference_in_new_context.out +++ b/test/message/undefined_reference_in_new_context.out @@ -1,13 +1,13 @@ before - evalmachine.:1 foo.bar = 5; ^ + ReferenceError: foo is not defined at evalmachine.:1:1 at ContextifyScript.Script.runInContext (vm.js:*) at ContextifyScript.Script.runInNewContext (vm.js:*) - at Object.exports.runInNewContext (vm.js:*) + at Object.runInNewContext (vm.js:*) at Object. (*test*message*undefined_reference_in_new_context.js:*) at Module._compile (module.js:*) at *..js (module.js:*) diff --git a/test/message/vm_display_runtime_error.out b/test/message/vm_display_runtime_error.out index b7fe798cd29adb..d5cf1d3ee50dbb 100644 --- a/test/message/vm_display_runtime_error.out +++ b/test/message/vm_display_runtime_error.out @@ -1,12 +1,12 @@ beginning - test.vm:1 throw new Error("boo!") ^ + Error: boo! at test.vm:1:7 at ContextifyScript.Script.runInThisContext (vm.js:*) - at Object.exports.runInThisContext (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. (*test*message*vm_display_runtime_error.js:*) at Module._compile (module.js:*) at Object.Module._extensions..js (module.js:*) diff --git a/test/message/vm_display_syntax_error.out b/test/message/vm_display_syntax_error.out index 8917f2f9d0cbb7..9ec62eacb895f0 100644 --- a/test/message/vm_display_syntax_error.out +++ b/test/message/vm_display_syntax_error.out @@ -1,10 +1,10 @@ beginning - foo.vm:1 var 4; ^ SyntaxError: Unexpected number - at Object.exports.runInThisContext (vm.js:*) + at createScript (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. (*test*message*vm_display_syntax_error.js:*) at Module._compile (module.js:*) at Object.Module._extensions..js (module.js:*) @@ -13,12 +13,12 @@ SyntaxError: Unexpected number at Function.Module._load (module.js:*) at Module.runMain (module.js:*) at run (bootstrap_node.js:*) - at startup (bootstrap_node.js:*) test.vm:1 var 5; ^ SyntaxError: Unexpected number - at Object.exports.runInThisContext (vm.js:*) + at createScript (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. (*test*message*vm_display_syntax_error.js:*) at Module._compile (module.js:*) at Object.Module._extensions..js (module.js:*) @@ -27,4 +27,3 @@ SyntaxError: Unexpected number at Function.Module._load (module.js:*) at Module.runMain (module.js:*) at run (bootstrap_node.js:*) - at startup (bootstrap_node.js:*) diff --git a/test/message/vm_dont_display_runtime_error.out b/test/message/vm_dont_display_runtime_error.out index e0795d1f535e35..a60bde2a8c29ea 100644 --- a/test/message/vm_dont_display_runtime_error.out +++ b/test/message/vm_dont_display_runtime_error.out @@ -3,10 +3,11 @@ middle test.vm:1 throw new Error("boo!") ^ + Error: boo! at test.vm:1:7 at ContextifyScript.Script.runInThisContext (vm.js:*) - at Object.exports.runInThisContext (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. (*test*message*vm_dont_display_runtime_error.js:*) at Module._compile (module.js:*) at Object.Module._extensions..js (module.js:*) diff --git a/test/message/vm_dont_display_syntax_error.out b/test/message/vm_dont_display_syntax_error.out index de3daab301890e..bc5b180dc1fa2a 100644 --- a/test/message/vm_dont_display_syntax_error.out +++ b/test/message/vm_dont_display_syntax_error.out @@ -3,8 +3,10 @@ middle test.vm:1 var 5; ^ + SyntaxError: Unexpected number - at Object.exports.runInThisContext (vm.js:*) + at createScript (vm.js:*) + at Object.runInThisContext (vm.js:*) at Object. (*test*message*vm_dont_display_syntax_error.js:*) at Module._compile (module.js:*) at Object.Module._extensions..js (module.js:*) @@ -13,4 +15,3 @@ SyntaxError: Unexpected number at Function.Module._load (module.js:*) at Module.runMain (module.js:*) at run (bootstrap_node.js:*) - at startup (bootstrap_node.js:*) From 0240eb99a29c3e3719f500040cb965d0d85f4734 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 16 Feb 2017 15:04:29 -0500 Subject: [PATCH 061/164] child_process: remove empty if condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit replaces an empty if-else-if with a single if condition. PR-URL: https://github.com/nodejs/node/pull/11427 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Michaël Zasso Reviewed-By: Santiago Gimeno --- lib/child_process.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/child_process.js b/lib/child_process.js index 76ec6d3d0f9437..e5b35e7add952d 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -196,9 +196,7 @@ exports.execFile = function(file /*, args, options, callback*/) { stderr = Buffer.concat(_stderr); } - if (ex) { - // Will be handled later - } else if (code === 0 && signal === null) { + if (!ex && code === 0 && signal === null) { callback(null, stdout, stderr); return; } From b457f38e686f729aba56324021fcd9680cfe96f2 Mon Sep 17 00:00:00 2001 From: xiaoyu <306766053@qq.com> Date: Fri, 17 Feb 2017 00:24:39 +0800 Subject: [PATCH 062/164] test: add coverage for utf8CheckIncomplete() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds code coverage to utf8CheckIncomplete(), when the lastNeed is greater than buffer length. PR-URL: https://github.com/nodejs/node/pull/11419 Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Michael Dawson Reviewed-By: Michaël Zasso --- test/parallel/test-string-decoder.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/parallel/test-string-decoder.js b/test/parallel/test-string-decoder.js index a8fdb999a0923f..07883a14ec8b7a 100644 --- a/test/parallel/test-string-decoder.js +++ b/test/parallel/test-string-decoder.js @@ -87,6 +87,9 @@ assert.strictEqual(decoder.write(Buffer.from('F1', 'hex')), ''); assert.strictEqual(decoder.write(Buffer.from('41F2', 'hex')), '\ufffdA'); assert.strictEqual(decoder.end(), '\ufffd'); +// Additional utf8Text test +decoder = new StringDecoder('utf8'); +assert.strictEqual(decoder.text(Buffer.from([0x41]), 2), ''); // Additional UTF-16LE surrogate pair tests decoder = new StringDecoder('utf16le'); From c942e2037cdfe18b65c334fd278ad6042d1fd7dd Mon Sep 17 00:00:00 2001 From: Arseniy Maximov Date: Tue, 14 Feb 2017 06:39:24 +0300 Subject: [PATCH 063/164] child_process: refactor internal/child_process.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Prefer === to == where possible * Remove condition that will always be false * Prefer for-loop statements to forEach where possible for perfomance reasons PR-URL: https://github.com/nodejs/node/pull/11366 Reviewed-By: Colin Ihrig Reviewed-By: Sam Roberts Reviewed-By: Michaël Zasso Reviewed-By: Brian White --- lib/internal/child_process.js | 46 ++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index b3023f6a46d9b7..da6ed289e8c587 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -230,12 +230,16 @@ util.inherits(ChildProcess, EventEmitter); function flushStdio(subprocess) { - if (subprocess.stdio == null) return; - subprocess.stdio.forEach(function(stream, fd, stdio) { + const stdio = subprocess.stdio; + + if (stdio == null) return; + + for (var i = 0; i < stdio.length; i++) { + const stream = stdio[i]; if (!stream || !stream.readable || stream._readableState.readableListening) - return; + continue; stream.resume(); - }); + } } @@ -268,6 +272,7 @@ ChildProcess.prototype.spawn = function(options) { const self = this; var ipc; var ipcFd; + var i; // If no `stdio` option was given - use default var stdio = options.stdio || 'pipe'; @@ -302,11 +307,12 @@ ChildProcess.prototype.spawn = function(options) { if (err !== uv.UV_ENOENT) return err; } else if (err) { // Close all opened fds on error - stdio.forEach(function(stdio) { - if (stdio.type === 'pipe') { - stdio.handle.close(); + for (i = 0; i < stdio.length; i++) { + const stream = stdio[i]; + if (stream.type === 'pipe') { + stream.handle.close(); } - }); + } this._handle.close(); this._handle = null; @@ -315,27 +321,29 @@ ChildProcess.prototype.spawn = function(options) { this.pid = this._handle.pid; - stdio.forEach(function(stdio, i) { - if (stdio.type === 'ignore') return; + for (i = 0; i < stdio.length; i++) { + const stream = stdio[i]; + if (stream.type === 'ignore') continue; - if (stdio.ipc) { + if (stream.ipc) { self._closesNeeded++; - return; + continue; } - if (stdio.handle) { + if (stream.handle) { // when i === 0 - we're dealing with stdin // (which is the only one writable pipe) - stdio.socket = createSocket(self.pid !== 0 ? stdio.handle : null, i > 0); + stream.socket = createSocket(self.pid !== 0 ? + stream.handle : null, i > 0); if (i > 0 && self.pid !== 0) { self._closesNeeded++; - stdio.socket.on('close', function() { + stream.socket.on('close', function() { maybeClose(self); }); } } - }); + } this.stdin = stdio.length >= 1 && stdio[0].socket !== undefined ? stdio[0].socket : null; @@ -797,11 +805,11 @@ function _validateStdio(stdio, sync) { } // Defaults - if (stdio === null || stdio === undefined) { + if (stdio == null) { stdio = i < 3 ? 'pipe' : 'ignore'; } - if (stdio === null || stdio === 'ignore') { + if (stdio === 'ignore') { acc.push({type: 'ignore'}); } else if (stdio === 'pipe' || typeof stdio === 'number' && stdio < 0) { var a = { @@ -887,7 +895,7 @@ function getSocketList(type, slave, key) { function maybeClose(subprocess) { subprocess._closesGot++; - if (subprocess._closesGot == subprocess._closesNeeded) { + if (subprocess._closesGot === subprocess._closesNeeded) { subprocess.emit('close', subprocess.exitCode, subprocess.signalCode); } } From 539e83a8207d801c567a280e9ad1db136e34b46b Mon Sep 17 00:00:00 2001 From: Yang Guo Date: Thu, 2 Feb 2017 09:02:46 +0100 Subject: [PATCH 064/164] src: remove usage of deprecated debug API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Debug::GetMirror is used in contextify to force loading of the debug context. There is a better way to achieve this. PR-URL: https://github.com/nodejs/node/pull/11437 Reviewed-By: Anna Henningsen Reviewed-By: Evan Lucas Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell Reviewed-By: Michael Dawson Reviewed-By: Michaël Zasso --- src/node_contextify.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/node_contextify.cc b/src/node_contextify.cc index ff66ffdaaa0467..9b0ab4ea262d41 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -261,7 +261,8 @@ class ContextifyContext { Environment* env = Environment::GetCurrent(args); if (debug_context.IsEmpty()) { // Force-load the debug context. - Debug::GetMirror(args.GetIsolate()->GetCurrentContext(), args[0]); + auto dummy_event_listener = [] (const Debug::EventDetails&) {}; + Debug::SetDebugEventListener(args.GetIsolate(), dummy_event_listener); debug_context = Debug::GetDebugContext(args.GetIsolate()); CHECK(!debug_context.IsEmpty()); // Ensure that the debug context has an Environment assigned in case From 1d86a9f5eb011663340d6621db20cf003f025f63 Mon Sep 17 00:00:00 2001 From: Ali Ijaz Sheikh Date: Tue, 17 Jan 2017 12:54:29 -0800 Subject: [PATCH 065/164] test: fix over-dependence on native promise impl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In later versions of V8, the stack trace will be different than our current expectations for Promise methods. PR-URL: https://github.com/nodejs/node/pull/11437 Reviewed-By: Anna Henningsen Reviewed-By: Evan Lucas Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell Reviewed-By: Michael Dawson Reviewed-By: Michaël Zasso --- test/message/unhandled_promise_trace_warnings.out | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/message/unhandled_promise_trace_warnings.out b/test/message/unhandled_promise_trace_warnings.out index 80cf948cf118a3..aab7ce604a4d1b 100644 --- a/test/message/unhandled_promise_trace_warnings.out +++ b/test/message/unhandled_promise_trace_warnings.out @@ -23,8 +23,8 @@ at getAsynchronousRejectionWarningObject (internal/process/promises.js:*) at rejectionHandled (internal/process/promises.js:*) at * - at Promise.then (native) - at Promise.catch (native) + at Promise.then * + at Promise.catch * at Immediate.setImmediate (*test*message*unhandled_promise_trace_warnings.js:*) at * at * From 95bee8f20211fbaa678b07ddfff61b488d9520cf Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 17 Feb 2017 16:49:38 -0800 Subject: [PATCH 066/164] util: eliminate unnecessary exports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The getHiddenValue and setHiddenValue functions are exported from internalUtil for no really good reason PR-URL: https://github.com/nodejs/node/pull/11451 Reviewed-By: Michaël Zasso Reviewed-By: Luigi Pinca --- lib/internal/util.js | 9 +++---- ...test-internal-util-decorate-error-stack.js | 26 ++++++++++--------- test/parallel/test-util-internal.js | 13 +++++----- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/lib/internal/util.js b/lib/internal/util.js index 42a0922d304970..cc66c7fb04ae9f 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -6,9 +6,6 @@ const prefix = `(${process.release.name}:${process.pid}) `; const kArrowMessagePrivateSymbolIndex = binding['arrow_message_private_symbol']; const kDecoratedPrivateSymbolIndex = binding['decorated_private_symbol']; -exports.getHiddenValue = binding.getHiddenValue; -exports.setHiddenValue = binding.setHiddenValue; - // The `buffer` module uses this. Defining it here instead of in the public // `util` module makes it accessible without having to `require('util')` there. exports.customInspectSymbol = Symbol('util.inspect.custom'); @@ -77,14 +74,14 @@ exports._deprecate = function(fn, msg) { exports.decorateErrorStack = function decorateErrorStack(err) { if (!(exports.isError(err) && err.stack) || - exports.getHiddenValue(err, kDecoratedPrivateSymbolIndex) === true) + binding.getHiddenValue(err, kDecoratedPrivateSymbolIndex) === true) return; - const arrow = exports.getHiddenValue(err, kArrowMessagePrivateSymbolIndex); + const arrow = binding.getHiddenValue(err, kArrowMessagePrivateSymbolIndex); if (arrow) { err.stack = arrow + err.stack; - exports.setHiddenValue(err, kDecoratedPrivateSymbolIndex, true); + binding.setHiddenValue(err, kDecoratedPrivateSymbolIndex, true); } }; diff --git a/test/parallel/test-internal-util-decorate-error-stack.js b/test/parallel/test-internal-util-decorate-error-stack.js index caf31cb2650f17..7028188f6cd4bf 100644 --- a/test/parallel/test-internal-util-decorate-error-stack.js +++ b/test/parallel/test-internal-util-decorate-error-stack.js @@ -10,16 +10,18 @@ const path = require('path'); const kArrowMessagePrivateSymbolIndex = binding['arrow_message_private_symbol']; const kDecoratedPrivateSymbolIndex = binding['decorated_private_symbol']; +const decorateErrorStack = internalUtil.decorateErrorStack; + assert.doesNotThrow(function() { - internalUtil.decorateErrorStack(); - internalUtil.decorateErrorStack(null); - internalUtil.decorateErrorStack(1); - internalUtil.decorateErrorStack(true); + decorateErrorStack(); + decorateErrorStack(null); + decorateErrorStack(1); + decorateErrorStack(true); }); // Verify that a stack property is not added to non-Errors const obj = {}; -internalUtil.decorateErrorStack(obj); +decorateErrorStack(obj); assert.strictEqual(obj.stack, undefined); // Verify that the stack is decorated when possible @@ -43,8 +45,8 @@ assert(typeof err, 'object'); checkStack(err.stack); // Verify that the stack is only decorated once -internalUtil.decorateErrorStack(err); -internalUtil.decorateErrorStack(err); +decorateErrorStack(err); +decorateErrorStack(err); checkStack(err.stack); // Verify that the stack is only decorated once for uncaught exceptions @@ -58,7 +60,7 @@ checkStack(result.stderr); // Verify that the stack is unchanged when there is no arrow message err = new Error('foo'); let originalStack = err.stack; -internalUtil.decorateErrorStack(err); +decorateErrorStack(err); assert.strictEqual(originalStack, err.stack); // Verify that the arrow message is added to the start of the stack when it @@ -67,9 +69,9 @@ const arrowMessage = 'arrow_message'; err = new Error('foo'); originalStack = err.stack; -internalUtil.setHiddenValue(err, kArrowMessagePrivateSymbolIndex, arrowMessage); -internalUtil.decorateErrorStack(err); +binding.setHiddenValue(err, kArrowMessagePrivateSymbolIndex, arrowMessage); +decorateErrorStack(err); assert.strictEqual(err.stack, `${arrowMessage}${originalStack}`); -assert.strictEqual(internalUtil - .getHiddenValue(err, kDecoratedPrivateSymbolIndex), true); +assert.strictEqual( + binding.getHiddenValue(err, kDecoratedPrivateSymbolIndex), true); diff --git a/test/parallel/test-util-internal.js b/test/parallel/test-util-internal.js index aa475db4a1b7a7..9be642a8ffe715 100644 --- a/test/parallel/test-util-internal.js +++ b/test/parallel/test-util-internal.js @@ -4,7 +4,6 @@ const common = require('../common'); const path = require('path'); const assert = require('assert'); -const internalUtil = require('internal/util'); const spawnSync = require('child_process').spawnSync; const binding = process.binding('util'); @@ -12,13 +11,13 @@ const kArrowMessagePrivateSymbolIndex = binding['arrow_message_private_symbol']; function getHiddenValue(obj, index) { return function() { - internalUtil.getHiddenValue(obj, index); + binding.getHiddenValue(obj, index); }; } function setHiddenValue(obj, index, val) { return function() { - internalUtil.setHiddenValue(obj, index, val); + binding.setHiddenValue(obj, index, val); }; } @@ -31,7 +30,7 @@ assert.throws(getHiddenValue({}), /index must be an uint32/); assert.throws(getHiddenValue({}, null), /index must be an uint32/); assert.throws(getHiddenValue({}, []), /index must be an uint32/); assert.deepStrictEqual( - internalUtil.getHiddenValue({}, kArrowMessagePrivateSymbolIndex), + binding.getHiddenValue({}, kArrowMessagePrivateSymbolIndex), undefined); assert.throws(setHiddenValue(), /obj must be an object/); @@ -44,10 +43,10 @@ assert.throws(setHiddenValue({}, null), /index must be an uint32/); assert.throws(setHiddenValue({}, []), /index must be an uint32/); const obj = {}; assert.strictEqual( - internalUtil.setHiddenValue(obj, kArrowMessagePrivateSymbolIndex, 'bar'), + binding.setHiddenValue(obj, kArrowMessagePrivateSymbolIndex, 'bar'), true); assert.strictEqual( - internalUtil.getHiddenValue(obj, kArrowMessagePrivateSymbolIndex), + binding.getHiddenValue(obj, kArrowMessagePrivateSymbolIndex), 'bar'); let arrowMessage; @@ -56,7 +55,7 @@ try { require(path.join(common.fixturesDir, 'syntax', 'bad_syntax')); } catch (err) { arrowMessage = - internalUtil.getHiddenValue(err, kArrowMessagePrivateSymbolIndex); + binding.getHiddenValue(err, kArrowMessagePrivateSymbolIndex); } assert(/bad_syntax\.js:1/.test(arrowMessage)); From 3d133ebd3d2d7a4f438e11a2c3aed5e754a36085 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 17 Feb 2017 15:25:28 -0800 Subject: [PATCH 067/164] util, debugger: remove internalUtil.error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The internalUtil.error() function was only used by _debugger.js. PR-URL: https://github.com/nodejs/node/pull/11448 Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- lib/_debugger.js | 16 ++++++++++------ lib/internal/util.js | 13 ------------- test/parallel/test-util-internal.js | 10 ---------- 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/lib/_debugger.js b/lib/_debugger.js index d3bf1f9ffa2dab..090c9e5dc650e1 100644 --- a/lib/_debugger.js +++ b/lib/_debugger.js @@ -1,6 +1,5 @@ 'use strict'; -const internalUtil = require('internal/util'); const util = require('util'); const path = require('path'); const net = require('net'); @@ -11,6 +10,11 @@ const inherits = util.inherits; const assert = require('assert'); const spawn = require('child_process').spawn; const Buffer = require('buffer').Buffer; +const prefix = `(${process.release.name}:${process.pid}) `; + +function error(msg) { + console.error(`${prefix}${msg}`); +} exports.start = function(argv, stdin, stdout) { argv || (argv = process.argv.slice(2)); @@ -32,8 +36,8 @@ exports.start = function(argv, stdin, stdout) { stdin.resume(); process.on('uncaughtException', function(e) { - internalUtil.error('There was an internal error in Node\'s debugger. ' + - 'Please report this bug.'); + error('There was an internal error in Node\'s debugger. ' + + 'Please report this bug.'); console.error(e.message); console.error(e.stack); if (interface_.child) interface_.child.kill(); @@ -521,7 +525,7 @@ Client.prototype.mirrorObject = function(handle, depth, cb) { cb = cb || function() {}; this.reqLookup(propertyRefs, function(err, res) { if (err) { - internalUtil.error('problem with reqLookup'); + error('problem with reqLookup'); cb(null, handle); return; } @@ -1672,7 +1676,7 @@ Interface.prototype.trySpawn = function(cb) { process._debugProcess(pid); } catch (e) { if (e.code === 'ESRCH') { - internalUtil.error(`Target process: ${pid} doesn't exist.`); + error(`Target process: ${pid} doesn't exist.`); process.exit(1); } throw e; @@ -1741,7 +1745,7 @@ Interface.prototype.trySpawn = function(cb) { function connectError() { // If it's failed to connect 10 times then print failed message if (connectionAttempts >= 10) { - internalUtil.error(' failed to connect, please retry'); + error(' failed to connect, please retry'); process.exit(1); } setTimeout(attemptConnect, 500); diff --git a/lib/internal/util.js b/lib/internal/util.js index cc66c7fb04ae9f..4f7e9924a94186 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -16,19 +16,6 @@ exports.deprecate = function(fn, msg) { return exports._deprecate(fn, msg); }; -exports.error = function(msg) { - const fmt = `${prefix}${msg}`; - if (arguments.length > 1) { - const args = new Array(arguments.length); - args[0] = fmt; - for (var i = 1; i < arguments.length; ++i) - args[i] = arguments[i]; - console.error.apply(console, args); - } else { - console.error(fmt); - } -}; - exports.trace = function(msg) { console.trace(`${prefix}${msg}`); }; diff --git a/test/parallel/test-util-internal.js b/test/parallel/test-util-internal.js index 9be642a8ffe715..5131353abbef9b 100644 --- a/test/parallel/test-util-internal.js +++ b/test/parallel/test-util-internal.js @@ -4,7 +4,6 @@ const common = require('../common'); const path = require('path'); const assert = require('assert'); -const spawnSync = require('child_process').spawnSync; const binding = process.binding('util'); const kArrowMessagePrivateSymbolIndex = binding['arrow_message_private_symbol']; @@ -59,12 +58,3 @@ try { } assert(/bad_syntax\.js:1/.test(arrowMessage)); - -const args = [ - '--expose-internals', - '-e', - "require('internal/util').error('foo %d', 5)" -]; -const result = spawnSync(process.argv[0], args, { encoding: 'utf8' }); -assert.strictEqual(result.stderr.indexOf('%'), -1); -assert(/foo 5/.test(result.stderr)); From a523482cca77168fde805964f8e4737ec59396b4 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Thu, 16 Feb 2017 15:52:47 -0800 Subject: [PATCH 068/164] test: enhance test-common.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor test-common.js so that global leak detection does not need to be disabled * add test for common.fail() PR-URL: https://github.com/nodejs/node/pull/11433 Reviewed-By: James M Snell Reviewed-By: Gibson Fahnestock Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: Santiago Gimeno Reviewed-By: Michaël Zasso --- test/parallel/test-common.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-common.js b/test/parallel/test-common.js index 17f41840e4ffa5..67e5e6d8b5741b 100644 --- a/test/parallel/test-common.js +++ b/test/parallel/test-common.js @@ -2,10 +2,14 @@ const common = require('../common'); const assert = require('assert'); -common.globalCheck = false; + +// test for leaked global detection global.gc = 42; // Not a valid global unless --expose_gc is set. assert.deepStrictEqual(common.leakedGlobals(), ['gc']); +delete global.gc; + +// common.mustCall() tests assert.throws(function() { common.mustCall(function() {}, 'foo'); }, /^TypeError: Invalid expected value: foo$/); @@ -13,3 +17,10 @@ assert.throws(function() { assert.throws(function() { common.mustCall(function() {}, /foo/); }, /^TypeError: Invalid expected value: \/foo\/$/); + + +// common.fail() tests +assert.throws( + () => { common.fail('fhqwhgads'); }, + /^AssertionError: fhqwhgads$/ +); From c37e2b7690ca6a049badb012c88ad31ad408ab04 Mon Sep 17 00:00:00 2001 From: Yuta Hiroto Date: Sat, 18 Feb 2017 15:53:01 +0900 Subject: [PATCH 069/164] test: add test cases for path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add test cases for the following line. https://github.com/nodejs/node/blob/0f2f8ef/lib/path.js#L1364 https://github.com/nodejs/node/blob/0f2f8ef/lib/path.js#L1347 PR-URL: https://github.com/nodejs/node/pull/11453 Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- test/parallel/test-path.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/parallel/test-path.js b/test/parallel/test-path.js index 42a54b1707d0c2..3c5374175abd8e 100644 --- a/test/parallel/test-path.js +++ b/test/parallel/test-path.js @@ -10,6 +10,7 @@ const failures = []; // path.basename tests assert.strictEqual(path.basename(f), 'test-path.js'); assert.strictEqual(path.basename(f, '.js'), 'test-path'); +assert.strictEqual(path.basename('.js', '.js'), ''); assert.strictEqual(path.basename(''), ''); assert.strictEqual(path.basename('/dir/basename.ext'), 'basename.ext'); assert.strictEqual(path.basename('/basename.ext'), 'basename.ext'); @@ -74,6 +75,7 @@ assert.strictEqual(path.posix.dirname('/a'), '/'); assert.strictEqual(path.posix.dirname(''), '.'); assert.strictEqual(path.posix.dirname('/'), '/'); assert.strictEqual(path.posix.dirname('////'), '/'); +assert.strictEqual(path.posix.dirname('//a'), '//'); assert.strictEqual(path.posix.dirname('foo'), '.'); assert.strictEqual(path.win32.dirname('c:\\'), 'c:\\'); From 7b8087630f68a92768d5aeb78ee183062e80d191 Mon Sep 17 00:00:00 2001 From: Arseniy Maximov Date: Thu, 16 Feb 2017 23:29:23 +0300 Subject: [PATCH 070/164] test: refactor test-http-response-splitting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * move repeated code to function * remove unneeded `common.mustCall()` usage with function arguments that are not callbacks * add error message checking PR-URL: https://github.com/nodejs/node/pull/11429 Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: Michaël Zasso Reviewed-By: Сковорода Никита Андреевич --- test/parallel/test-http-response-splitting.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/parallel/test-http-response-splitting.js b/test/parallel/test-http-response-splitting.js index f6c3a04064ec1c..e6927bc1e63f77 100644 --- a/test/parallel/test-http-response-splitting.js +++ b/test/parallel/test-http-response-splitting.js @@ -19,23 +19,23 @@ const y = 'foo⠊Set-Cookie: foo=bar'; let count = 0; +function test(res, code, header) { + assert.throws(() => { + res.writeHead(code, header); + }, /^TypeError: The header content contains invalid characters$/); +} + const server = http.createServer((req, res) => { switch (count++) { case 0: const loc = url.parse(req.url, true).query.lang; - assert.throws(common.mustCall(() => { - res.writeHead(302, {Location: `/foo?lang=${loc}`}); - })); + test(res, 302, {Location: `/foo?lang=${loc}`}); break; case 1: - assert.throws(common.mustCall(() => { - res.writeHead(200, {'foo': x}); - })); + test(res, 200, {'foo': x}); break; case 2: - assert.throws(common.mustCall(() => { - res.writeHead(200, {'foo': y}); - })); + test(res, 200, {'foo': y}); break; default: common.fail('should not get to here.'); From da10e2649db94c3134a4043d1803247e9d83701a Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Fri, 17 Feb 2017 13:40:31 -0800 Subject: [PATCH 071/164] test: add error checking in callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add assert.ifError() for test-dgram-send-callback-buffer-length. PR-URL: https://github.com/nodejs/node/pull/11446 Reviewed-By: James M Snell Reviewed-By: Santiago Gimeno Reviewed-By: Yuta Hiroto Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- test/parallel/test-dgram-send-callback-buffer-length.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/parallel/test-dgram-send-callback-buffer-length.js b/test/parallel/test-dgram-send-callback-buffer-length.js index 76af0e14635be0..8551e97387ea51 100644 --- a/test/parallel/test-dgram-send-callback-buffer-length.js +++ b/test/parallel/test-dgram-send-callback-buffer-length.js @@ -11,6 +11,7 @@ const offset = 20; const len = buf.length - offset; const messageSent = common.mustCall(function messageSent(err, bytes) { + assert.ifError(err); assert.notStrictEqual(bytes, buf.length); assert.strictEqual(bytes, buf.length - offset); client.close(); From 4b4bc13758b2a76b6624e70beb17dae6ccc9b57a Mon Sep 17 00:00:00 2001 From: Ali Ijaz Sheikh Date: Tue, 14 Feb 2017 13:24:37 -0800 Subject: [PATCH 072/164] cluster: properly handle --inspect-{brk,port} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/11386 Reviewed-By: Jeremiah Senkpiel Reviewed-By: Colin Ihrig Reviewed-By: Ben Noordhuis Reviewed-By: Michaël Zasso Reviewed-By: Josh Gavant Reviewed-By: James M Snell --- lib/internal/cluster/master.js | 2 +- test/parallel/test-cluster-inspector-debug-port.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/internal/cluster/master.js b/lib/internal/cluster/master.js index 9d5062f5427ffa..97a71381744573 100644 --- a/lib/internal/cluster/master.js +++ b/lib/internal/cluster/master.js @@ -115,7 +115,7 @@ function createWorkerProcess(id, env) { for (var i = 0; i < execArgv.length; i++) { const match = execArgv[i].match( - /^(--inspect|--debug|--debug-(brk|port))(=\d+)?$/ + /^(--inspect|--inspect-(brk|port)|--debug|--debug-(brk|port))(=\d+)?$/ ); if (match) { diff --git a/test/parallel/test-cluster-inspector-debug-port.js b/test/parallel/test-cluster-inspector-debug-port.js index 0adb6d2a2b37b8..f2f8db9b5d5890 100644 --- a/test/parallel/test-cluster-inspector-debug-port.js +++ b/test/parallel/test-cluster-inspector-debug-port.js @@ -27,6 +27,8 @@ if (cluster.isMaster) { fork(4, ['--inspect', '--debug']); fork(5, [`--debug=${debuggerPort}`, '--inspect']); fork(6, ['--inspect', `--debug-port=${debuggerPort}`]); + fork(7, [`--inspect-port=${debuggerPort}`]); + fork(8, ['--inspect', `--inspect-port=${debuggerPort}`]); } else { const hasDebugArg = process.execArgv.some(function(arg) { return /inspect/.test(arg); From 4509d84095edf4c5bdc35e31f11ad5c227d8fd4c Mon Sep 17 00:00:00 2001 From: Eric Christie Date: Wed, 8 Feb 2017 23:20:05 -0500 Subject: [PATCH 073/164] test: improve coverage in test-crypto.dh MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/11253 Reviewed-By: Rich Trott Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- test/pummel/test-crypto-dh.js | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/test/pummel/test-crypto-dh.js b/test/pummel/test-crypto-dh.js index 64c2800f16ae8d..03be3ab7ad48e2 100644 --- a/test/pummel/test-crypto-dh.js +++ b/test/pummel/test-crypto-dh.js @@ -8,15 +8,32 @@ if (!common.hasCrypto) { return; } -assert.throws(function() { - crypto.getDiffieHellman('unknown-group'); -}); -assert.throws(function() { - crypto.getDiffieHellman('modp1').setPrivateKey(''); -}); -assert.throws(function() { - crypto.getDiffieHellman('modp1').setPublicKey(''); -}); +assert.throws( + function() { + crypto.getDiffieHellman('unknown-group'); + }, + /^Error: Unknown group$/, + 'crypto.getDiffieHellman(\'unknown-group\') ' + + 'failed to throw the expected error.' +); +assert.throws( + function() { + crypto.getDiffieHellman('modp1').setPrivateKey(''); + }, + new RegExp('^TypeError: crypto\\.getDiffieHellman\\(\\.\\.\\.\\)\\.' + + 'setPrivateKey is not a function$'), + 'crypto.getDiffieHellman(\'modp1\').setPrivateKey(\'\') ' + + 'failed to throw the expected error.' +); +assert.throws( + function() { + crypto.getDiffieHellman('modp1').setPublicKey(''); + }, + new RegExp('^TypeError: crypto\\.getDiffieHellman\\(\\.\\.\\.\\)\\.' + + 'setPublicKey is not a function$'), + 'crypto.getDiffieHellman(\'modp1\').setPublicKey(\'\') ' + + 'failed to throw the expected error.' +); const hashes = { modp1: '630e9acd2cc63f7e80d8507624ba60ac0757201a', From 20d86db9bbae7e81f03a160c5d4aa8643be180d8 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Wed, 25 Jan 2017 14:20:24 -0800 Subject: [PATCH 074/164] doc: add version meta for SSL_CERT_DIR/FILE The metadata markup for when SSL_CERT_DIR and SSL_CERT_FILE added in 33012e9866cbb43db562dd6a3feffe8cd4ec5838 is missing. PR-URL: https://github.com/nodejs/node/pull/11007 Reviewed-By: Evan Lucas Reviewed-By: James M Snell --- doc/api/cli.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/api/cli.md b/doc/api/cli.md index 099c4c993d113c..a03b0c507c646c 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -376,6 +376,9 @@ If the [`--openssl-config`][] command line option is used, the environment variable is ignored. ### `SSL_CERT_DIR=dir` + If `--use-openssl-ca` is enabled, this overrides and sets OpenSSL's directory containing trusted certificates. @@ -385,6 +388,9 @@ evironment variable will be inherited by any child processes, and if they use OpenSSL, it may cause them to trust the same CAs as node. ### `SSL_CERT_FILE=file` + If `--use-openssl-ca` is enabled, this overrides and sets OpenSSL's file containing trusted certificates. From 98eb18ba3fb0a2a6938a84152004c69038349055 Mon Sep 17 00:00:00 2001 From: QianJin2013 Date: Sun, 12 Feb 2017 18:45:42 +0900 Subject: [PATCH 075/164] doc: add comment for net.Server's error event Fixes: https://github.com/nodejs/node/issues/9710 PR-URL: https://github.com/nodejs/node/pull/11136 Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Sam Roberts --- doc/api/net.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/api/net.md b/doc/api/net.md index 49e8b6126895d0..2936800fe91178 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -40,8 +40,10 @@ added: v0.1.90 * {Error} -Emitted when an error occurs. The [`'close'`][] event will be called directly -following this event. See example in discussion of `server.listen`. +Emitted when an error occurs. Unlike [`net.Socket`][], the [`'close'`][] +event will **not** be emitted directly following this event unless +[`server.close()`][] is manually called. See the example in discussion of +[`server.listen()`][`server.listen(port, host, backlog, callback)`]. ### Event: 'listening' -* `target` {Buffer} A `Buffer` to copy into. +* `target` {Buffer|Uint8Array} A `Buffer` or [`Uint8Array`] to copy into. * `targetStart` {Integer} The offset within `target` at which to begin copying to. **Default:** `0` * `sourceStart` {Integer} The offset within `buf` at which to begin copying from. diff --git a/test/parallel/test-buffer-copy.js b/test/parallel/test-buffer-copy.js index 5737ed748058ef..1b10dadb5b709b 100644 --- a/test/parallel/test-buffer-copy.js +++ b/test/parallel/test-buffer-copy.js @@ -118,3 +118,29 @@ assert.strictEqual(b.copy(c, 0, 100, 10), 0); // when targetStart > targetLength, zero copied assert.strictEqual(b.copy(c, 512, 0, 10), 0); + +// Test that the `target` can be a Uint8Array. +{ + const d = new Uint8Array(c); + // copy 512 bytes, from 0 to 512. + b.fill(++cntr); + d.fill(++cntr); + const copied = b.copy(d, 0, 0, 512); + assert.strictEqual(512, copied); + for (let i = 0; i < d.length; i++) { + assert.strictEqual(b[i], d[i]); + } +} + +// Test that the source can be a Uint8Array, too. +{ + const e = new Uint8Array(b); + // copy 512 bytes, from 0 to 512. + e.fill(++cntr); + c.fill(++cntr); + const copied = Buffer.prototype.copy.call(e, c, 0, 0, 512); + assert.strictEqual(512, copied); + for (let i = 0; i < c.length; i++) { + assert.strictEqual(e[i], c[i]); + } +} From 8fdb6c24f9aafaa9b503e832b03b556d5444b52d Mon Sep 17 00:00:00 2001 From: Jason Wilson Date: Tue, 21 Feb 2017 13:59:24 -0500 Subject: [PATCH 093/164] test: throw check in test-zlib-write-after-close PR-URL: https://github.com/nodejs/node/pull/11482 Reviewed-By: Rich Trott Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Yuta Hiroto --- test/parallel/test-zlib-write-after-close.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/parallel/test-zlib-write-after-close.js b/test/parallel/test-zlib-write-after-close.js index 0c54270ec29b13..fdad1708c81ff0 100644 --- a/test/parallel/test-zlib-write-after-close.js +++ b/test/parallel/test-zlib-write-after-close.js @@ -6,7 +6,5 @@ const zlib = require('zlib'); zlib.gzip('hello', common.mustCall(function(err, out) { const unzip = zlib.createGunzip(); unzip.close(common.mustCall(function() {})); - assert.throws(function() { - unzip.write(out); - }); + assert.throws(() => unzip.write(out), /^Error: zlib binding closed$/); })); From d9d541d564436ca1cdf9901712420f5294d7a4ca Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 10 Jan 2017 20:43:57 +0100 Subject: [PATCH 094/164] tools,doc: enable changelogs for items PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api_assets/style.css | 6 +++++ test/doctool/test-doctool-html.js | 10 ++++++- test/doctool/test-doctool-json.js | 15 ++++++++--- test/fixtures/doc_with_yaml.md | 4 +++ tools/doc/common.js | 5 ++++ tools/doc/html.js | 43 +++++++++++++++++++++++++++++-- 6 files changed, 77 insertions(+), 6 deletions(-) diff --git a/doc/api_assets/style.css b/doc/api_assets/style.css index f45c4672af88f8..7889389f59b251 100644 --- a/doc/api_assets/style.css +++ b/doc/api_assets/style.css @@ -470,6 +470,12 @@ th > *:last-child, td > *:last-child { margin-bottom: 0; } +.changelog > summary { + margin: .5rem 0; + padding: .5rem 0; + cursor: pointer; +} + /* simpler clearfix */ .clearfix:after { content: "."; diff --git a/test/doctool/test-doctool-html.js b/test/doctool/test-doctool-html.js index 442381b54d7b72..a990d35507a7b7 100644 --- a/test/doctool/test-doctool-html.js +++ b/test/doctool/test-doctool-html.js @@ -47,7 +47,15 @@ const testData = [ '

Describe Foobar in more detail here.

' + '

Foobar II#

' + - ' ' + + ' ' + '

Describe Foobar II in more detail here.

' + '

Deprecated thingy#' + diff --git a/test/doctool/test-doctool-json.js b/test/doctool/test-doctool-json.js index ae7b2007b7d2ef..1019728f0fe1f5 100644 --- a/test/doctool/test-doctool-json.js +++ b/test/doctool/test-doctool-json.js @@ -89,7 +89,8 @@ const testData = [ textRaw: 'Foobar', name: 'foobar', meta: { - added: ['v1.0.0'] + added: ['v1.0.0'], + changes: [] }, desc: '

Describe Foobar in more detail ' + 'here.

\n', @@ -100,7 +101,14 @@ const testData = [ textRaw: 'Foobar II', name: 'foobar_ii', meta: { - added: ['v5.3.0', 'v4.2.0'] + added: ['v5.3.0', 'v4.2.0'], + changes: [ + { version: 'v4.2.0', + 'pr-url': 'https://github.com/nodejs/node/pull/3276', + description: 'The `error` parameter can now be ' + + 'an arrow function.' + } + ] }, desc: '

Describe Foobar II in more detail ' + 'here.

\n', @@ -112,7 +120,8 @@ const testData = [ name: 'deprecated_thingy', meta: { added: ['v1.0.0'], - deprecated: ['v2.0.0'] + deprecated: ['v2.0.0'], + changes: [] }, desc: '

Describe Deprecated thingy in more ' + 'detail here.

\n', diff --git a/test/fixtures/doc_with_yaml.md b/test/fixtures/doc_with_yaml.md index 493c2e7e4268b2..cf039c243a482b 100644 --- a/test/fixtures/doc_with_yaml.md +++ b/test/fixtures/doc_with_yaml.md @@ -12,6 +12,10 @@ Describe `Foobar` in more detail here. added: - v5.3.0 - v4.2.0 +changes: + - version: v4.2.0 + pr-url: https://github.com/nodejs/node/pull/3276 + description: The `error` parameter can now be an arrow function. --> Describe `Foobar II` in more detail here. diff --git a/tools/doc/common.js b/tools/doc/common.js index c2f561da806577..ce4995ddff39d1 100644 --- a/tools/doc/common.js +++ b/tools/doc/common.js @@ -34,6 +34,11 @@ function extractAndParseYAML(text) { meta.deprecated = arrify(deprecated); } + meta.changes = meta.changes || []; + meta.changes.forEach((entry) => { + entry.description = entry.description.replace(/^\^\s*/, ''); + }); + return meta; } diff --git a/tools/doc/html.js b/tools/doc/html.js index 3dd6f83da503df..bc5d3167f7bbb4 100644 --- a/tools/doc/html.js +++ b/tools/doc/html.js @@ -269,12 +269,40 @@ function parseYAML(text) { const meta = common.extractAndParseYAML(text); const html = [''); @@ -390,3 +418,14 @@ function getId(text) { } return text; } + +const numberRe = /^(\d*)/; +function versionSort(a, b) { + a = a.trim(); + b = b.trim(); + let i = 0; // common prefix length + while (i < a.length && i < b.length && a[i] === b[i]) i++; + a = a.substr(i); + b = b.substr(i); + return +b.match(numberRe)[1] - +a.match(numberRe)[1]; +} From 42413b611b72d39186a6212a9e67ea1907ed9fdc Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:39:15 +0100 Subject: [PATCH 095/164] doc: add changelogs for assert PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/assert.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/doc/api/assert.md b/doc/api/assert.md index 6e0c9ad409464c..b94f6ee9080ea0 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -30,6 +30,16 @@ assert(false, 'it\'s false'); ## assert.deepEqual(actual, expected[, message]) Tests for deep equality between the `actual` and `expected` parameters. @@ -91,6 +101,16 @@ parameter is undefined, a default error message is assigned. ## assert.deepStrictEqual(actual, expected[, message]) Generally identical to `assert.deepEqual()` with two exceptions. First, @@ -115,6 +135,13 @@ parameter is undefined, a default error message is assigned. ## assert.doesNotThrow(block[, error][, message]) Asserts that the function `block` does not throw an error. See @@ -402,6 +429,10 @@ If the values are not strictly equal, an `AssertionError` is thrown with a ## assert.throws(block[, error][, message]) Expects the function `block` to throw an error. From ad1ad4d06d0bffd866f4b4a8c7ea528143963b0d Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:42 +0100 Subject: [PATCH 096/164] doc: add changelogs for child_process PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/child_process.md | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 938c3d513b5874..1753b1eaa8c747 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -251,6 +251,10 @@ encoding, `Buffer` objects will be passed to the callback instead. ### child_process.fork(modulePath[, args][, options]) * `modulePath` {String} The module to run in the child @@ -302,6 +306,13 @@ not clone the current process.* ### child_process.spawn(command[, args][, options]) * `command` {String} The command to run @@ -485,6 +496,10 @@ child.unref(); #### options.stdio The `options.stdio` option is used to configure the pipes that are established @@ -574,6 +589,10 @@ configuration at startup. ### child_process.execFileSync(file[, args][, options]) * `file` {String} The name or path of the executable file to run @@ -660,6 +679,13 @@ execution.** ### child_process.spawnSync(command[, args][, options]) * `command` {String} The command to run @@ -911,6 +937,17 @@ grep.stdin.end(); ### child.send(message[, sendHandle[, options]][, callback]) * `message` {Object} From 5d4e638e3483a406dbab63ed67d889087ecbf64f Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:42 +0100 Subject: [PATCH 097/164] doc: add changelogs for cli PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/cli.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/api/cli.md b/doc/api/cli.md index a03b0c507c646c..720108e1b3e836 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -43,6 +43,10 @@ The output of this option is less detailed than this document. ### `-e`, `--eval "script"` Evaluate the following argument as JavaScript. The modules which are @@ -52,6 +56,10 @@ predefined in the REPL can also be used in `script`. ### `-p`, `--print "script"` Identical to `-e` but prints the result. @@ -59,7 +67,9 @@ Identical to `-e` but prints the result. ### `-c`, `--check` Syntax check the script without executing. From de83e215cbc3917932b3663c75507801ce81b906 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:43 +0100 Subject: [PATCH 098/164] doc: add changelogs for cluster PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/cluster.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/doc/api/cluster.md b/doc/api/cluster.md index 01a2aaf6a8cc86..d0ec3f4ed5d277 100644 --- a/doc/api/cluster.md +++ b/doc/api/cluster.md @@ -260,6 +260,10 @@ It is not emitted in the worker. ### worker.disconnect() * Returns: {Worker} A reference to `worker`. @@ -416,6 +420,10 @@ accidental disconnection. ### worker.send(message[, sendHandle][, callback]) * `message` {Object} @@ -449,6 +457,10 @@ if (cluster.isMaster) { > Stability: 0 - Deprecated: Use [`worker.exitedAfterDisconnect`][] instead. @@ -579,6 +591,13 @@ The `addressType` is one of: * `"udp4"` or `"udp6"` (UDP v4 or v6) ## Event: 'message' + * `worker` {cluster.Worker} * `message` {Object} @@ -708,6 +727,10 @@ values are `"rr"` and `"none"`. ## cluster.settings * {Object} @@ -732,6 +755,10 @@ This object is not supposed to be changed or set manually, by you. ## cluster.setupMaster([settings]) * `settings` {Object} From 296e22adce8e0f24607658e2b8cba95e5097f3bc Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:43 +0100 Subject: [PATCH 099/164] doc: add changelogs for console PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/console.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/api/console.md b/doc/api/console.md index 7bc54641a21714..45566a9cdf586d 100644 --- a/doc/api/console.md +++ b/doc/api/console.md @@ -236,6 +236,11 @@ milliseconds to `stdout`. Timer durations are accurate to the sub-millisecond. ### console.timeEnd(label) Stops a timer that was previously started by calling [`console.time()`][] and From e23598d09fee25dba8a05df04b8c49bdd801aa97 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:44 +0100 Subject: [PATCH 100/164] doc: add changelogs for crypto PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/crypto.md | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 9102f2e89c03c4..045c1dd6c174eb 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -229,6 +229,10 @@ Returns `this` for method chaining. ### cipher.update(data[, input_encoding][, output_encoding]) Updates the cipher with `data`. If the `input_encoding` argument is given, @@ -327,6 +331,10 @@ than once will result in an error being thrown. ### decipher.setAAD(buffer) When using an authenticated encryption mode (only `GCM` is currently @@ -338,6 +346,10 @@ Returns `this` for method chaining. ### decipher.setAuthTag(buffer) When using an authenticated encryption mode (only `GCM` is currently @@ -368,6 +380,10 @@ Returns `this` for method chaining. ### decipher.update(data[, input_encoding][, output_encoding]) Updates the decipher with `data`. If the `input_encoding` argument is given, @@ -548,6 +564,10 @@ assert.strictEqual(aliceSecret.toString('hex'), bobSecret.toString('hex')); ### ecdh.computeSecret(other_public_key[, input_encoding][, output_encoding]) Computes the shared secret using `other_public_key` as the other @@ -731,6 +751,10 @@ called. Multiple calls will cause an error to be thrown. ### hash.update(data[, input_encoding]) Updates the hash content with the given `data`, the encoding of which @@ -813,6 +837,10 @@ called. Multiple calls to `hmac.digest()` will result in an error being thrown. ### hmac.update(data[, input_encoding]) Updates the `Hmac` content with the given `data`, the encoding of which @@ -914,6 +942,10 @@ called. Multiple calls to `sign.sign()` will result in an error being thrown. ### sign.update(data[, input_encoding]) Updates the `Sign` content with the given `data`, the encoding of which @@ -972,6 +1004,10 @@ console.log(verify.verify(publicKey, signature)); ### verifier.update(data[, input_encoding]) Updates the `Verify` content with the given `data`, the encoding of which @@ -1133,6 +1169,11 @@ The `key` is the raw key used by the `algorithm` and `iv` is an ### crypto.createDiffieHellman(prime[, prime_encoding][, generator][, generator_encoding]) Creates a `DiffieHellman` key exchange object using the supplied `prime` and an @@ -1334,6 +1375,15 @@ console.log(hashes); // ['DSA', 'DSA-SHA', 'DSA-SHA1', ...] ### crypto.pbkdf2(password, salt, iterations, keylen, digest, callback) Provides an asynchronous Password-Based Key Derivation Function 2 (PBKDF2) @@ -1369,6 +1419,15 @@ An array of supported digest functions can be retrieved using ### crypto.pbkdf2Sync(password, salt, iterations, keylen, digest) Provides a synchronous Password-Based Key Derivation Function 2 (PBKDF2) From 5bc9349d40e617b89f5e09614dac500d0bd14c70 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:44 +0100 Subject: [PATCH 101/164] doc: add changelogs for dgram PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/dgram.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/api/dgram.md b/doc/api/dgram.md index 2e214beb2ff7d2..91db049fd1ad75 100644 --- a/doc/api/dgram.md +++ b/doc/api/dgram.md @@ -228,6 +228,15 @@ drop membership on all valid interfaces. ### socket.send(msg, [offset, length,] port, address[, callback]) * `msg` {Buffer|String|Array} Message to be sent From 4f936014ff2a4f3063938064d70ab10920277f8f Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:44 +0100 Subject: [PATCH 102/164] doc: add changelogs for dns PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/dns.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/api/dns.md b/doc/api/dns.md index f705d96246bd87..b943664ec8b605 100644 --- a/doc/api/dns.md +++ b/doc/api/dns.md @@ -65,6 +65,10 @@ resolution. ## dns.lookup(hostname[, options], callback) Resolves a hostname (e.g. `'nodejs.org'`) into the first found A (IPv4) or @@ -198,6 +202,11 @@ one of the error codes listed [here](#dns_error_codes). ## dns.resolve4(hostname[, options], callback) Uses the DNS protocol to resolve a IPv4 addresses (`A` records) for the @@ -215,6 +224,11 @@ will contain an array of IPv4 addresses (e.g. ## dns.resolve6(hostname[, options], callback) Uses the DNS protocol to resolve a IPv6 addresses (`AAAA` records) for the From 354161d80402014dec0168522777adc2a9719424 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:45 +0100 Subject: [PATCH 103/164] doc: add changelogs for events PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/events.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/api/events.md b/doc/api/events.md index b468674c3613fa..7a376415a842b9 100644 --- a/doc/api/events.md +++ b/doc/api/events.md @@ -222,6 +222,11 @@ myEmitter.emit('event'); ### Event: 'removeListener' * `eventName` {String|Symbol} The event name @@ -347,6 +352,11 @@ Returns the number of listeners listening to the event named `eventName`. ### emitter.listeners(eventName) Returns a copy of the array of listeners for the event named `eventName`. From f0cee80de7f8e8bdbb7cf8d1ef6aacb80334131f Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:45 +0100 Subject: [PATCH 104/164] doc: add changelogs for fs PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/fs.md | 276 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) diff --git a/doc/api/fs.md b/doc/api/fs.md index 187c7d9edc1a12..1a4233e81e6011 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -448,6 +448,17 @@ checks fail, and does nothing otherwise. ## fs.appendFile(file, data[, options], callback) * `file` {String | Buffer | Number} filename or file descriptor @@ -484,6 +495,13 @@ automatically._ ## fs.appendFileSync(file, data[, options]) * `file` {String | Buffer | Number} filename or file descriptor @@ -498,6 +516,11 @@ The synchronous version of [`fs.appendFile()`][]. Returns `undefined`. ## fs.chmod(path, mode, callback) * `path` {String | Buffer} @@ -520,6 +543,11 @@ Synchronous chmod(2). Returns `undefined`. ## fs.chown(path, uid, gid, callback) * `path` {String | Buffer} @@ -544,6 +572,11 @@ Synchronous chown(2). Returns `undefined`. ## fs.close(fd, callback) * `fd` {Integer} @@ -570,6 +603,13 @@ operations. The specific constants currently defined are described in ## fs.createReadStream(path[, options]) * `path` {String | Buffer} @@ -631,6 +671,16 @@ If `options` is a string, then it specifies the encoding. ## fs.createWriteStream(path[, options]) * `path` {String | Buffer} @@ -797,6 +847,11 @@ a callback.) ## fs.fchmod(fd, mode, callback) * `fd` {Integer} @@ -819,6 +874,11 @@ Synchronous fchmod(2). Returns `undefined`. ## fs.fchown(fd, uid, gid, callback) * `fd` {Integer} @@ -843,6 +903,11 @@ Synchronous fchown(2). Returns `undefined`. ## fs.fdatasync(fd, callback) * `fd` {Integer} @@ -863,6 +928,11 @@ Synchronous fdatasync(2). Returns `undefined`. ## fs.fstat(fd, callback) * `fd` {Integer} @@ -884,6 +954,11 @@ Synchronous fstat(2). Returns an instance of [`fs.Stats`][]. ## fs.fsync(fd, callback) * `fd` {Integer} @@ -904,6 +979,11 @@ Synchronous fsync(2). Returns `undefined`. ## fs.ftruncate(fd, len, callback) * `fd` {Integer} @@ -967,6 +1047,15 @@ Synchronous ftruncate(2). Returns `undefined`. ## fs.futimes(fd, atime, mtime, callback) * `fd` {Integer} @@ -980,6 +1069,11 @@ descriptor. ## fs.futimesSync(fd, atime, mtime) * `fd` {Integer} @@ -991,6 +1085,11 @@ Synchronous version of [`fs.futimes()`][]. Returns `undefined`. ## fs.lchmod(path, mode, callback) * `path` {String | Buffer} @@ -1015,6 +1114,11 @@ Synchronous lchmod(2). Returns `undefined`. ## fs.lchown(path, uid, gid, callback) * `path` {String | Buffer} @@ -1039,6 +1143,11 @@ Synchronous lchown(2). Returns `undefined`. ## fs.link(existingPath, newPath, callback) * `existingPath` {String | Buffer} @@ -1061,6 +1170,11 @@ Synchronous link(2). Returns `undefined`. ## fs.lstat(path, callback) * `path` {String | Buffer} @@ -1083,6 +1197,11 @@ Synchronous lstat(2). Returns an instance of [`fs.Stats`][]. ## fs.mkdir(path[, mode], callback) * `path` {String | Buffer} @@ -1105,6 +1224,14 @@ Synchronous mkdir(2). Returns `undefined`. ## fs.mkdtemp(prefix[, options], callback) * `prefix` {String} @@ -1278,6 +1405,13 @@ descriptor. ## fs.read(fd, buffer, offset, length, position, callback) * `fd` {Integer} @@ -1303,6 +1437,11 @@ The callback is given the three arguments, `(err, bytesRead, buffer)`. ## fs.readdir(path[, options], callback) * `path` {String | Buffer} @@ -1339,6 +1478,18 @@ the filenames returned will be passed as `Buffer` objects. ## fs.readFile(file[, options], callback) * `file` {String | Buffer | Integer} filename or file descriptor @@ -1375,6 +1526,10 @@ automatically._ ## fs.readFileSync(file[, options]) * `file` {String | Buffer | Integer} filename or file descriptor @@ -1390,6 +1545,11 @@ string. Otherwise it returns a buffer. ## fs.readlink(path[, options], callback) * `path` {String | Buffer} @@ -1424,6 +1584,10 @@ the link path returned will be passed as a `Buffer` object. ## fs.readSync(fd, buffer, offset, length, position) * `fd` {Integer} @@ -1437,6 +1601,18 @@ Synchronous version of [`fs.read()`][]. Returns the number of `bytesRead`. ## fs.realpath(path[, options], callback) * `path` {String | Buffer} @@ -1457,6 +1633,14 @@ the path returned will be passed as a `Buffer` object. ## fs.realpathSync(path[, options]) * `path` {String | Buffer}; @@ -1475,6 +1659,11 @@ will be passed as a `Buffer` object. ## fs.rename(oldPath, newPath, callback) * `oldPath` {String | Buffer} @@ -1497,6 +1686,11 @@ Synchronous rename(2). Returns `undefined`. ## fs.rmdir(path, callback) * `path` {String | Buffer} @@ -1517,6 +1711,11 @@ Synchronous rmdir(2). Returns `undefined`. ## fs.stat(path, callback) * `path` {String | Buffer} @@ -1583,6 +1782,11 @@ Synchronous symlink(2). Returns `undefined`. ## fs.truncate(path, len, callback) * `path` {String | Buffer} @@ -1607,6 +1811,11 @@ passed as the first argument. In this case, `fs.ftruncateSync()` is called. ## fs.unlink(path, callback) * `path` {String | Buffer} @@ -1646,6 +1855,15 @@ when possible._ ## fs.utimes(path, atime, mtime, callback) * `path` {String | Buffer} @@ -1668,6 +1886,11 @@ follow these rules: ## fs.utimesSync(path, atime, mtime) * `path` {String | Buffer} @@ -1679,6 +1902,10 @@ Synchronous version of [`fs.utimes()`][]. Returns `undefined`. ## fs.watch(filename[, options][, listener]) * `filename` {String | Buffer} @@ -1828,6 +2055,17 @@ _Note: [`fs.watch()`][] is more efficient than `fs.watchFile` and ## fs.write(fd, buffer[, offset[, length[, position]]], callback) * `fd` {Integer} @@ -1860,6 +2098,14 @@ the end of the file. ## fs.write(fd, string[, position[, encoding]], callback) * `fd` {Integer} @@ -1896,6 +2142,17 @@ the end of the file. ## fs.writeFile(file, data[, options], callback) * `file` {String | Buffer | Integer} filename or file descriptor @@ -1939,6 +2196,13 @@ automatically._ ## fs.writeFileSync(file, data[, options]) * `file` {String | Buffer | Integer} filename or file descriptor @@ -1953,6 +2217,13 @@ The synchronous version of [`fs.writeFile()`][]. Returns `undefined`. ## fs.writeSync(fd, buffer[, offset[, length[, position]]]) * `fd` {Integer} @@ -1964,6 +2235,10 @@ added: v0.1.21 ## fs.writeSync(fd, string[, position[, encoding]]) * `fd` {Integer} @@ -2231,3 +2506,4 @@ The following constants are meant for use with the [`fs.Stats`][] object's [`ReadDirectoryChangesW`]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx [`AHAFS`]: https://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/ [Common System Errors]: errors.html#errors_common_system_errors +[`Uint8Array`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array From 6cc8f19e99bcfbb52533f0deb276d48952edbdc5 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:45 +0100 Subject: [PATCH 105/164] doc: add changelogs for http PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/http.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/api/http.md b/doc/api/http.md index 681fb21eb511ff..90d48768f13928 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -586,6 +586,12 @@ not be emitted. ### Event: 'clientError' * `exception` {Error} @@ -1118,6 +1124,11 @@ the request body should be sent. See the [`'checkContinue'`][] event on `Server` ### response.writeHead(statusCode[, statusMessage][, headers]) * `statusCode` {Number} From 3183397c8a3383f3df7feea0f882ed150bc0e407 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:46 +0100 Subject: [PATCH 106/164] doc: add changelogs for net PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/net.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/doc/api/net.md b/doc/api/net.md index 2936800fe91178..f4669449ee0107 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -411,6 +411,10 @@ following this event. ### Event: 'lookup' Emitted after resolving the hostname but before connecting. @@ -479,6 +483,15 @@ The amount of bytes sent. ### socket.connect(options[, connectListener]) Opens the connection for a given socket. From ac10a3b306917f90f6367c73a756ac05284e7cae Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:46 +0100 Subject: [PATCH 107/164] doc: add changelogs for os PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/os.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/api/os.md b/doc/api/os.md index 15b84189c91272..d1a4cc66aed053 100644 --- a/doc/api/os.md +++ b/doc/api/os.md @@ -333,6 +333,11 @@ https://en.wikipedia.org/wiki/Uname#Examples for more information. ## os.tmpdir() * Returns: {String} @@ -404,6 +409,12 @@ The following constants are exported by `os.constants`. **Note:** Not all constants will be available on every operating system. ### Signal Constants + The following signal constants are exported by `os.constants.signals`: From c1477b9bd3cc62f72101e6ac1d2b214ec41e2656 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:46 +0100 Subject: [PATCH 108/164] doc: add changelogs for path PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/path.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/doc/api/path.md b/doc/api/path.md index df65616b6c4e94..f284c500595571 100644 --- a/doc/api/path.md +++ b/doc/api/path.md @@ -57,6 +57,10 @@ path.posix.basename('/tmp/myfile.html'); ## path.basename(path[, ext]) * `path` {String} @@ -114,6 +118,10 @@ process.env.PATH.split(path.delimiter) ## path.dirname(path) * `path` {String} @@ -134,6 +142,10 @@ A [`TypeError`][] is thrown if `path` is not a string. ## path.extname(path) * `path` {String} @@ -408,6 +420,11 @@ of the `path` methods. ## path.relative(from, to) * `from` {String} From df30bc869aa958aba58c98e6a62127dbdcc45fef Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:47 +0100 Subject: [PATCH 109/164] doc: add changelogs for process PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/process.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/doc/api/process.md b/doc/api/process.md index dd449172ed416e..c6bb13d4a7ac10 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -203,6 +203,14 @@ to detect application failures and recover or restart as needed. ### Event: 'unhandledRejection' The `'unhandledRejection`' event is emitted whenever a `Promise` is rejected and @@ -1130,6 +1138,10 @@ is no entry script. ## process.memoryUsage() * Returns: {Object} @@ -1165,6 +1177,10 @@ objects managed by V8. ## process.nextTick(callback[, ...args]) * `callback` {Function} @@ -1284,6 +1300,10 @@ console.log(`This platform is ${process.platform}`); ## process.release The `process.release` property returns an Object containing metadata related to @@ -1646,6 +1666,10 @@ console.log(`Version: ${process.version}`); ## process.versions * {Object} From 6285ff2275cbe237d3eafa26c5c02671b1de386e Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:47 +0100 Subject: [PATCH 110/164] doc: add changelogs for punycode PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/punycode.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/api/punycode.md b/doc/api/punycode.md index a5d1908a8c40b6..7b0b63939de369 100644 --- a/doc/api/punycode.md +++ b/doc/api/punycode.md @@ -1,4 +1,10 @@ # Punycode + > Stability: 0 - Deprecated From 7c609dc30aba4938bfdcd9dd68050442614b9bb7 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:47 +0100 Subject: [PATCH 111/164] doc: add changelogs for querystring PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/querystring.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/api/querystring.md b/doc/api/querystring.md index 443bd4c003501e..0c31c1600bd67c 100644 --- a/doc/api/querystring.md +++ b/doc/api/querystring.md @@ -30,6 +30,13 @@ necessary by assigning `querystring.escape` to an alternative function. ## querystring.parse(str[, sep[, eq[, options]]]) * `str` {String} The URL query string to parse From 962d27dbde35297c6c541d6a0da132022c180979 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:48 +0100 Subject: [PATCH 112/164] doc: add changelogs for readline PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/readline.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/api/readline.md b/doc/api/readline.md index 32fad5732c70df..b7c9a506309e5c 100644 --- a/doc/api/readline.md +++ b/doc/api/readline.md @@ -344,6 +344,13 @@ the current position of the cursor down. ## readline.createInterface(options) * `options` {Object} From c373e07a09cc3cc707a757e18d1922ffb547fafb Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:48 +0100 Subject: [PATCH 113/164] doc: add changelogs for repl PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/repl.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/api/repl.md b/doc/api/repl.md index 1b03ba47a25d99..f4d85e11c96b3b 100644 --- a/doc/api/repl.md +++ b/doc/api/repl.md @@ -373,6 +373,10 @@ within the action function for commands registered using the ## repl.start([options]) * `options` {Object | String} From fc53547ed4975ab83d98b97997594e2720507ba8 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:48 +0100 Subject: [PATCH 114/164] doc: add changelogs for stream PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/stream.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/doc/api/stream.md b/doc/api/stream.md index ba1c56398d544c..0e12e76c810c17 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -380,6 +380,10 @@ file.end('world!'); ##### writable.setDefaultEncoding(encoding) * `encoding` {String} The new default encoding @@ -429,6 +433,11 @@ See also: [`writable.cork()`][]. ##### writable.write(chunk[, encoding][, callback]) * `chunk` {String|Buffer} The data to write @@ -1069,6 +1078,11 @@ myReader.on('readable', () => { #### Class: stream.Duplex @@ -1190,6 +1204,9 @@ the [API for Stream Consumers][] section). Doing so may lead to adverse side effects in application code consuming the stream. ### Simplified Construction + For many simple cases, it is possible to construct a stream without relying on inheritance. This can be accomplished by directly creating instances of the From f7d59e55685f6a8a99bceb303af78490dcfad8a4 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:49 +0100 Subject: [PATCH 115/164] doc: add changelogs for tls PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/tls.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/doc/api/tls.md b/doc/api/tls.md index f83ed1df3e449f..97bc8301f4ead1 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -461,6 +461,10 @@ connection is open. ### new tls.TLSSocket(socket[, options]) * `socket` {net.Socket} An instance of [`net.Socket`][] @@ -770,6 +774,13 @@ argument. ## tls.connect(options[, callback]) * `options` {Object} @@ -883,6 +894,16 @@ socket.on('end', () => { ## tls.createSecureContext(options) * `options` {Object} @@ -972,6 +993,10 @@ publicly trusted list of CAs as given in ## tls.createServer([options][, secureConnectionListener]) * `options` {Object} @@ -1146,6 +1171,10 @@ certificate used is properly authorized. > Stability: 0 - Deprecated: Use [`tls.TLSSocket`][] instead. From 93e7639c12d42a0c855659cf7e86bdc7fa94e71d Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:49 +0100 Subject: [PATCH 116/164] doc: add changelogs for url PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/url.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/api/url.md b/doc/api/url.md index b71e0b88b21ead..5a66e827a09101 100644 --- a/doc/api/url.md +++ b/doc/api/url.md @@ -262,6 +262,18 @@ object. ## url.resolve(from, to) * `from` {String} The Base URL being resolved against. From b868468942b586c32719495c429c9d8443df11ba Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:49 +0100 Subject: [PATCH 117/164] doc: add changelogs for util PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/util.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/api/util.md b/doc/api/util.md index 3843f80ce75366..3e99949322b02f 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -136,6 +136,10 @@ util.format(1, 2, 3); // '1 2 3' ## util.inherits(constructor, superConstructor) _Note: usage of `util.inherits()` is discouraged. Please use the ES6 `class` and @@ -203,6 +207,20 @@ stream.write('With ES6'); ## util.inspect(object[, options]) * `object` {any} Any JavaScript primitive or Object. From 4d122700abc1a7ee9815c69037af3d50b3de3fa2 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:50 +0100 Subject: [PATCH 118/164] doc: add changelogs for vm PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/vm.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/api/vm.md b/doc/api/vm.md index ffa50be84612df..025e9725a94e66 100644 --- a/doc/api/vm.md +++ b/doc/api/vm.md @@ -25,6 +25,11 @@ executed in specific sandboxes (or "contexts"). ### new vm.Script(code, options) * `code` {string} The JavaScript code to compile. @@ -60,6 +65,10 @@ each run, just for that run. ### script.runInContext(contextifiedSandbox[, options]) * `contextifiedSandbox` {Object} A [contextified][] object as returned by the From 47dc5662f3b021cee3cb9f26da17bc8539d16116 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:50 +0100 Subject: [PATCH 119/164] doc: add changelogs for zlib PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/zlib.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/doc/api/zlib.md b/doc/api/zlib.md index 0d79c084acd565..5b02a8ed37d278 100644 --- a/doc/api/zlib.md +++ b/doc/api/zlib.md @@ -277,6 +277,10 @@ Compression strategy. ## Class Options @@ -315,6 +319,17 @@ Compress data using deflate, and do not append a `zlib` header. ## Class: zlib.Gunzip Decompress a gzip stream. @@ -329,6 +344,10 @@ Compress data using gzip. ## Class: zlib.Inflate Decompress a deflate stream. @@ -336,6 +355,13 @@ Decompress a deflate stream. ## Class: zlib.InflateRaw Decompress a raw deflate stream. From 47034e12adde529ef96871494f8181b158ca7a1f Mon Sep 17 00:00:00 2001 From: Karan Thakkar Date: Wed, 22 Feb 2017 20:12:46 +0530 Subject: [PATCH 120/164] doc: change broken fg(1) links to fg(1p) The fg(1) links in the readline docs have moved from `http://man7.org/linux/man-pages/man1/fg.1.html` to `http://man7.org/linux/man-pages/man1/fg.1p.html`. It also modifies the regex for replacing man page links in docs by allowing optional character after number. eg: fg(1) and fg(1p) will both be now parsed and replaced. Fixes: https://github.com/nodejs/node/issues/11492 PR-URL: https://github.com/nodejs/node/pull/11504 Reviewed-By: Anna Henningsen Reviewed-By: Jeremiah Senkpiel --- doc/api/readline.md | 4 ++-- test/doctool/test-doctool-html.js | 7 +++++-- test/doctool/test-doctool-json.js | 4 ++-- test/fixtures/doc_with_yaml.md | 4 ++-- tools/doc/html.js | 24 +++++++++++++----------- 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/doc/api/readline.md b/doc/api/readline.md index b7c9a506309e5c..b3be83bb6eb8c4 100644 --- a/doc/api/readline.md +++ b/doc/api/readline.md @@ -124,7 +124,7 @@ added: v0.7.5 The `'SIGCONT'` event is emitted when a Node.js process previously moved into the background using `-Z` (i.e. `SIGTSTP`) is then brought back to the -foreground using fg(1). +foreground using fg(1p). If the `input` stream was paused *before* the `SIGTSTP` request, this event will not be emitted. @@ -174,7 +174,7 @@ input, typically known as `SIGTSTP`. If there are no `SIGTSTP` event listeners registered when the `input` stream receives a `SIGTSTP`, the Node.js process will be sent to the background. -When the program is resumed using fg(1), the `'pause'` and `SIGCONT` events +When the program is resumed using fg(1p), the `'pause'` and `SIGCONT` events will be emitted. These can be used to resume the `input` stream. The `'pause'` and `'SIGCONT'` events will not be emitted if the `input` was diff --git a/test/doctool/test-doctool-html.js b/test/doctool/test-doctool-html.js index a990d35507a7b7..e119ee86172c25 100644 --- a/test/doctool/test-doctool-html.js +++ b/test/doctool/test-doctool-html.js @@ -56,13 +56,16 @@ const testData = [ 'v4.2.0

The error parameter can now be' + 'an arrow function.

' + ' ' + - '

Describe Foobar II in more detail here.

' + + '

Describe Foobar II in more detail here.' + + 'fg(1)

' + '

Deprecated thingy#' + '

' + '

Describe ' + - 'Deprecated thingy in more detail here.

' + + 'Deprecated thingy in more detail here.' + + 'fg(1p)' + + '

' + '

Something#

' + ' ' + diff --git a/test/doctool/test-doctool-json.js b/test/doctool/test-doctool-json.js index 1019728f0fe1f5..346a7f331e9d7f 100644 --- a/test/doctool/test-doctool-json.js +++ b/test/doctool/test-doctool-json.js @@ -111,7 +111,7 @@ const testData = [ ] }, desc: '

Describe Foobar II in more detail ' + - 'here.

\n', + 'here. fg(1)

\n', type: 'module', displayName: 'Foobar II' }, @@ -124,7 +124,7 @@ const testData = [ changes: [] }, desc: '

Describe Deprecated thingy in more ' + - 'detail here.

\n', + 'detail here. fg(1p)

\n', type: 'module', displayName: 'Deprecated thingy' }, diff --git a/test/fixtures/doc_with_yaml.md b/test/fixtures/doc_with_yaml.md index cf039c243a482b..89cf28104e5533 100644 --- a/test/fixtures/doc_with_yaml.md +++ b/test/fixtures/doc_with_yaml.md @@ -18,7 +18,7 @@ changes: description: The `error` parameter can now be an arrow function. --> -Describe `Foobar II` in more detail here. +Describe `Foobar II` in more detail here. fg(1) ## Deprecated thingy -Describe `Deprecated thingy` in more detail here. +Describe `Deprecated thingy` in more detail here. fg(1p) ## Something diff --git a/tools/doc/html.js b/tools/doc/html.js index bc5d3167f7bbb4..10b04a1b9887e4 100644 --- a/tools/doc/html.js +++ b/tools/doc/html.js @@ -316,17 +316,19 @@ var BSD_ONLY_SYSCALLS = new Set(['lchmod']); // Returns modified text, with such refs replace with HTML links, for example // 'open(2)' function linkManPages(text) { - return text.replace(/ ([a-z.]+)\((\d)\)/gm, function(match, name, number) { - // name consists of lowercase letters, number is a single digit - var displayAs = name + '(' + number + ')'; - if (BSD_ONLY_SYSCALLS.has(name)) { - return ' ' + displayAs + ''; - } else { - return ' ' + displayAs + ''; - } - }); + return text.replace( + / ([a-z.]+)\((\d)([a-z]?)\)/gm, + (match, name, number, optionalCharacter) => { + // name consists of lowercase letters, number is a single digit + var displayAs = `${name}(${number}${optionalCharacter})`; + if (BSD_ONLY_SYSCALLS.has(name)) { + return ` ${displayAs}`; + } else { + return ` ${displayAs}`; + } + }); } function linkJsTypeDocs(text) { From a710167c7948a00bd7decfda26126df1211096f4 Mon Sep 17 00:00:00 2001 From: JungMinu Date: Tue, 21 Feb 2017 13:14:28 +0900 Subject: [PATCH 121/164] lib: rename kMaxCallbacksUntilQueueIsShortened PR-URL: https://github.com/nodejs/node/pull/11473 Ref: https://github.com/nodejs/node/pull/11199#issuecomment-281184439 Reviewed-By: Daniel Bevenius Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- lib/internal/process/next_tick.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/internal/process/next_tick.js b/lib/internal/process/next_tick.js index bc89c6e8b269e3..ad635aaf494b33 100644 --- a/lib/internal/process/next_tick.js +++ b/lib/internal/process/next_tick.js @@ -4,7 +4,7 @@ // large and cause the process to run out of memory. When this value // is reached the nextTimeQueue array will be shortend (see tickDone // for details). -const kMaxCallbacksUntilQueueIsShortened = 1e4; +const kMaxCallbacksPerLoop = 1e4; exports.setup = setupNextTick; @@ -102,7 +102,7 @@ function setupNextTick() { // callback invocation with small numbers of arguments to avoid the // performance hit associated with using `fn.apply()` _combinedTickCallback(args, callback); - if (kMaxCallbacksUntilQueueIsShortened < tickInfo[kIndex]) + if (kMaxCallbacksPerLoop < tickInfo[kIndex]) tickDone(); } tickDone(); @@ -126,7 +126,7 @@ function setupNextTick() { // callback invocation with small numbers of arguments to avoid the // performance hit associated with using `fn.apply()` _combinedTickCallback(args, callback); - if (kMaxCallbacksUntilQueueIsShortened < tickInfo[kIndex]) + if (kMaxCallbacksPerLoop < tickInfo[kIndex]) tickDone(); if (domain) domain.exit(); From 214a39294a19c8d4ecfc467fc3729d4c4da9cf02 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Mon, 24 Oct 2016 13:09:34 -0700 Subject: [PATCH 122/164] errors: add internal/errors.js Add the internal/errors.js core mechanism. PR-URL: https://github.com/nodejs/node/pull/11220 Reviewed-By: Anna Henningsen Reviewed-By: Joyee Cheung --- doc/guides/using-internal-errors.md | 141 ++++++++++++++++++++++++++ lib/internal/errors.js | 88 ++++++++++++++++ node.gyp | 1 + test/common.js | 15 +++ test/parallel/test-internal-errors.js | 116 +++++++++++++++++++++ 5 files changed, 361 insertions(+) create mode 100644 doc/guides/using-internal-errors.md create mode 100644 lib/internal/errors.js create mode 100644 test/parallel/test-internal-errors.js diff --git a/doc/guides/using-internal-errors.md b/doc/guides/using-internal-errors.md new file mode 100644 index 00000000000000..9f8634dc233b9e --- /dev/null +++ b/doc/guides/using-internal-errors.md @@ -0,0 +1,141 @@ +# Using the internal/errors.js Module + +## What is internal/errors.js + +The `require('internal/errors')` module is an internal-only module that can be +used to produce `Error`, `TypeError` and `RangeError` instances that use a +static, permanent error code and an optionally parameterized message. + +The intent of the module is to allow errors provided by Node.js to be assigned a +permanent identifier. Without a permanent identifier, userland code may need to +inspect error messages to distinguish one error from another. An unfortunate +result of that practice is that changes to error messages result in broken code +in the ecosystem. For that reason, Node.js has considered error message changes +to be breaking changes. By providing a permanent identifier for a specific +error, we reduce the need for userland code to inspect error messages. + +*Note*: Switching an existing error to use the `internal/errors` module must be +considered a `semver-major` change. However, once using `internal/errors`, +changes to `internal/errors` error messages will be handled as `semver-minor` +or `semver-patch`. + +## Using internal/errors.js + +The `internal/errors` module exposes three custom `Error` classes that +are intended to replace existing `Error` objects within the Node.js source. + +For instance, an existing `Error` such as: + +```js + var err = new TypeError('Expected string received ' + type); +``` + +Can be replaced by first adding a new error key into the `internal/errors.js` +file: + +```js +E('FOO', 'Expected string received %s'); +``` + +Then replacing the existing `new TypeError` in the code: + +```js + const errors = require('internal/errors'); + // ... + var err = new errors.TypeError('FOO', type); +``` + +## Adding new errors + +New static error codes are added by modifying the `internal/errors.js` file +and appending the new error codes to the end using the utility `E()` method. + +```js +E('EXAMPLE_KEY1', 'This is the error value'); +E('EXAMPLE_KEY2', (a, b) => return `${a} ${b}`); +``` + +The first argument passed to `E()` is the static identifier. The second +argument is either a String with optional `util.format()` style replacement +tags (e.g. `%s`, `%d`), or a function returning a String. The optional +additional arguments passed to the `errors.message()` function (which is +used by the `errors.Error`, `errors.TypeError` and `errors.RangeError` classes), +will be used to format the error message. + +## Documenting new errors + +Whenever a new static error code is added and used, corresponding documentation +for the error code should be added to the `doc/api/errors.md` file. This will +give users a place to go to easily look up the meaning of individual error +codes. + + +## API + +### Class: errors.Error(key[, args...]) + +* `key` {String} The static error identifier +* `args...` {Any} Zero or more optional arguments + +```js +const errors = require('internal/errors'); + +var arg1 = 'foo'; +var arg2 = 'bar'; +const myError = new errors.Error('KEY', arg1, arg2); +throw myError; +``` + +The specific error message for the `myError` instance will depend on the +associated value of `KEY` (see "Adding new errors"). + +The `myError` object will have a `code` property equal to the `key` and a +`name` property equal to `Error[${key}]`. + +### Class: errors.TypeError(key[, args...]) + +* `key` {String} The static error identifier +* `args...` {Any} Zero or more optional arguments + +```js +const errors = require('internal/errors'); + +var arg1 = 'foo'; +var arg2 = 'bar'; +const myError = new errors.TypeError('KEY', arg1, arg2); +throw myError; +``` + +The specific error message for the `myError` instance will depend on the +associated value of `KEY` (see "Adding new errors"). + +The `myError` object will have a `code` property equal to the `key` and a +`name` property equal to `TypeError[${key}]`. + +### Class: errors.RangeError(key[, args...]) + +* `key` {String} The static error identifier +* `args...` {Any} Zero or more optional arguments + +```js +const errors = require('internal/errors'); + +var arg1 = 'foo'; +var arg2 = 'bar'; +const myError = new errors.RangeError('KEY', arg1, arg2); +throw myError; +``` + +The specific error message for the `myError` instance will depend on the +associated value of `KEY` (see "Adding new errors"). + +The `myError` object will have a `code` property equal to the `key` and a +`name` property equal to `RangeError[${key}]`. + +### Method: errors.message(key, args) + +* `key` {String} The static error identifier +* `args` {Array} Zero or more optional arguments passed as an Array +* Returns: {String} + +Returns the formatted error message string for the given `key`. diff --git a/lib/internal/errors.js b/lib/internal/errors.js new file mode 100644 index 00000000000000..f2376f70371c60 --- /dev/null +++ b/lib/internal/errors.js @@ -0,0 +1,88 @@ +'use strict'; + +// The whole point behind this internal module is to allow Node.js to no +// longer be forced to treat every error message change as a semver-major +// change. The NodeError classes here all expose a `code` property whose +// value statically and permanently identifies the error. While the error +// message may change, the code should not. + +const kCode = Symbol('code'); +const messages = new Map(); + +var assert, util; +function lazyAssert() { + if (!assert) + assert = require('assert'); + return assert; +} + +function lazyUtil() { + if (!util) + util = require('util'); + return util; +} + +function makeNodeError(Base) { + return class NodeError extends Base { + constructor(key, ...args) { + super(message(key, args)); + this[kCode] = key; + Error.captureStackTrace(this, NodeError); + } + + get name() { + return `${super.name}[${this[kCode]}]`; + } + + get code() { + return this[kCode]; + } + }; +} + +function message(key, args) { + const assert = lazyAssert(); + assert.strictEqual(typeof key, 'string'); + const util = lazyUtil(); + const msg = messages.get(key); + assert(msg, `An invalid error message key was used: ${key}.`); + let fmt = util.format; + if (typeof msg === 'function') { + fmt = msg; + } else { + if (args === undefined || args.length === 0) + return msg; + args.unshift(msg); + } + return String(fmt.apply(null, args)); +} + +// Utility function for registering the error codes. Only used here. Exported +// *only* to allow for testing. +function E(sym, val) { + messages.set(sym, typeof val === 'function' ? val : String(val)); +} + +module.exports = exports = { + message, + Error: makeNodeError(Error), + TypeError: makeNodeError(TypeError), + RangeError: makeNodeError(RangeError), + E // This is exported only to facilitate testing. +}; + +// To declare an error message, use the E(sym, val) function above. The sym +// must be an upper case string. The val can be either a function or a string. +// The return value of the function must be a string. +// Examples: +// E('EXAMPLE_KEY1', 'This is the error value'); +// E('EXAMPLE_KEY2', (a, b) => return `${a} ${b}`); +// +// Once an error code has been assigned, the code itself MUST NOT change and +// any given error code must never be reused to identify a different error. +// +// Any error code added here should also be added to the documentation +// +// Note: Please try to keep these in alphabetical order +E('ERR_ASSERTION', (msg) => msg); +// Add new errors from here... diff --git a/node.gyp b/node.gyp index d877bb22b69db7..4d6d5bc6b72339 100644 --- a/node.gyp +++ b/node.gyp @@ -82,6 +82,7 @@ 'lib/internal/cluster/shared_handle.js', 'lib/internal/cluster/utils.js', 'lib/internal/cluster/worker.js', + 'lib/internal/errors.js', 'lib/internal/freelist.js', 'lib/internal/fs.js', 'lib/internal/linkedlist.js', diff --git a/test/common.js b/test/common.js index 8fe1d3c91e7b4f..146344522a290f 100644 --- a/test/common.js +++ b/test/common.js @@ -620,3 +620,18 @@ exports.WPT = { assert.fail(undefined, undefined, `Reached unreachable code: ${desc}`); } }; + +// Useful for testing expected internal/error objects +exports.expectsError = function expectsError(code, type, message) { + return function(error) { + assert.strictEqual(error.code, code); + if (type !== undefined) + assert(error instanceof type, 'error is not the expected type'); + if (message !== undefined) { + if (!util.isRegExp(message)) + message = new RegExp(String(message)); + assert(message.test(error.message), 'error.message does not match'); + } + return true; + }; +}; diff --git a/test/parallel/test-internal-errors.js b/test/parallel/test-internal-errors.js new file mode 100644 index 00000000000000..6844ce539ee004 --- /dev/null +++ b/test/parallel/test-internal-errors.js @@ -0,0 +1,116 @@ +// Flags: --expose-internals +'use strict'; + +const common = require('../common'); +const errors = require('internal/errors'); +const assert = require('assert'); + +errors.E('TEST_ERROR_1', 'Error for testing purposes: %s'); +errors.E('TEST_ERROR_2', (a, b) => `${a} ${b}`); + +const err1 = new errors.Error('TEST_ERROR_1', 'test'); +const err2 = new errors.TypeError('TEST_ERROR_1', 'test'); +const err3 = new errors.RangeError('TEST_ERROR_1', 'test'); +const err4 = new errors.Error('TEST_ERROR_2', 'abc', 'xyz'); + +assert(err1 instanceof Error); +assert.strictEqual(err1.name, 'Error[TEST_ERROR_1]'); +assert.strictEqual(err1.message, 'Error for testing purposes: test'); +assert.strictEqual(err1.code, 'TEST_ERROR_1'); + +assert(err2 instanceof TypeError); +assert.strictEqual(err2.name, 'TypeError[TEST_ERROR_1]'); +assert.strictEqual(err2.message, 'Error for testing purposes: test'); +assert.strictEqual(err2.code, 'TEST_ERROR_1'); + +assert(err3 instanceof RangeError); +assert.strictEqual(err3.name, 'RangeError[TEST_ERROR_1]'); +assert.strictEqual(err3.message, 'Error for testing purposes: test'); +assert.strictEqual(err3.code, 'TEST_ERROR_1'); + +assert(err4 instanceof Error); +assert.strictEqual(err4.name, 'Error[TEST_ERROR_2]'); +assert.strictEqual(err4.message, 'abc xyz'); +assert.strictEqual(err4.code, 'TEST_ERROR_2'); + +assert.throws( + () => new errors.Error('TEST_FOO_KEY'), + /^AssertionError: An invalid error message key was used: TEST_FOO_KEY.$/); +// Calling it twice yields same result (using the key does not create it) +assert.throws( + () => new errors.Error('TEST_FOO_KEY'), + /^AssertionError: An invalid error message key was used: TEST_FOO_KEY.$/); +assert.throws( + () => new errors.Error(1), + /^AssertionError: 'number' === 'string'$/); +assert.throws( + () => new errors.Error({}), + /^AssertionError: 'object' === 'string'$/); +assert.throws( + () => new errors.Error([]), + /^AssertionError: 'object' === 'string'$/); +assert.throws( + () => new errors.Error(true), + /^AssertionError: 'boolean' === 'string'$/); +assert.throws( + () => new errors.TypeError(1), + /^AssertionError: 'number' === 'string'$/); +assert.throws( + () => new errors.TypeError({}), + /^AssertionError: 'object' === 'string'$/); +assert.throws( + () => new errors.TypeError([]), + /^AssertionError: 'object' === 'string'$/); +assert.throws( + () => new errors.TypeError(true), + /^AssertionError: 'boolean' === 'string'$/); +assert.throws( + () => new errors.RangeError(1), + /^AssertionError: 'number' === 'string'$/); +assert.throws( + () => new errors.RangeError({}), + /^AssertionError: 'object' === 'string'$/); +assert.throws( + () => new errors.RangeError([]), + /^AssertionError: 'object' === 'string'$/); +assert.throws( + () => new errors.RangeError(true), + /^AssertionError: 'boolean' === 'string'$/); + + +// Tests for common.expectsError +assert.doesNotThrow(() => { + assert.throws(() => { + throw new errors.TypeError('TEST_ERROR_1', 'a'); + }, common.expectsError('TEST_ERROR_1')); +}); + +assert.doesNotThrow(() => { + assert.throws(() => { + throw new errors.TypeError('TEST_ERROR_1', 'a'); + }, common.expectsError('TEST_ERROR_1', TypeError, /^Error for testing/)); +}); + +assert.doesNotThrow(() => { + assert.throws(() => { + throw new errors.TypeError('TEST_ERROR_1', 'a'); + }, common.expectsError('TEST_ERROR_1', TypeError)); +}); + +assert.doesNotThrow(() => { + assert.throws(() => { + throw new errors.TypeError('TEST_ERROR_1', 'a'); + }, common.expectsError('TEST_ERROR_1', Error)); +}); + +assert.throws(() => { + assert.throws(() => { + throw new errors.TypeError('TEST_ERROR_1', 'a'); + }, common.expectsError('TEST_ERROR_1', RangeError)); +}, /^AssertionError: error is not the expected type/); + +assert.throws(() => { + assert.throws(() => { + throw new errors.TypeError('TEST_ERROR_1', 'a'); + }, common.expectsError('TEST_ERROR_1', TypeError, /^Error for testing 2/)); +}, /^AssertionError: error.message does not match/); From 5f10827248d48463a674334db63e808616260de9 Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Mon, 13 Feb 2017 23:12:19 -0800 Subject: [PATCH 123/164] url: fix handling of ? in URLSearchParams creation PR-URL: https://github.com/nodejs/node/pull/11372 Fixes: https://github.com/nodejs/node/issues/11093 Ref: https://github.com/whatwg/url/issues/248 Reviewed-By: Joyee Cheung Reviewed-By: James M Snell --- lib/internal/url.js | 9 ++++----- test/parallel/test-whatwg-url-constructor.js | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/lib/internal/url.js b/lib/internal/url.js index a8406503cc0909..630c69d2cbaf81 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -95,12 +95,11 @@ function onParseComplete(flags, protocol, username, password, ctx.query = query; ctx.fragment = fragment; ctx.host = host; - if (this[searchParams]) { // invoked from href setter - initSearchParams(this[searchParams], query); - } else { - this[searchParams] = new URLSearchParams(query); + if (!this[searchParams]) { // invoked from URL constructor + this[searchParams] = new URLSearchParams(); + this[searchParams][context] = this; } - this[searchParams][context] = this; + initSearchParams(this[searchParams], query); } // Reused by URL constructor and URL#href setter. diff --git a/test/parallel/test-whatwg-url-constructor.js b/test/parallel/test-whatwg-url-constructor.js index a8a8667fc47021..ffcc022d3149b5 100644 --- a/test/parallel/test-whatwg-url-constructor.js +++ b/test/parallel/test-whatwg-url-constructor.js @@ -119,22 +119,22 @@ function runURLSearchParamTests() { // And in the other direction, altering searchParams propagates // back to 'search'. - // searchParams.append('i', ' j ') + searchParams.append('i', ' j ') // assert_equals(url.search, '?e=f&g=h&i=+j+') // assert_equals(url.searchParams.toString(), 'e=f&g=h&i=+j+') - // assert_equals(searchParams.get('i'), ' j ') + assert_equals(searchParams.get('i'), ' j ') - // searchParams.set('e', 'updated') + searchParams.set('e', 'updated') // assert_equals(url.search, '?e=updated&g=h&i=+j+') - // assert_equals(searchParams.get('e'), 'updated') + assert_equals(searchParams.get('e'), 'updated') - // var url2 = bURL('http://example.org/file??a=b&c=d') - // assert_equals(url2.search, '??a=b&c=d') - // assert_equals(url2.searchParams.toString(), '%3Fa=b&c=d') + var url2 = bURL('http://example.org/file??a=b&c=d') + assert_equals(url2.search, '??a=b&c=d') + assert_equals(url2.searchParams.toString(), '%3Fa=b&c=d') - // url2.href = 'http://example.org/file??a=b' - // assert_equals(url2.search, '??a=b') - // assert_equals(url2.searchParams.toString(), '%3Fa=b') + url2.href = 'http://example.org/file??a=b' + assert_equals(url2.search, '??a=b') + assert_equals(url2.searchParams.toString(), '%3Fa=b') }, 'URL.searchParams and URL.search setters, update propagation') } runURLSearchParamTests() From 46084e327098522dcccc16c4a4c4d6550e6c89bb Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Tue, 14 Feb 2017 10:35:27 -0800 Subject: [PATCH 124/164] test: refactor common.expectsError() * Report values in assertions. * Strict equality match if message is a string. * instanceof/typeof instead of deprecated util.isRegExp() PR-URL: https://github.com/nodejs/node/pull/11381 Reviewed-By: James M Snell Reviewed-By: Joyee Cheung Reviewed-By: Luigi Pinca --- test/common.js | 12 +++++++----- test/parallel/test-internal-errors.js | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/test/common.js b/test/common.js index 146344522a290f..b451b455ea1565 100644 --- a/test/common.js +++ b/test/common.js @@ -626,11 +626,13 @@ exports.expectsError = function expectsError(code, type, message) { return function(error) { assert.strictEqual(error.code, code); if (type !== undefined) - assert(error instanceof type, 'error is not the expected type'); - if (message !== undefined) { - if (!util.isRegExp(message)) - message = new RegExp(String(message)); - assert(message.test(error.message), 'error.message does not match'); + assert(error instanceof type, + `${error} is not the expected type ${type}`); + if (message instanceof RegExp) { + assert(message.test(error.message), + `${error.message} does not match ${message}`); + } else if (typeof message === 'string') { + assert.strictEqual(error.message, message); } return true; }; diff --git a/test/parallel/test-internal-errors.js b/test/parallel/test-internal-errors.js index 6844ce539ee004..526e6befaf89e8 100644 --- a/test/parallel/test-internal-errors.js +++ b/test/parallel/test-internal-errors.js @@ -107,10 +107,10 @@ assert.throws(() => { assert.throws(() => { throw new errors.TypeError('TEST_ERROR_1', 'a'); }, common.expectsError('TEST_ERROR_1', RangeError)); -}, /^AssertionError: error is not the expected type/); +}, /^AssertionError: .+ is not the expected type \S/); assert.throws(() => { assert.throws(() => { throw new errors.TypeError('TEST_ERROR_1', 'a'); }, common.expectsError('TEST_ERROR_1', TypeError, /^Error for testing 2/)); -}, /^AssertionError: error.message does not match/); +}, /AssertionError: .+ does not match \S/); From 91fac08c3b17fe0881ece39af1429f3491b3c57e Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 15 Feb 2017 15:09:23 -0800 Subject: [PATCH 125/164] test: use common.expectsError() Use common.expectsError() instead of rolling own validation function in test-http-request-invalid-method-error.js. common.expectsError() didn't exist when the test was written, but now it does. PR-URL: https://github.com/nodejs/node/pull/11408 Reviewed-By: James M Snell Reviewed-By: Gibson Fahnestock Reviewed-By: Santiago Gimeno Reviewed-By: Colin Ihrig --- test/parallel/test-http-request-invalid-method-error.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/parallel/test-http-request-invalid-method-error.js b/test/parallel/test-http-request-invalid-method-error.js index febb340eacd2a4..00f593fa6f9701 100644 --- a/test/parallel/test-http-request-invalid-method-error.js +++ b/test/parallel/test-http-request-invalid-method-error.js @@ -1,12 +1,9 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const http = require('http'); assert.throws( () => { http.request({method: '\0'}); }, - (error) => { - return (error instanceof TypeError) && - /Method must be a valid HTTP token/.test(error); - } + common.expectsError(undefined, TypeError, 'Method must be a valid HTTP token') ); From ae9b891a3904cd0b1017453ccec3f3bc18a1f093 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 15 Feb 2017 15:21:12 -0800 Subject: [PATCH 126/164] test: use expectsError in require-invalid-package Use common.expectsError() in place of inline validation function in test-require-invalid-package. PR-URL: https://github.com/nodejs/node/pull/11409 Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- test/parallel/test-require-invalid-package.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/parallel/test-require-invalid-package.js b/test/parallel/test-require-invalid-package.js index 45272cf5c3af9a..54ffaabe2ec3f2 100644 --- a/test/parallel/test-require-invalid-package.js +++ b/test/parallel/test-require-invalid-package.js @@ -1,9 +1,9 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); // Should be an invalid package path. -assert.throws(() => require('package.json'), (err) => { - return err && err.code === 'MODULE_NOT_FOUND'; -}); +assert.throws(() => require('package.json'), + common.expectsError('MODULE_NOT_FOUND') +); From 8e455a909312a0ebf4ec61c907035135b194dc31 Mon Sep 17 00:00:00 2001 From: Daijiro Wachi Date: Thu, 16 Feb 2017 21:06:33 +0100 Subject: [PATCH 127/164] test: add test for URLSearchParams inspection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The member methods of URLSearchParams should split across multiple lines with `util.inspect` depending on an option `breakLength`. PR-URL: https://github.com/nodejs/node/pull/11428 Reviewed-By: James M Snell Reviewed-By: Timothy Gu Reviewed-By: Joyee Cheung Reviewed-By: Michaël Zasso --- test/parallel/test-whatwg-url-searchparams-inspect.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/parallel/test-whatwg-url-searchparams-inspect.js b/test/parallel/test-whatwg-url-searchparams-inspect.js index 768ec5aa390f06..9a56543637dc55 100644 --- a/test/parallel/test-whatwg-url-searchparams-inspect.js +++ b/test/parallel/test-whatwg-url-searchparams-inspect.js @@ -13,6 +13,8 @@ assert.strictEqual(util.inspect(sp.keys()), "URLSearchParamsIterator { 'a', 'b', 'b' }"); assert.strictEqual(util.inspect(sp.values()), "URLSearchParamsIterator { 'a', 'b', 'c' }"); +assert.strictEqual(util.inspect(sp.keys(), {breakLength: 1}), + "URLSearchParamsIterator {\n 'a',\n 'b',\n 'b' }"); const iterator = sp.entries(); assert.strictEqual(util.inspect(iterator), From ea29d4852aca7a555f7007546d4b730b81731b5d Mon Sep 17 00:00:00 2001 From: Arseniy Maximov Date: Thu, 16 Feb 2017 03:35:34 +0300 Subject: [PATCH 128/164] test: use expectsError in test-debug-agent.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use common.expectsError() in place of inline validation function in test-debug-agent.js. PR-URL: https://github.com/nodejs/node/pull/11410 Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Michaël Zasso --- test/parallel/test-debug-agent.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/parallel/test-debug-agent.js b/test/parallel/test-debug-agent.js index d65029e5855b26..d2f57a0bf80550 100644 --- a/test/parallel/test-debug-agent.js +++ b/test/parallel/test-debug-agent.js @@ -1,12 +1,13 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const debug = require('_debug_agent'); assert.throws( () => { debug.start(); }, - function(err) { - return (err instanceof assert.AssertionError && - err.message === 'Debugger agent running without bindings!'); - } + common.expectsError( + undefined, + assert.AssertionError, + 'Debugger agent running without bindings!' + ) ); From ff927b2cf8e176e6dc59c02639b38b65a1b3833a Mon Sep 17 00:00:00 2001 From: Daijiro Wachi Date: Fri, 17 Feb 2017 21:32:46 +0100 Subject: [PATCH 129/164] test: add cases for unescape & unescapeBuffer These two functions in the querystring are used as a fallback. To test them, two test cases were added which make errors that will be caught. PR-URL: https://github.com/nodejs/node/pull/11326 Reviewed-By: James M Snell Reviewed-By: Timothy Gu Reviewed-By: Yuta Hiroto Reviewed-By: Michael Dawson Reviewed-By: Colin Ihrig --- test/parallel/test-querystring.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/parallel/test-querystring.js b/test/parallel/test-querystring.js index 988e210c4f2194..2c8e756efda0de 100644 --- a/test/parallel/test-querystring.js +++ b/test/parallel/test-querystring.js @@ -105,6 +105,17 @@ const qsNoMungeTestCases = [ ['trololol=yes&lololo=no', {'trololol': 'yes', 'lololo': 'no'}] ]; +const qsUnescapeTestCases = [ + ['there is nothing to unescape here', + 'there is nothing to unescape here'], + ['there%20are%20several%20spaces%20that%20need%20to%20be%20unescaped', + 'there are several spaces that need to be unescaped'], + ['there%2Qare%0-fake%escaped values in%%%%this%9Hstring', + 'there%2Qare%0-fake%escaped values in%%%%this%9Hstring'], + ['%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%30%31%32%33%34%35%36%37', + ' !"#$%&\'()*+,-./01234567'] +]; + assert.strictEqual('918854443121279438895193', qs.parse('id=918854443121279438895193').id); @@ -298,6 +309,12 @@ function demoDecode(str) { check(qs.parse('a=a&b=b&c=c', null, null, { decodeURIComponent: demoDecode }), { aa: 'aa', bb: 'bb', cc: 'cc' }); +// Test QueryString.unescape +function errDecode(str) { + throw new Error('To jump to the catch scope'); +} +check(qs.parse('a=a', null, null, { decodeURIComponent: errDecode }), + { a: 'a' }); // Test custom encode function demoEncode(str) { @@ -308,6 +325,12 @@ assert.strictEqual( qs.stringify(obj, null, null, { encodeURIComponent: demoEncode }), 'a=a&b=b&c=c'); +// Test QueryString.unescapeBuffer +qsUnescapeTestCases.forEach(function(testCase) { + assert.strictEqual(qs.unescape(testCase[0]), testCase[1]); + assert.strictEqual(qs.unescapeBuffer(testCase[0]).toString(), testCase[1]); +}); + // test overriding .unescape const prevUnescape = qs.unescape; qs.unescape = function(str) { From f5b4849208a7b0ced9333a77837658f684b07d0a Mon Sep 17 00:00:00 2001 From: Daijiro Wachi Date: Thu, 16 Feb 2017 14:03:23 +0100 Subject: [PATCH 130/164] test: test bottom-up merge sort in URLSearchParams MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bottom-up iterative stable merge sort is called only when the length of provided value is larger than 100. Added a test for it. PR-URL: https://github.com/nodejs/node/pull/11399 Reviewed-By: James M Snell Reviewed-By: Joyee Cheung Reviewed-By: Timothy Gu Reviewed-By: Michaël Zasso --- .../test-whatwg-url-searchparams-sort.js | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/test/parallel/test-whatwg-url-searchparams-sort.js b/test/parallel/test-whatwg-url-searchparams-sort.js index 0fcc01335aed57..5bddc14d947d8f 100644 --- a/test/parallel/test-whatwg-url-searchparams-sort.js +++ b/test/parallel/test-whatwg-url-searchparams-sort.js @@ -55,12 +55,25 @@ const { test, assert_array_equals } = common.WPT; /* eslint-enable */ // Tests below are not from WPT. -;[ + +// Test bottom-up iterative stable merge sort +const tests = [{input: '', output: []}]; +const pairs = []; +for (let i = 10; i < 100; i++) { + pairs.push([`a${i}`, 'b']); + tests[0].output.push([`a${i}`, 'b']); +} +tests[0].input = pairs.sort(() => Math.random() > 0.5) + .map((pair) => pair.join('=')).join('&'); + +tests.push( { 'input': 'z=a&=b&c=d', 'output': [['', 'b'], ['c', 'd'], ['z', 'a']] } -].forEach((val) => { +); + +tests.forEach((val) => { test(() => { const params = new URLSearchParams(val.input); let i = 0; From ecb3a7e9336b5de3196c7d5fb0fb590d1f37fed8 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Mon, 16 Jan 2017 15:24:28 -0800 Subject: [PATCH 131/164] test: make tls-socket-default-options tests run Because of a poorly constructed test, only one of the two test vectors ran. The test also failed to cover the authentication error that occurs when the server's certificate is not trusted. Both issues are fixed. Fix: https://github.com/nodejs/node/issues/10538 PR-URL: https://github.com/nodejs/node/pull/11005 Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell --- .../test-tls-socket-default-options.js | 94 ++++++++++--------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/test/parallel/test-tls-socket-default-options.js b/test/parallel/test-tls-socket-default-options.js index dd62a41090c88e..b4c5a9754eb84e 100644 --- a/test/parallel/test-tls-socket-default-options.js +++ b/test/parallel/test-tls-socket-default-options.js @@ -1,55 +1,59 @@ 'use strict'; const common = require('../common'); + +// Test a directly created TLS socket supports no options, and empty options. + const assert = require('assert'); +const join = require('path').join; +const { + connect, keys, tls +} = require(join(common.fixturesDir, 'tls-connect')); if (!common.hasCrypto) { common.skip('missing crypto'); return; } -const tls = require('tls'); - -const fs = require('fs'); - -const sent = 'hello world'; - -const serverOptions = { - isServer: true, - key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), - cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem') -}; - -function testSocketOptions(socket, socketOptions) { - let received = ''; - const server = tls.createServer(serverOptions, function(s) { - s.on('data', function(chunk) { - received += chunk; - }); - - s.on('end', function() { - server.close(); - s.destroy(); - assert.strictEqual(received, sent); - setImmediate(runTests); - }); - }).listen(0, function() { - const c = new tls.TLSSocket(socket, socketOptions); - c.connect(this.address().port, function() { - c.end(sent); - }); - }); - -} - -const testArgs = [ - [], - [undefined, {}] -]; -let n = 0; -function runTests() { - if (n++ < testArgs.length) { - testSocketOptions.apply(null, testArgs[n]); - } +test(undefined, (err) => { + assert.strictEqual(err.message, 'unable to verify the first certificate'); +}); + +test({}, (err) => { + assert.strictEqual(err.message, 'unable to verify the first certificate'); +}); + +test({secureContext: tls.createSecureContext({ca: keys.agent1.ca})}, (err) => { + assert.ifError(err); +}); + +function test(client, callback) { + callback = common.mustCall(callback); + connect({ + server: { + key: keys.agent1.key, + cert: keys.agent1.cert, + }, + }, function(err, pair, cleanup) { + assert.strictEqual(err.message, 'unable to verify the first certificate'); + let recv = ''; + pair.server.server.once('secureConnection', common.mustCall((conn) => { + conn.on('data', (data) => recv += data); + conn.on('end', common.mustCall(() => { + // Server sees nothing wrong with connection, even though the client's + // authentication of the server cert failed. + assert.strictEqual(recv, 'hello'); + cleanup(); + })); + })); + + // Client doesn't support the 'secureConnect' event, and doesn't error if + // authentication failed. Caller must explicitly check for failure. + (new tls.TLSSocket(null, client)).connect(pair.server.server.address().port) + .on('connect', common.mustCall(function() { + this.end('hello'); + })) + .on('secure', common.mustCall(function() { + callback(this.ssl.verifyError()); + })); + }); } - -runTests(); From 4e327708a92c4f1bb87400fca8af2fb5a14f4d34 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Mon, 16 Jan 2017 19:36:42 -0800 Subject: [PATCH 132/164] tls: new tls.TLSSocket() supports sec ctx options Add support to new tls.TLSSocket() to create a SecureContext object with all its supported options, in the same way they are supported for all the other APIs that need SecureContext objects. Fix: https://github.com/nodejs/node/issues/10538 PR-URL: https://github.com/nodejs/node/pull/11005 Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell --- doc/api/tls.md | 7 ++++++- lib/_tls_wrap.js | 2 +- test/parallel/test-tls-socket-default-options.js | 12 +++++++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/doc/api/tls.md b/doc/api/tls.md index 97bc8301f4ead1..161bc8e48421ce 100644 --- a/doc/api/tls.md +++ b/doc/api/tls.md @@ -487,7 +487,12 @@ changes: will be emitted on the socket before establishing a secure communication * `secureContext`: Optional TLS context object created with [`tls.createSecureContext()`][]. If a `secureContext` is _not_ provided, one - will be created by calling [`tls.createSecureContext()`][] with no options. + will be created by passing the entire `options` object to + `tls.createSecureContext()`. *Note*: In effect, all + [`tls.createSecureContext()`][] options can be provided, but they will be + _completely ignored_ unless the `secureContext` option is missing. + * ...: Optional [`tls.createSecureContext()`][] options can be provided, see + the `secureContext` option for more information. Construct a new `tls.TLSSocket` object from an existing TCP socket. diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index 3761a85181d70a..ebd36519cf1525 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -351,7 +351,7 @@ TLSSocket.prototype._wrapHandle = function(wrap) { // Wrap socket's handle var context = options.secureContext || options.credentials || - tls.createSecureContext(); + tls.createSecureContext(options); res = tls_wrap.wrap(handle._externalStream, context.context, !!options.isServer); diff --git a/test/parallel/test-tls-socket-default-options.js b/test/parallel/test-tls-socket-default-options.js index b4c5a9754eb84e..24b7a5d34ec0fb 100644 --- a/test/parallel/test-tls-socket-default-options.js +++ b/test/parallel/test-tls-socket-default-options.js @@ -1,7 +1,7 @@ 'use strict'; const common = require('../common'); -// Test a directly created TLS socket supports no options, and empty options. +// Test directly created TLS sockets and options. const assert = require('assert'); const join = require('path').join; @@ -26,6 +26,16 @@ test({secureContext: tls.createSecureContext({ca: keys.agent1.ca})}, (err) => { assert.ifError(err); }); +test({ca: keys.agent1.ca}, (err) => { + assert.ifError(err); +}); + +// Secure context options, like ca, are ignored if a sec ctx is explicitly +// provided. +test({secureContext: tls.createSecureContext(), ca: keys.agent1.ca}, (err) => { + assert.strictEqual(err.message, 'unable to verify the first certificate'); +}); + function test(client, callback) { callback = common.mustCall(callback); connect({ From 4109e0edc4309289b98d7cfb936cb6095060f95d Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 17 Feb 2017 20:32:40 +0800 Subject: [PATCH 133/164] test: remove WHATWG URL test data file extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make url-tests a js file so we can comment out incompatible tests PR-URL: https://github.com/nodejs/node/pull/11439 Reviewed-By: Michaël Zasso Reviewed-By: Timothy Gu Reviewed-By: James M Snell --- test/fixtures/{url-tests.json => url-tests.js} | 10 ++++++++-- test/known_issues/test-url-parse-conformance.js | 2 +- test/parallel/test-whatwg-url-constructor.js | 2 +- test/parallel/test-whatwg-url-inspect.js | 4 ++-- test/parallel/test-whatwg-url-origin.js | 2 +- test/parallel/test-whatwg-url-parsing.js | 2 +- 6 files changed, 14 insertions(+), 8 deletions(-) rename test/fixtures/{url-tests.json => url-tests.js} (99%) diff --git a/test/fixtures/url-tests.json b/test/fixtures/url-tests.js similarity index 99% rename from test/fixtures/url-tests.json rename to test/fixtures/url-tests.js index fb286ed91fcbd7..a762f8213c9135 100644 --- a/test/fixtures/url-tests.json +++ b/test/fixtures/url-tests.js @@ -1,7 +1,13 @@ +'use strict'; + +/* WPT Refs: + https://github.com/w3c/web-platform-tests/blob/master/url/urltestdata.json + License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html +*/ + +module.exports = [ "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/segments.js", - "License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html", - "Source: https://github.com/w3c/web-platform-tests/tree/master/url", { "input": "http://example\t.\norg", "base": "http://example.org/foo/bar", diff --git a/test/known_issues/test-url-parse-conformance.js b/test/known_issues/test-url-parse-conformance.js index f7fcec821c8e50..62c36da87e6678 100644 --- a/test/known_issues/test-url-parse-conformance.js +++ b/test/known_issues/test-url-parse-conformance.js @@ -7,7 +7,7 @@ const url = require('url'); const assert = require('assert'); const path = require('path'); -const tests = require(path.join(common.fixturesDir, 'url-tests.json')); +const tests = require(path.join(common.fixturesDir, 'url-tests')); let failed = 0; let attempted = 0; diff --git a/test/parallel/test-whatwg-url-constructor.js b/test/parallel/test-whatwg-url-constructor.js index ffcc022d3149b5..3b567f4a9439e0 100644 --- a/test/parallel/test-whatwg-url-constructor.js +++ b/test/parallel/test-whatwg-url-constructor.js @@ -11,7 +11,7 @@ if (!common.hasIntl) { } const request = { - response: require(path.join(common.fixturesDir, 'url-tests.json')) + response: require(path.join(common.fixturesDir, 'url-tests')) }; /* eslint-disable */ diff --git a/test/parallel/test-whatwg-url-inspect.js b/test/parallel/test-whatwg-url-inspect.js index 4c6c8771b9f8f4..4afbbc13102905 100644 --- a/test/parallel/test-whatwg-url-inspect.js +++ b/test/parallel/test-whatwg-url-inspect.js @@ -13,9 +13,9 @@ if (!common.hasIntl) { } // Tests below are not from WPT. -const tests = require(path.join(common.fixturesDir, 'url-tests.json')); +const tests = require(path.join(common.fixturesDir, 'url-tests')); const additional_tests = require( - path.join(common.fixturesDir, 'url-tests-additional.js')); + path.join(common.fixturesDir, 'url-tests-additional')); const allTests = additional_tests.slice(); for (const test of tests) { diff --git a/test/parallel/test-whatwg-url-origin.js b/test/parallel/test-whatwg-url-origin.js index 1186a1d1844147..c7126585e170e7 100644 --- a/test/parallel/test-whatwg-url-origin.js +++ b/test/parallel/test-whatwg-url-origin.js @@ -11,7 +11,7 @@ if (!common.hasIntl) { } const request = { - response: require(path.join(common.fixturesDir, 'url-tests.json')) + response: require(path.join(common.fixturesDir, 'url-tests')) }; /* eslint-disable */ diff --git a/test/parallel/test-whatwg-url-parsing.js b/test/parallel/test-whatwg-url-parsing.js index 6775f79746a57d..e4f8306ead8d87 100644 --- a/test/parallel/test-whatwg-url-parsing.js +++ b/test/parallel/test-whatwg-url-parsing.js @@ -12,7 +12,7 @@ if (!common.hasIntl) { } // Tests below are not from WPT. -const tests = require(path.join(common.fixturesDir, 'url-tests.json')); +const tests = require(path.join(common.fixturesDir, 'url-tests')); for (const test of tests) { if (typeof test === 'string') From e92ddd46bbbe656e928fd1191bfa439747611f78 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 17 Feb 2017 21:05:33 +0800 Subject: [PATCH 134/164] test: synchronize WPT url test data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Synchronize url-tests to upstream b207902 and comment out incompatible tests PR-URL: https://github.com/nodejs/node/pull/11439 Reviewed-By: Michaël Zasso Reviewed-By: Timothy Gu Reviewed-By: James M Snell --- test/fixtures/url-tests.js | 933 ++++++++++++++++++- test/parallel/test-whatwg-url-constructor.js | 2 +- 2 files changed, 894 insertions(+), 41 deletions(-) diff --git a/test/fixtures/url-tests.js b/test/fixtures/url-tests.js index a762f8213c9135..3b162391cd2ef5 100644 --- a/test/fixtures/url-tests.js +++ b/test/fixtures/url-tests.js @@ -1,10 +1,9 @@ 'use strict'; /* WPT Refs: - https://github.com/w3c/web-platform-tests/blob/master/url/urltestdata.json + https://github.com/w3c/web-platform-tests/blob/b207902/url/urltestdata.json License: http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html */ - module.exports = [ "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/script-tests/segments.js", @@ -173,6 +172,20 @@ module.exports = "search": "?%20d%20", "hash": "# e" }, + { + "input": "lolscheme:x x#x x", + "base": "about:blank", + "href": "lolscheme:x x#x x", + "protocol": "lolscheme:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "x x", + "search": "", + "hash": "#x x" + }, { "input": "http://f:/c", "base": "http://example.org/foo/bar", @@ -558,21 +571,21 @@ module.exports = "search": "", "hash": "" }, - { - "input": "foo://", - "base": "http://example.org/foo/bar", - "href": "foo:///", - "origin": "null", - "protocol": "foo:", - "username": "", - "password": "", - "host": "", - "hostname": "", - "port": "", - "pathname": "/", - "search": "", - "hash": "" - }, + // { + // "input": "foo://", + // "base": "http://example.org/foo/bar", + // "href": "foo://", + // "origin": "null", + // "protocol": "foo:", + // "username": "", + // "password": "", + // "host": "", + // "hostname": "", + // "port": "", + // "pathname": "", + // "search": "", + // "hash": "" + // }, { "input": "http://a:b@c:29/d", "base": "http://example.org/foo/bar", @@ -1027,6 +1040,26 @@ module.exports = "search": "", "hash": "" }, + // { + // "input": "file://example:1/", + // "base": "about:blank", + // "failure": true + // }, + // { + // "input": "file://example:test/", + // "base": "about:blank", + // "failure": true + // }, + { + "input": "file://example%/", + "base": "about:blank", + "failure": true + }, + { + "input": "file://[example]/", + "base": "about:blank", + "failure": true + }, { "input": "ftps:/example.com/", "base": "http://example.org/foo/bar", @@ -2256,11 +2289,6 @@ module.exports = "search": "", "hash": "# %C2%BB" }, - { - "input": "http://[www.google.com]/", - "base": "about:blank", - "failure": true - }, { "input": "http://www.google.com", "base": "about:blank", @@ -3561,6 +3589,32 @@ module.exports = "base": "http://other.com/", "failure": true }, + // "U+FFFD", + // { + // "input": "https://\ufffd", + // "base": "about:blank", + // "failure": true + // }, + // { + // "input": "https://%EF%BF%BD", + // "base": "about:blank", + // "failure": true + // }, + { + "input": "https://x/\ufffd?\ufffd#\ufffd", + "base": "about:blank", + "href": "https://x/%EF%BF%BD?%EF%BF%BD#%EF%BF%BD", + "origin": "https://x", + "protocol": "https:", + "username": "", + "password": "", + "host": "x", + "hostname": "x", + "port": "", + "pathname": "/%EF%BF%BD", + "search": "?%EF%BF%BD", + "hash": "#%EF%BF%BD" + }, "Test name prepping, fullwidth input should be converted to ASCII and NOT IDN-ized. This is 'Go' in fullwidth UTF-8/UTF-16.", { "input": "http://Go.com", @@ -3668,18 +3722,23 @@ module.exports = "base": "http://other.com/", "failure": true }, - "Invalid escaping should trigger the regular host error handling", + "Invalid escaping in hosts causes failure", { "input": "http://%3g%78%63%30%2e%30%32%35%30%2E.01", "base": "http://other.com/", "failure": true }, - "Something that isn't exactly an IP should get treated as a host and spaces escaped", + "A space in a host causes failure", { "input": "http://192.168.0.1 hello", "base": "http://other.com/", "failure": true }, + { + "input": "https://x x:12", + "base": "about:blank", + "failure": true + }, "Fullwidth and escaped UTF-8 fullwidth should still be treated as IP", { "input": "http://0Xc0.0250.01", @@ -3697,11 +3756,36 @@ module.exports = "hash": "" }, "Broken IPv6", + { + "input": "http://[www.google.com]/", + "base": "about:blank", + "failure": true + }, { "input": "http://[google.com]", "base": "http://other.com/", "failure": true }, + // { + // "input": "http://[::1.2.3.4x]", + // "base": "http://other.com/", + // "failure": true + // }, + // { + // "input": "http://[::1.2.3.]", + // "base": "http://other.com/", + // "failure": true + // }, + // { + // "input": "http://[::1.2.]", + // "base": "http://other.com/", + // "failure": true + // }, + // { + // "input": "http://[::1.]", + // "base": "http://other.com/", + // "failure": true + // }, "Misc Unicode", { "input": "http://foo:💩@example.com/bar", @@ -4244,22 +4328,111 @@ module.exports = "search": "", "hash": "" }, - "# unknown schemes and non-ASCII domains", + // "# unknown schemes and their hosts", + // { + // "input": "sc://ñ.test/", + // "base": "about:blank", + // "href": "sc://%C3%B1.test/", + // "origin": "null", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "%C3%B1.test", + // "hostname": "%C3%B1.test", + // "port": "", + // "pathname": "/", + // "search": "", + // "hash": "" + // }, + // { + // "input": "sc://\u001F!\"$&'()*+,-.;<=>^_`{|}~/", + // "base": "about:blank", + // "href": "sc://%1F!\"$&'()*+,-.;<=>^_`{|}~/", + // "origin": "null", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "%1F!\"$&'()*+,-.;<=>^_`{|}~", + // "hostname": "%1F!\"$&'()*+,-.;<=>^_`{|}~", + // "port": "", + // "pathname": "/", + // "search": "", + // "hash": "" + // }, + { + "input": "sc://\u0000/", + "base": "about:blank", + "failure": true + }, { - "input": "sc://ñ.test/", + "input": "sc:// /", "base": "about:blank", - "href": "sc://xn--ida.test/", - "origin": "null", - "protocol": "sc:", - "username": "", - "password": "", - "host": "xn--ida.test", - "hostname": "xn--ida.test", - "port": "", - "pathname": "/", - "search": "", - "hash": "" + "failure": true }, + // { + // "input": "sc://%/", + // "base": "about:blank", + // "href": "sc://%/", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "%", + // "hostname": "%", + // "port": "", + // "pathname": "/", + // "search": "", + // "hash": "" + // }, + // { + // "input": "sc://@/", + // "base": "about:blank", + // "failure": true + // }, + // { + // "input": "sc://te@s:t@/", + // "base": "about:blank", + // "failure": true + // }, + // { + // "input": "sc://:/", + // "base": "about:blank", + // "failure": true + // }, + // { + // "input": "sc://:12/", + // "base": "about:blank", + // "failure": true + // }, + { + "input": "sc://[/", + "base": "about:blank", + "failure": true + }, + { + "input": "sc://\\/", + "base": "about:blank", + "failure": true + }, + { + "input": "sc://]/", + "base": "about:blank", + "failure": true + }, + // { + // "input": "x", + // "base": "sc://ñ", + // "href": "sc://%C3%B1/x", + // "origin": "null", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "%C3%B1", + // "hostname": "%C3%B1", + // "port": "", + // "pathname": "/x", + // "search": "", + // "hash": "" + // }, "# unknown schemes and backslashes", { "input": "sc:\\../", @@ -4292,6 +4465,88 @@ module.exports = "search": "", "hash": "" }, + "# unknown scheme with bogus percent-encoding", + { + "input": "wow:%NBD", + "base": "about:blank", + "href": "wow:%NBD", + "origin": "null", + "protocol": "wow:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "%NBD", + "search": "", + "hash": "" + }, + { + "input": "wow:%1G", + "base": "about:blank", + "href": "wow:%1G", + "origin": "null", + "protocol": "wow:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "%1G", + "search": "", + "hash": "" + }, + "# Hosts and percent-encoding", + // { + // "input": "ftp://example.com%80/", + // "base": "about:blank", + // "failure": true + // }, + // { + // "input": "ftp://example.com%A0/", + // "base": "about:blank", + // "failure": true + // }, + // { + // "input": "https://example.com%80/", + // "base": "about:blank", + // "failure": true + // }, + // { + // "input": "https://example.com%A0/", + // "base": "about:blank", + // "failure": true + // }, + { + "input": "ftp://%e2%98%83", + "base": "about:blank", + "href": "ftp://xn--n3h/", + "origin": "ftp://☃", + "protocol": "ftp:", + "username": "", + "password": "", + "host": "xn--n3h", + "hostname": "xn--n3h", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + { + "input": "https://%e2%98%83", + "base": "about:blank", + "href": "https://xn--n3h/", + "origin": "https://☃", + "protocol": "https:", + "username": "", + "password": "", + "host": "xn--n3h", + "hostname": "xn--n3h", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, "# tests from jsdom/whatwg-url designed for code coverage", { "input": "http://127.0.0.1:10100/relative_import.html", @@ -4384,7 +4639,7 @@ module.exports = "port": "", "pathname": "/foo/bar", "search": "??a=b&c=d", - "searchParams": "%3Fa=b&c=d", + // "searchParams": "%3Fa=b&c=d", "hash": "" }, "# Scheme only", @@ -4439,7 +4694,7 @@ module.exports = "port": "", "pathname": "/baz", "search": "?qux", - "searchParams": "", + "searchParams": "qux=", "hash": "#foo%08bar" }, "# IPv4 parsing (via https://github.com/nodejs/node/pull/10317)", @@ -4613,6 +4868,50 @@ module.exports = "search": "", "hash": "" }, + { + "input": "https://0x.0x.0", + "base": "about:blank", + "href": "https://0.0.0.0/", + "origin": "https://0.0.0.0", + "protocol": "https:", + "username": "", + "password": "", + "host": "0.0.0.0", + "hostname": "0.0.0.0", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + "# file URLs containing percent-encoded Windows drive letters (shouldn't work)", + { + "input": "file:///C%3A/", + "base": "about:blank", + "href": "file:///C%3A/", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/C%3A/", + "search": "", + "hash": "" + }, + { + "input": "file:///C%7C/", + "base": "about:blank", + "href": "file:///C%7C/", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/C%7C/", + "search": "", + "hash": "" + }, "# file URLs relative to other file URLs (via https://github.com/jsdom/whatwg-url/pull/60)", { "input": "pix/submit.gif", @@ -4656,7 +4955,7 @@ module.exports = "search": "", "hash": "" }, - "# More file URL tests by zcorpan", + "# More file URL tests by zcorpan and annevk", { "input": "/", "base": "file:///C:/a/b", @@ -4727,6 +5026,90 @@ module.exports = "search": "", "hash": "" }, + { + "input": "", + "base": "file:///test?test#test", + "href": "file:///test?test", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "?test", + "hash": "" + }, + { + "input": "file:", + "base": "file:///test?test#test", + "href": "file:///test?test", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "?test", + "hash": "" + }, + { + "input": "?x", + "base": "file:///test?test#test", + "href": "file:///test?x", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "?x", + "hash": "" + }, + { + "input": "file:?x", + "base": "file:///test?test#test", + "href": "file:///test?x", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "?x", + "hash": "" + }, + { + "input": "#x", + "base": "file:///test?test#test", + "href": "file:///test?test#x", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "?test", + "hash": "#x" + }, + { + "input": "file:#x", + "base": "file:///test?test#test", + "href": "file:///test?test#x", + "protocol": "file:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/test", + "search": "?test", + "hash": "#x" + }, "# file URLs without base URL by Rimas Misevičius", { "input": "file:", @@ -4769,5 +5152,475 @@ module.exports = "pathname": "/", "search": "", "hash": "#frag" + }, + "# IPv6 tests", + { + "input": "http://[1:0::]", + "base": "http://example.net/", + "href": "http://[1::]/", + "origin": "http://[1::]", + "protocol": "http:", + "username": "", + "password": "", + "host": "[1::]", + "hostname": "[1::]", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + { + "input": "http://[0:1:2:3:4:5:6:7:8]", + "base": "http://example.net/", + "failure": true + }, + { + "input": "https://[0::0::0]", + "base": "about:blank", + "failure": true + }, + { + "input": "https://[0:.0]", + "base": "about:blank", + "failure": true + }, + { + "input": "https://[0:0:]", + "base": "about:blank", + "failure": true + }, + { + "input": "https://[0:1:2:3:4:5:6:7.0.0.0.1]", + "base": "about:blank", + "failure": true + }, + { + "input": "https://[0:1.00.0.0.0]", + "base": "about:blank", + "failure": true + }, + { + "input": "https://[0:1.290.0.0.0]", + "base": "about:blank", + "failure": true + }, + { + "input": "https://[0:1.23.23]", + "base": "about:blank", + "failure": true + }, + "# Empty host", + { + "input": "http://?", + "base": "about:blank", + "failure": "true" + }, + { + "input": "http://#", + "base": "about:blank", + "failure": "true" + }, + "# Non-special-URL path tests", + // { + // "input": "sc://ñ", + // "base": "about:blank", + // "href": "sc://%C3%B1", + // "origin": "null", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "%C3%B1", + // "hostname": "%C3%B1", + // "port": "", + // "pathname": "", + // "search": "", + // "hash": "" + // }, + // { + // "input": "sc://ñ?x", + // "base": "about:blank", + // "href": "sc://%C3%B1?x", + // "origin": "null", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "%C3%B1", + // "hostname": "%C3%B1", + // "port": "", + // "pathname": "", + // "search": "?x", + // "hash": "" + // }, + // { + // "input": "sc://ñ#x", + // "base": "about:blank", + // "href": "sc://%C3%B1#x", + // "origin": "null", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "%C3%B1", + // "hostname": "%C3%B1", + // "port": "", + // "pathname": "", + // "search": "", + // "hash": "#x" + // }, + // { + // "input": "#x", + // "base": "sc://ñ", + // "href": "sc://%C3%B1#x", + // "origin": "null", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "%C3%B1", + // "hostname": "%C3%B1", + // "port": "", + // "pathname": "", + // "search": "", + // "hash": "#x" + // }, + // { + // "input": "?x", + // "base": "sc://ñ", + // "href": "sc://%C3%B1?x", + // "origin": "null", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "%C3%B1", + // "hostname": "%C3%B1", + // "port": "", + // "pathname": "", + // "search": "?x", + // "hash": "" + // }, + // { + // "input": "sc://?", + // "base": "about:blank", + // "href": "sc://?", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "", + // "hostname": "", + // "port": "", + // "pathname": "", + // "search": "", + // "hash": "" + // }, + // { + // "input": "sc://#", + // "base": "about:blank", + // "href": "sc://#", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "", + // "hostname": "", + // "port": "", + // "pathname": "", + // "search": "", + // "hash": "" + // }, + { + "input": "///", + "base": "sc://x/", + "href": "sc:///", + "protocol": "sc:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + // { + // "input": "////", + // "base": "sc://x/", + // "href": "sc:////", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "", + // "hostname": "", + // "port": "", + // "pathname": "//", + // "search": "", + // "hash": "" + // }, + // { + // "input": "////x/", + // "base": "sc://x/", + // "href": "sc:////x/", + // "protocol": "sc:", + // "username": "", + // "password": "", + // "host": "", + // "hostname": "", + // "port": "", + // "pathname": "//x/", + // "search": "", + // "hash": "" + // }, + { + "input": "tftp://foobar.com/someconfig;mode=netascii", + "base": "about:blank", + "href": "tftp://foobar.com/someconfig;mode=netascii", + "origin": "null", + "protocol": "tftp:", + "username": "", + "password": "", + "host": "foobar.com", + "hostname": "foobar.com", + "port": "", + "pathname": "/someconfig;mode=netascii", + "search": "", + "hash": "" + }, + { + "input": "telnet://user:pass@foobar.com:23/", + "base": "about:blank", + "href": "telnet://user:pass@foobar.com:23/", + "origin": "null", + "protocol": "telnet:", + "username": "user", + "password": "pass", + "host": "foobar.com:23", + "hostname": "foobar.com", + "port": "23", + "pathname": "/", + "search": "", + "hash": "" + }, + { + "input": "ut2004://10.10.10.10:7777/Index.ut2", + "base": "about:blank", + "href": "ut2004://10.10.10.10:7777/Index.ut2", + "origin": "null", + "protocol": "ut2004:", + "username": "", + "password": "", + "host": "10.10.10.10:7777", + "hostname": "10.10.10.10", + "port": "7777", + "pathname": "/Index.ut2", + "search": "", + "hash": "" + }, + { + "input": "redis://foo:bar@somehost:6379/0?baz=bam&qux=baz", + "base": "about:blank", + "href": "redis://foo:bar@somehost:6379/0?baz=bam&qux=baz", + "origin": "null", + "protocol": "redis:", + "username": "foo", + "password": "bar", + "host": "somehost:6379", + "hostname": "somehost", + "port": "6379", + "pathname": "/0", + "search": "?baz=bam&qux=baz", + "hash": "" + }, + { + "input": "rsync://foo@host:911/sup", + "base": "about:blank", + "href": "rsync://foo@host:911/sup", + "origin": "null", + "protocol": "rsync:", + "username": "foo", + "password": "", + "host": "host:911", + "hostname": "host", + "port": "911", + "pathname": "/sup", + "search": "", + "hash": "" + }, + { + "input": "git://github.com/foo/bar.git", + "base": "about:blank", + "href": "git://github.com/foo/bar.git", + "origin": "null", + "protocol": "git:", + "username": "", + "password": "", + "host": "github.com", + "hostname": "github.com", + "port": "", + "pathname": "/foo/bar.git", + "search": "", + "hash": "" + }, + { + "input": "irc://myserver.com:6999/channel?passwd", + "base": "about:blank", + "href": "irc://myserver.com:6999/channel?passwd", + "origin": "null", + "protocol": "irc:", + "username": "", + "password": "", + "host": "myserver.com:6999", + "hostname": "myserver.com", + "port": "6999", + "pathname": "/channel", + "search": "?passwd", + "hash": "" + }, + { + "input": "dns://fw.example.org:9999/foo.bar.org?type=TXT", + "base": "about:blank", + "href": "dns://fw.example.org:9999/foo.bar.org?type=TXT", + "origin": "null", + "protocol": "dns:", + "username": "", + "password": "", + "host": "fw.example.org:9999", + "hostname": "fw.example.org", + "port": "9999", + "pathname": "/foo.bar.org", + "search": "?type=TXT", + "hash": "" + }, + { + "input": "ldap://localhost:389/ou=People,o=JNDITutorial", + "base": "about:blank", + "href": "ldap://localhost:389/ou=People,o=JNDITutorial", + "origin": "null", + "protocol": "ldap:", + "username": "", + "password": "", + "host": "localhost:389", + "hostname": "localhost", + "port": "389", + "pathname": "/ou=People,o=JNDITutorial", + "search": "", + "hash": "" + }, + { + "input": "git+https://github.com/foo/bar", + "base": "about:blank", + "href": "git+https://github.com/foo/bar", + "origin": "null", + "protocol": "git+https:", + "username": "", + "password": "", + "host": "github.com", + "hostname": "github.com", + "port": "", + "pathname": "/foo/bar", + "search": "", + "hash": "" + }, + { + "input": "urn:ietf:rfc:2648", + "base": "about:blank", + "href": "urn:ietf:rfc:2648", + "origin": "null", + "protocol": "urn:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "ietf:rfc:2648", + "search": "", + "hash": "" + }, + { + "input": "tag:joe@example.org,2001:foo/bar", + "base": "about:blank", + "href": "tag:joe@example.org,2001:foo/bar", + "origin": "null", + "protocol": "tag:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "joe@example.org,2001:foo/bar", + "search": "", + "hash": "" + }, + "# percent encoded hosts in non-special-URLs", + // { + // "input": "non-special://%E2%80%A0/", + // "base": "about:blank", + // "href": "non-special://%E2%80%A0/", + // "protocol": "non-special:", + // "username": "", + // "password": "", + // "host": "%E2%80%A0", + // "hostname": "%E2%80%A0", + // "port": "", + // "pathname": "/", + // "search": "", + // "hash": "" + // }, + // { + // "input": "non-special://H%4fSt/path", + // "base": "about:blank", + // "href": "non-special://H%4fSt/path", + // "protocol": "non-special:", + // "username": "", + // "password": "", + // "host": "H%4fSt", + // "hostname": "H%4fSt", + // "port": "", + // "pathname": "/path", + // "search": "", + // "hash": "" + // }, + "# IPv6 in non-special-URLs", + { + "input": "non-special://[1:2:0:0:5:0:0:0]/", + "base": "about:blank", + "href": "non-special://[1:2:0:0:5::]/", + "protocol": "non-special:", + "username": "", + "password": "", + "host": "[1:2:0:0:5::]", + "hostname": "[1:2:0:0:5::]", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + { + "input": "non-special://[1:2:0:0:0:0:0:3]/", + "base": "about:blank", + "href": "non-special://[1:2::3]/", + "protocol": "non-special:", + "username": "", + "password": "", + "host": "[1:2::3]", + "hostname": "[1:2::3]", + "port": "", + "pathname": "/", + "search": "", + "hash": "" + }, + { + "input": "non-special://[1:2::3]:80/", + "base": "about:blank", + "href": "non-special://[1:2::3]:80/", + "protocol": "non-special:", + "username": "", + "password": "", + "host": "[1:2::3]:80", + "hostname": "[1:2::3]", + "port": "80", + "pathname": "/", + "search": "", + "hash": "" + }, + { + "input": "non-special://[:80/", + "base": "about:blank", + "failure": true } ] diff --git a/test/parallel/test-whatwg-url-constructor.js b/test/parallel/test-whatwg-url-constructor.js index 3b567f4a9439e0..c5d70b3f4c1544 100644 --- a/test/parallel/test-whatwg-url-constructor.js +++ b/test/parallel/test-whatwg-url-constructor.js @@ -63,7 +63,7 @@ function runURLTests(urltests) { assert_equals(url.search, expected.search, "search") if ("searchParams" in expected) { assert_true("searchParams" in url) - // assert_equals(url.searchParams.toString(), expected.searchParams, "searchParams") + assert_equals(url.searchParams.toString(), expected.searchParams, "searchParams") } assert_equals(url.hash, expected.hash, "hash") }, "Parsing: <" + expected.input + "> against <" + expected.base + ">") From d7fd694cee65e0010703de8cfdf6b61c36926fa8 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 17 Feb 2017 21:11:21 +0800 Subject: [PATCH 135/164] test: remove redundant additional url tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit url-tests-additional.js now is a placeholder since existing test cases have been upstreamed. This is now a temporary place for test cases not upstreamed yet. Refs: https://github.com/w3c/web-platform-tests/pull/4693 PR-URL: https://github.com/nodejs/node/pull/11439 Reviewed-By: Michaël Zasso Reviewed-By: Timothy Gu Reviewed-By: James M Snell --- test/fixtures/url-tests-additional.js | 89 ++------------------------- 1 file changed, 4 insertions(+), 85 deletions(-) diff --git a/test/fixtures/url-tests-additional.js b/test/fixtures/url-tests-additional.js index 7e3282d17d091b..ffe47fb639dcba 100644 --- a/test/fixtures/url-tests-additional.js +++ b/test/fixtures/url-tests-additional.js @@ -1,87 +1,6 @@ +'use strict'; + +// This file contains test cases not part of the WPT + module.exports = [ - { - 'url': 'tftp://foobar.com/someconfig;mode=netascii', - 'protocol': 'tftp:', - 'hostname': 'foobar.com', - 'pathname': '/someconfig;mode=netascii' - }, - { - 'url': 'telnet://user:pass@foobar.com:23/', - 'protocol': 'telnet:', - 'username': 'user', - 'password': 'pass', - 'hostname': 'foobar.com', - 'port': '23', - 'pathname': '/' - }, - { - 'url': 'ut2004://10.10.10.10:7777/Index.ut2', - 'protocol': 'ut2004:', - 'hostname': '10.10.10.10', - 'port': '7777', - 'pathname': '/Index.ut2' - }, - { - 'url': 'redis://foo:bar@somehost:6379/0?baz=bam&qux=baz', - 'protocol': 'redis:', - 'username': 'foo', - 'password': 'bar', - 'hostname': 'somehost', - 'port': '6379', - 'pathname': '/0', - 'search': '?baz=bam&qux=baz' - }, - { - 'url': 'rsync://foo@host:911/sup', - 'protocol': 'rsync:', - 'username': 'foo', - 'hostname': 'host', - 'port': '911', - 'pathname': '/sup' - }, - { - 'url': 'git://github.com/foo/bar.git', - 'protocol': 'git:', - 'hostname': 'github.com', - 'pathname': '/foo/bar.git' - }, - { - 'url': 'irc://myserver.com:6999/channel?passwd', - 'protocol': 'irc:', - 'hostname': 'myserver.com', - 'port': '6999', - 'pathname': '/channel', - 'search': '?passwd' - }, - { - 'url': 'dns://fw.example.org:9999/foo.bar.org?type=TXT', - 'protocol': 'dns:', - 'hostname': 'fw.example.org', - 'port': '9999', - 'pathname': '/foo.bar.org', - 'search': '?type=TXT' - }, - { - 'url': 'ldap://localhost:389/ou=People,o=JNDITutorial', - 'protocol': 'ldap:', - 'hostname': 'localhost', - 'port': '389', - 'pathname': '/ou=People,o=JNDITutorial' - }, - { - 'url': 'git+https://github.com/foo/bar', - 'protocol': 'git+https:', - 'hostname': 'github.com', - 'pathname': '/foo/bar' - }, - { - 'url': 'urn:ietf:rfc:2648', - 'protocol': 'urn:', - 'pathname': 'ietf:rfc:2648' - }, - { - 'url': 'tag:joe@example.org,2001:foo/bar', - 'protocol': 'tag:', - 'pathname': 'joe@example.org,2001:foo/bar' - } ]; From 56cd1932c1471ee56fc2896afcc621556e474ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Rodr=C3=ADguez=20Baquero?= Date: Wed, 22 Feb 2017 01:41:07 -0500 Subject: [PATCH 136/164] doc: note message event listeners ref IPC channels The IPC channel is referenced with the message event too. PR-URL: https://github.com/nodejs/node/pull/11494 Reviewed-By: James M Snell Reviewed-By: Sam Roberts Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- doc/api/child_process.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 1753b1eaa8c747..1cb2410a84dcee 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -569,9 +569,9 @@ spawn('prg', [], { stdio: ['pipe', null, null, null, 'pipe'] }); *It is worth noting that when an IPC channel is established between the parent and child processes, and the child is a Node.js process, the child is launched with the IPC channel unreferenced (using `unref()`) until the -child registers an event handler for the [`process.on('disconnect')`][] event. -This allows the child to exit normally without the process being held open -by the open IPC channel.* +child registers an event handler for the [`process.on('disconnect')`][] event +or the [`process.on('message')`][] event.This allows the child to exit normally +without the process being held open by the open IPC channel.* See also: [`child_process.exec()`][] and [`child_process.fork()`][] From ff854834b65aa37a38665105044dc3823b59e2c6 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 23 Feb 2017 18:18:48 -0800 Subject: [PATCH 137/164] test: fix flaky test-vm-timeout-rethrow The intention of test case is to make sure that `timeout` property is honored and the code in context terminates and throws correct exception. However in test case, the code inside context would complete before `timeout` for windows and would sometimes fail. Updated the code so it guarantee to not complete execution until timeout is triggered. Fixes: https://github.com/nodejs/node/issues/11261 PR-URL: https://github.com/nodejs/node/pull/11530 Reviewed-By: James M Snell Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: Josh Gavant --- test/sequential/test-vm-timeout-rethrow.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/test/sequential/test-vm-timeout-rethrow.js b/test/sequential/test-vm-timeout-rethrow.js index a434e2ae3e6978..54ffee1ff976f5 100644 --- a/test/sequential/test-vm-timeout-rethrow.js +++ b/test/sequential/test-vm-timeout-rethrow.js @@ -5,15 +5,9 @@ const vm = require('vm'); const spawn = require('child_process').spawn; if (process.argv[2] === 'child') { - const code = 'let j = 0;\n' + - 'for (let i = 0; i < 1000000; i++) j += add(i, i + 1);\n' + - 'j;'; + const code = 'while(true);'; - const ctx = vm.createContext({ - add: function(x, y) { - return x + y; - } - }); + const ctx = vm.createContext(); vm.runInContext(code, ctx, { timeout: 1 }); } else { From 6bcc8417867a0643c58cb6bf49c3c9333e9d0976 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 22 Feb 2017 13:49:52 -0800 Subject: [PATCH 138/164] assert: apply minor refactoring * Remove comment referring to the CommonJS Unit Testing 1.0 spec. This module is no longer intended to comply with that spec. * Remove puzzling "THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!" comment. No doubt, it made sense at one time. * Favor `===` over `==` in two places. PR-URL: https://github.com/nodejs/node/pull/11511 Reviewed-By: Sakthipriyan Vairamani Reviewed-By: Sam Roberts Reviewed-By: Anna Henningsen Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Joyee Cheung Reviewed-By: Luigi Pinca --- lib/assert.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index baecb38d4f33d8..6a09e3f74bce00 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -1,7 +1,3 @@ -// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 -// -// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! -// // Originally from narwhal.js (http://narwhaljs.org) // Copyright (c) 2009 Thomas Robinson <280north.com> // @@ -213,7 +209,7 @@ function _deepEqual(actual, expected, strict, memos) { } function isArguments(object) { - return Object.prototype.toString.call(object) == '[object Arguments]'; + return Object.prototype.toString.call(object) === '[object Arguments]'; } function objEquiv(a, b, strict, actualVisitedObjects) { @@ -299,7 +295,7 @@ function expectedException(actual, expected) { return false; } - if (Object.prototype.toString.call(expected) == '[object RegExp]') { + if (Object.prototype.toString.call(expected) === '[object RegExp]') { return expected.test(actual); } From beda32675f79f8b5058b8e8f1823d3fee75568da Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Sun, 19 Feb 2017 22:01:31 -0800 Subject: [PATCH 139/164] src: don't assume v8::Local is using-declared PR-URL: https://github.com/nodejs/node/pull/11464 Reviewed-By: Steven R Loomis Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell --- src/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util.h b/src/util.h index b32f2b8a71ca0f..20b2ffcdba454b 100644 --- a/src/util.h +++ b/src/util.h @@ -394,7 +394,7 @@ class BufferValue : public MaybeStackBuffer { #define SPREAD_BUFFER_ARG(val, name) \ CHECK((val)->IsUint8Array()); \ - Local name = (val).As(); \ + v8::Local name = (val).As(); \ v8::ArrayBuffer::Contents name##_c = name->Buffer()->GetContents(); \ const size_t name##_offset = name->ByteOffset(); \ const size_t name##_length = name->ByteLength(); \ From fb85f5049eb828a383ba1d889597cfcd3306c653 Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Sun, 19 Feb 2017 20:03:42 -0800 Subject: [PATCH 140/164] src: clean up MaybeStackBuffer - Add IsInvalidated() method - Add capacity() method for finding out the actual capacity, not the current size, of the buffer - Make IsAllocated() work for invalidated buffers - Allow multiple calls to AllocateSufficientStorage() and Invalidate() - Assert buffer is malloc'd in Release() - Assert buffer has not been invalidated in AllocateSufficientStorage() - Add more descriptive comments describing the purpose of the methods - Add cctest for MaybeStackBuffer PR-URL: https://github.com/nodejs/node/pull/11464 Reviewed-By: Steven R Loomis Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell --- src/util.h | 63 +++++++++++++++------- test/cctest/util.cc | 124 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 19 deletions(-) diff --git a/src/util.h b/src/util.h index 20b2ffcdba454b..cf530a4da9146c 100644 --- a/src/util.h +++ b/src/util.h @@ -10,6 +10,7 @@ #include #include #include +#include #include // std::remove_reference @@ -304,29 +305,40 @@ class MaybeStackBuffer { return length_; } - // Call to make sure enough space for `storage` entries is available. - // There can only be 1 call to AllocateSufficientStorage or Invalidate - // per instance. + // Current maximum capacity of the buffer with which SetLength() can be used + // without first calling AllocateSufficientStorage(). + size_t capacity() const { + return IsAllocated() ? capacity_ : + IsInvalidated() ? 0 : kStackStorageSize; + } + + // Make sure enough space for `storage` entries is available. + // This method can be called multiple times throughout the lifetime of the + // buffer, but once this has been called Invalidate() cannot be used. + // Content of the buffer in the range [0, length()) is preserved. void AllocateSufficientStorage(size_t storage) { - if (storage <= kStackStorageSize) { - buf_ = buf_st_; - } else { - buf_ = Malloc(storage); + CHECK(!IsInvalidated()); + if (storage > capacity()) { + bool was_allocated = IsAllocated(); + T* allocated_ptr = was_allocated ? buf_ : nullptr; + buf_ = Realloc(allocated_ptr, storage); + capacity_ = storage; + if (!was_allocated && length_ > 0) + memcpy(buf_, buf_st_, length_ * sizeof(buf_[0])); } - // Remember how much was allocated to check against that in SetLength(). length_ = storage; } void SetLength(size_t length) { - // length_ stores how much memory was allocated. - CHECK_LE(length, length_); + // capacity() returns how much memory is actually available. + CHECK_LE(length, capacity()); length_ = length; } void SetLengthAndZeroTerminate(size_t length) { - // length_ stores how much memory was allocated. - CHECK_LE(length + 1, length_); + // capacity() returns how much memory is actually available. + CHECK_LE(length + 1, capacity()); SetLength(length); // T() is 0 for integer types, nullptr for pointers, etc. @@ -334,24 +346,35 @@ class MaybeStackBuffer { } // Make derefencing this object return nullptr. - // Calling this is mutually exclusive with calling - // AllocateSufficientStorage. + // This method can be called multiple times throughout the lifetime of the + // buffer, but once this has been called AllocateSufficientStorage() cannot + // be used. void Invalidate() { - CHECK_EQ(buf_, buf_st_); + CHECK(!IsAllocated()); length_ = 0; buf_ = nullptr; } - bool IsAllocated() { - return buf_ != buf_st_; + // If the buffer is stored in the heap rather than on the stack. + bool IsAllocated() const { + return !IsInvalidated() && buf_ != buf_st_; + } + + // If Invalidate() has been called. + bool IsInvalidated() const { + return buf_ == nullptr; } + // Release ownership of the malloc'd buffer. + // Note: This does not free the buffer. void Release() { + CHECK(IsAllocated()); buf_ = buf_st_; length_ = 0; + capacity_ = 0; } - MaybeStackBuffer() : length_(0), buf_(buf_st_) { + MaybeStackBuffer() : length_(0), capacity_(0), buf_(buf_st_) { // Default to a zero-length, null-terminated buffer. buf_[0] = T(); } @@ -361,12 +384,14 @@ class MaybeStackBuffer { } ~MaybeStackBuffer() { - if (buf_ != buf_st_) + if (IsAllocated()) free(buf_); } private: size_t length_; + // capacity of the malloc'ed buf_ + size_t capacity_; T* buf_; T buf_st_[kStackStorageSize]; }; diff --git a/test/cctest/util.cc b/test/cctest/util.cc index f99a46cdf5353b..a6ece3c6f4d377 100644 --- a/test/cctest/util.cc +++ b/test/cctest/util.cc @@ -132,3 +132,127 @@ TEST(UtilTest, UncheckedCalloc) { TEST_AND_FREE(UncheckedCalloc(0)); TEST_AND_FREE(UncheckedCalloc(1)); } + +template +static void MaybeStackBufferBasic() { + using node::MaybeStackBuffer; + + MaybeStackBuffer buf; + size_t old_length; + size_t old_capacity; + + /* Default constructor */ + EXPECT_EQ(0U, buf.length()); + EXPECT_FALSE(buf.IsAllocated()); + EXPECT_GT(buf.capacity(), buf.length()); + + /* SetLength() expansion */ + buf.SetLength(buf.capacity()); + EXPECT_EQ(buf.capacity(), buf.length()); + EXPECT_FALSE(buf.IsAllocated()); + + /* Means of accessing raw buffer */ + EXPECT_EQ(buf.out(), *buf); + EXPECT_EQ(&buf[0], *buf); + + /* Basic I/O */ + for (size_t i = 0; i < buf.length(); i++) + buf[i] = static_cast(i); + for (size_t i = 0; i < buf.length(); i++) + EXPECT_EQ(static_cast(i), buf[i]); + + /* SetLengthAndZeroTerminate() */ + buf.SetLengthAndZeroTerminate(buf.capacity() - 1); + EXPECT_EQ(buf.capacity() - 1, buf.length()); + for (size_t i = 0; i < buf.length(); i++) + EXPECT_EQ(static_cast(i), buf[i]); + buf.SetLength(buf.capacity()); + EXPECT_EQ(0, buf[buf.length() - 1]); + + /* Initial Realloc */ + old_length = buf.length() - 1; + old_capacity = buf.capacity(); + buf.AllocateSufficientStorage(buf.capacity() * 2); + EXPECT_EQ(buf.capacity(), buf.length()); + EXPECT_TRUE(buf.IsAllocated()); + for (size_t i = 0; i < old_length; i++) + EXPECT_EQ(static_cast(i), buf[i]); + EXPECT_EQ(0, buf[old_length]); + + /* SetLength() reduction and expansion */ + for (size_t i = 0; i < buf.length(); i++) + buf[i] = static_cast(i); + buf.SetLength(10); + for (size_t i = 0; i < buf.length(); i++) + EXPECT_EQ(static_cast(i), buf[i]); + buf.SetLength(buf.capacity()); + for (size_t i = 0; i < buf.length(); i++) + EXPECT_EQ(static_cast(i), buf[i]); + + /* Subsequent Realloc */ + old_length = buf.length(); + old_capacity = buf.capacity(); + buf.AllocateSufficientStorage(old_capacity * 1.5); + EXPECT_EQ(buf.capacity(), buf.length()); + EXPECT_EQ(static_cast(old_capacity * 1.5), buf.length()); + EXPECT_TRUE(buf.IsAllocated()); + for (size_t i = 0; i < old_length; i++) + EXPECT_EQ(static_cast(i), buf[i]); + + /* Basic I/O on Realloc'd buffer */ + for (size_t i = 0; i < buf.length(); i++) + buf[i] = static_cast(i); + for (size_t i = 0; i < buf.length(); i++) + EXPECT_EQ(static_cast(i), buf[i]); + + /* Release() */ + T* rawbuf = buf.out(); + buf.Release(); + EXPECT_EQ(0U, buf.length()); + EXPECT_FALSE(buf.IsAllocated()); + EXPECT_GT(buf.capacity(), buf.length()); + free(rawbuf); +} + +TEST(UtilTest, MaybeStackBuffer) { + using node::MaybeStackBuffer; + + MaybeStackBufferBasic(); + MaybeStackBufferBasic(); + + // Constructor with size parameter + { + MaybeStackBuffer buf(100); + EXPECT_EQ(100U, buf.length()); + EXPECT_FALSE(buf.IsAllocated()); + EXPECT_GT(buf.capacity(), buf.length()); + buf.SetLength(buf.capacity()); + EXPECT_EQ(buf.capacity(), buf.length()); + EXPECT_FALSE(buf.IsAllocated()); + for (size_t i = 0; i < buf.length(); i++) + buf[i] = static_cast(i); + for (size_t i = 0; i < buf.length(); i++) + EXPECT_EQ(static_cast(i), buf[i]); + + MaybeStackBuffer bigbuf(10000); + EXPECT_EQ(10000U, bigbuf.length()); + EXPECT_TRUE(bigbuf.IsAllocated()); + EXPECT_EQ(bigbuf.length(), bigbuf.capacity()); + for (size_t i = 0; i < bigbuf.length(); i++) + bigbuf[i] = static_cast(i); + for (size_t i = 0; i < bigbuf.length(); i++) + EXPECT_EQ(static_cast(i), bigbuf[i]); + } + + // Invalidated buffer + { + MaybeStackBuffer buf; + buf.Invalidate(); + EXPECT_TRUE(buf.IsInvalidated()); + EXPECT_FALSE(buf.IsAllocated()); + EXPECT_EQ(0U, buf.length()); + EXPECT_EQ(0U, buf.capacity()); + buf.Invalidate(); + EXPECT_TRUE(buf.IsInvalidated()); + } +} From 39b00349b8b44217ffe8244e8e2a451344b42a57 Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Sun, 19 Feb 2017 20:04:10 -0800 Subject: [PATCH 141/164] src, i18n: cleanup usage of MaybeStackBuffer - Templatize AsBuffer() and create a generic version for inclusion in the Buffer class - Use MaybeStackBuffer::storage() - If possible, avoid double conversion in ToASCII()/ToUnicode() - More descriptive assertion error in tests PR-URL: https://github.com/nodejs/node/pull/11464 Reviewed-By: Steven R Loomis Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell --- src/node_i18n.cc | 110 ++++++++++++++-------------- src/node_internals.h | 29 ++++++++ test/parallel/test-icu-transcode.js | 4 +- 3 files changed, 85 insertions(+), 58 deletions(-) diff --git a/src/node_i18n.cc b/src/node_i18n.cc index 648012a50601e3..ae14aed7c6b4c2 100644 --- a/src/node_i18n.cc +++ b/src/node_i18n.cc @@ -72,37 +72,19 @@ using v8::Value; namespace i18n { -const size_t kStorageSize = 1024; - -// TODO(jasnell): This could potentially become a member of MaybeStackBuffer -// at some point in the future. Care would need to be taken with the -// MaybeStackBuffer variant below. -MaybeLocal AsBuffer(Isolate* isolate, - MaybeStackBuffer* buf, - size_t len) { - if (buf->IsAllocated()) { - MaybeLocal ret = Buffer::New(isolate, buf->out(), len); - if (!ret.IsEmpty()) buf->Release(); +template +MaybeLocal ToBufferEndian(Environment* env, MaybeStackBuffer* buf) { + MaybeLocal ret = Buffer::New(env, buf); + if (ret.IsEmpty()) return ret; - } - return Buffer::Copy(isolate, buf->out(), len); -} -MaybeLocal AsBuffer(Isolate* isolate, - MaybeStackBuffer* buf, - size_t len) { - char* dst = reinterpret_cast(**buf); - MaybeLocal ret; - if (buf->IsAllocated()) { - ret = Buffer::New(isolate, dst, len); - if (!ret.IsEmpty()) buf->Release(); - } else { - ret = Buffer::Copy(isolate, dst, len); - } - if (!ret.IsEmpty() && IsBigEndian()) { - SPREAD_BUFFER_ARG(ret.ToLocalChecked(), buf); - SwapBytes16(buf_data, buf_length); + static_assert(sizeof(T) == 1 || sizeof(T) == 2, + "Currently only one- or two-byte buffers are supported"); + if (sizeof(T) > 1 && IsBigEndian()) { + SPREAD_BUFFER_ARG(ret.ToLocalChecked(), retbuf); + SwapBytes16(retbuf_data, retbuf_length); } + return ret; } @@ -138,14 +120,14 @@ void CopySourceBuffer(MaybeStackBuffer* dest, } } -typedef MaybeLocal (*TranscodeFunc)(Isolate* isolate, +typedef MaybeLocal (*TranscodeFunc)(Environment* env, const char* fromEncoding, const char* toEncoding, const char* source, const size_t source_length, UErrorCode* status); -MaybeLocal Transcode(Isolate* isolate, +MaybeLocal Transcode(Environment* env, const char* fromEncoding, const char* toEncoding, const char* source, @@ -162,12 +144,14 @@ MaybeLocal Transcode(Isolate* isolate, ucnv_convertEx(to.conv, from.conv, &target, target + limit, &source, source + source_length, nullptr, nullptr, nullptr, nullptr, true, true, status); - if (U_SUCCESS(*status)) - ret = AsBuffer(isolate, &result, target - &result[0]); + if (U_SUCCESS(*status)) { + result.SetLength(target - &result[0]); + ret = ToBufferEndian(env, &result); + } return ret; } -MaybeLocal TranscodeToUcs2(Isolate* isolate, +MaybeLocal TranscodeToUcs2(Environment* env, const char* fromEncoding, const char* toEncoding, const char* source, @@ -181,11 +165,11 @@ MaybeLocal TranscodeToUcs2(Isolate* isolate, ucnv_toUChars(from.conv, *destbuf, length_in_chars, source, source_length, status); if (U_SUCCESS(*status)) - ret = AsBuffer(isolate, &destbuf, length_in_chars); + ret = ToBufferEndian(env, &destbuf); return ret; } -MaybeLocal TranscodeFromUcs2(Isolate* isolate, +MaybeLocal TranscodeFromUcs2(Environment* env, const char* fromEncoding, const char* toEncoding, const char* source, @@ -200,37 +184,42 @@ MaybeLocal TranscodeFromUcs2(Isolate* isolate, MaybeStackBuffer destbuf(length_in_chars); const uint32_t len = ucnv_fromUChars(to.conv, *destbuf, length_in_chars, *sourcebuf, length_in_chars, status); - if (U_SUCCESS(*status)) - ret = AsBuffer(isolate, &destbuf, len); + if (U_SUCCESS(*status)) { + destbuf.SetLength(len); + ret = ToBufferEndian(env, &destbuf); + } return ret; } -MaybeLocal TranscodeUcs2FromUtf8(Isolate* isolate, +MaybeLocal TranscodeUcs2FromUtf8(Environment* env, const char* fromEncoding, const char* toEncoding, const char* source, const size_t source_length, UErrorCode* status) { *status = U_ZERO_ERROR; - MaybeStackBuffer destbuf; + MaybeStackBuffer destbuf; int32_t result_length; - u_strFromUTF8(*destbuf, kStorageSize, &result_length, + u_strFromUTF8(*destbuf, destbuf.capacity(), &result_length, source, source_length, status); MaybeLocal ret; if (U_SUCCESS(*status)) { - ret = AsBuffer(isolate, &destbuf, result_length * sizeof(**destbuf)); + destbuf.SetLength(result_length); + ret = ToBufferEndian(env, &destbuf); } else if (*status == U_BUFFER_OVERFLOW_ERROR) { *status = U_ZERO_ERROR; destbuf.AllocateSufficientStorage(result_length); u_strFromUTF8(*destbuf, result_length, &result_length, source, source_length, status); - if (U_SUCCESS(*status)) - ret = AsBuffer(isolate, &destbuf, result_length * sizeof(**destbuf)); + if (U_SUCCESS(*status)) { + destbuf.SetLength(result_length); + ret = ToBufferEndian(env, &destbuf); + } } return ret; } -MaybeLocal TranscodeUtf8FromUcs2(Isolate* isolate, +MaybeLocal TranscodeUtf8FromUcs2(Environment* env, const char* fromEncoding, const char* toEncoding, const char* source, @@ -241,20 +230,21 @@ MaybeLocal TranscodeUtf8FromUcs2(Isolate* isolate, const size_t length_in_chars = source_length / sizeof(UChar); int32_t result_length; MaybeStackBuffer sourcebuf; - MaybeStackBuffer destbuf; + MaybeStackBuffer destbuf; CopySourceBuffer(&sourcebuf, source, source_length, length_in_chars); - u_strToUTF8(*destbuf, kStorageSize, &result_length, + u_strToUTF8(*destbuf, destbuf.capacity(), &result_length, *sourcebuf, length_in_chars, status); if (U_SUCCESS(*status)) { - ret = AsBuffer(isolate, &destbuf, result_length); + destbuf.SetLength(result_length); + ret = ToBufferEndian(env, &destbuf); } else if (*status == U_BUFFER_OVERFLOW_ERROR) { *status = U_ZERO_ERROR; destbuf.AllocateSufficientStorage(result_length); u_strToUTF8(*destbuf, result_length, &result_length, *sourcebuf, length_in_chars, status); if (U_SUCCESS(*status)) { - ret = Buffer::New(isolate, *destbuf, result_length); - destbuf.Release(); + destbuf.SetLength(result_length); + ret = ToBufferEndian(env, &destbuf); } } return ret; @@ -320,7 +310,7 @@ void Transcode(const FunctionCallbackInfo&args) { ABORT(); } - result = tfn(isolate, EncodingName(fromEncoding), EncodingName(toEncoding), + result = tfn(env, EncodingName(fromEncoding), EncodingName(toEncoding), ts_obj_data, ts_obj_length, &status); } else { status = U_ILLEGAL_ARGUMENT_ERROR; @@ -431,7 +421,7 @@ int32_t ToUnicode(MaybeStackBuffer* buf, int32_t len = uidna_nameToUnicodeUTF8(uidna, input, length, - **buf, buf->length(), + **buf, buf->capacity(), &info, &status); @@ -440,13 +430,17 @@ int32_t ToUnicode(MaybeStackBuffer* buf, buf->AllocateSufficientStorage(len); len = uidna_nameToUnicodeUTF8(uidna, input, length, - **buf, buf->length(), + **buf, buf->capacity(), &info, &status); } - if (U_FAILURE(status)) + if (U_FAILURE(status)) { len = -1; + buf->SetLength(0); + } else { + buf->SetLength(len); + } uidna_close(uidna); return len; @@ -465,7 +459,7 @@ int32_t ToASCII(MaybeStackBuffer* buf, int32_t len = uidna_nameToASCII_UTF8(uidna, input, length, - **buf, buf->length(), + **buf, buf->capacity(), &info, &status); @@ -474,13 +468,17 @@ int32_t ToASCII(MaybeStackBuffer* buf, buf->AllocateSufficientStorage(len); len = uidna_nameToASCII_UTF8(uidna, input, length, - **buf, buf->length(), + **buf, buf->capacity(), &info, &status); } - if (U_FAILURE(status)) + if (U_FAILURE(status)) { len = -1; + buf->SetLength(0); + } else { + buf->SetLength(len); + } uidna_close(uidna); return len; diff --git a/src/node_internals.h b/src/node_internals.h index f786adcdb3121c..b68594162b8ab8 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -198,6 +198,35 @@ v8::MaybeLocal New(Environment* env, // because ArrayBufferAllocator::Free() deallocates it again with free(). // Mixing operator new and free() is undefined behavior so don't do that. v8::MaybeLocal New(Environment* env, char* data, size_t length); + +// Construct a Buffer from a MaybeStackBuffer (and also its subclasses like +// Utf8Value and TwoByteValue). +// If |buf| is invalidated, an empty MaybeLocal is returned, and nothing is +// changed. +// If |buf| contains actual data, this method takes ownership of |buf|'s +// underlying buffer. However, |buf| itself can be reused even after this call, +// but its capacity, if increased through AllocateSufficientStorage, is not +// guaranteed to stay the same. +template +static v8::MaybeLocal New(Environment* env, + MaybeStackBuffer* buf) { + v8::MaybeLocal ret; + char* src = reinterpret_cast(buf->out()); + const size_t len_in_bytes = buf->length() * sizeof(buf->out()[0]); + + if (buf->IsAllocated()) + ret = New(env, src, len_in_bytes); + else if (!buf->IsInvalidated()) + ret = Copy(env, src, len_in_bytes); + + if (ret.IsEmpty()) + return ret; + + if (buf->IsAllocated()) + buf->Release(); + + return ret; +} } // namespace Buffer } // namespace node diff --git a/test/parallel/test-icu-transcode.js b/test/parallel/test-icu-transcode.js index 0766f8c6d460d8..6fd72ce3f86689 100644 --- a/test/parallel/test-icu-transcode.js +++ b/test/parallel/test-icu-transcode.js @@ -22,9 +22,9 @@ const tests = { for (const test in tests) { const dest = buffer.transcode(orig, 'utf8', test); - assert.strictEqual(dest.length, tests[test].length); + assert.strictEqual(dest.length, tests[test].length, `utf8->${test} length`); for (let n = 0; n < tests[test].length; n++) - assert.strictEqual(dest[n], tests[test][n]); + assert.strictEqual(dest[n], tests[test][n], `utf8->${test} char ${n}`); } { From 842ac583f6df969d40f7f875471c9851f1f14930 Mon Sep 17 00:00:00 2001 From: Timothy Gu Date: Sun, 19 Feb 2017 16:51:40 -0800 Subject: [PATCH 142/164] benchmark: add url.domainTo*() PR-URL: https://github.com/nodejs/node/pull/11464 Reviewed-By: Steven R Loomis Reviewed-By: Anna Henningsen Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell --- benchmark/url/whatwg-url-idna.js | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 benchmark/url/whatwg-url-idna.js diff --git a/benchmark/url/whatwg-url-idna.js b/benchmark/url/whatwg-url-idna.js new file mode 100644 index 00000000000000..41b4c639de97b6 --- /dev/null +++ b/benchmark/url/whatwg-url-idna.js @@ -0,0 +1,47 @@ +'use strict'; +const common = require('../common.js'); +const { domainToASCII, domainToUnicode } = require('url'); + +const inputs = { + empty: { + ascii: '', + unicode: '' + }, + none: { + ascii: 'passports', + unicode: 'passports' + }, + some: { + ascii: 'Paßstraße', + unicode: 'xn--Pastrae-1vae' + }, + all: { + ascii: '他们不说中文', + unicode: 'xn--ihqwczyycu19kkg2c' + }, + nonstring: { + ascii: { toString() { return ''; } }, + unicode: { toString() { return ''; } } + } +}; + +const bench = common.createBenchmark(main, { + input: Object.keys(inputs), + to: ['ascii', 'unicode'], + n: [5e6] +}); + +function main(conf) { + const n = conf.n | 0; + const to = conf.to; + const input = inputs[conf.input][to]; + const method = to === 'ascii' ? domainToASCII : domainToUnicode; + + common.v8ForceOptimization(method, input); + + bench.start(); + for (var i = 0; i < n; i++) { + method(input); + } + bench.end(n); +} From 54e1f0c219827a8a17e0cab3fa0018e96562e9d1 Mon Sep 17 00:00:00 2001 From: Brian White Date: Wed, 22 Feb 2017 02:03:49 -0500 Subject: [PATCH 143/164] process: improve memoryUsage() performance Creating an object in JS and using a typed array to transfer values from C++ to JS is faster than creating an object and setting properties in C++. The included benchmark shows ~34% increase in performance with this change. PR-URL: https://github.com/nodejs/node/pull/11497 Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell Reviewed-By: Jeremiah Senkpiel Reviewed-By: Colin Ihrig --- benchmark/process/memoryUsage.js | 16 ++++++++++++++++ lib/internal/bootstrap_node.js | 1 + lib/internal/process.js | 15 +++++++++++++++ src/env.h | 4 ---- src/node.cc | 31 ++++++++++++++----------------- 5 files changed, 46 insertions(+), 21 deletions(-) create mode 100644 benchmark/process/memoryUsage.js diff --git a/benchmark/process/memoryUsage.js b/benchmark/process/memoryUsage.js new file mode 100644 index 00000000000000..d68ef339b4d10b --- /dev/null +++ b/benchmark/process/memoryUsage.js @@ -0,0 +1,16 @@ +'use strict'; + +var common = require('../common.js'); +var bench = common.createBenchmark(main, { + n: [1e5] +}); + +function main(conf) { + var n = +conf.n; + + bench.start(); + for (var i = 0; i < n; i++) { + process.memoryUsage(); + } + bench.end(n); +} diff --git a/lib/internal/bootstrap_node.js b/lib/internal/bootstrap_node.js index be069d67a31816..12faa6bf00afb1 100644 --- a/lib/internal/bootstrap_node.js +++ b/lib/internal/bootstrap_node.js @@ -38,6 +38,7 @@ _process.setup_hrtime(); _process.setup_cpuUsage(); + _process.setupMemoryUsage(); _process.setupConfig(NativeModule._source); NativeModule.require('internal/process/warning').setup(); NativeModule.require('internal/process/next_tick').setup(); diff --git a/lib/internal/process.js b/lib/internal/process.js index a756f0d429c10d..0f514a50e31745 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -11,6 +11,7 @@ function lazyConstants() { exports.setup_cpuUsage = setup_cpuUsage; exports.setup_hrtime = setup_hrtime; +exports.setupMemoryUsage = setupMemoryUsage; exports.setupConfig = setupConfig; exports.setupKillAndExit = setupKillAndExit; exports.setupSignalHandlers = setupSignalHandlers; @@ -98,6 +99,20 @@ function setup_hrtime() { }; } +function setupMemoryUsage() { + const memoryUsage_ = process.memoryUsage; + const memValues = new Float64Array(4); + + process.memoryUsage = function memoryUsage() { + memoryUsage_(memValues); + return { + rss: memValues[0], + heapTotal: memValues[1], + heapUsed: memValues[2], + external: memValues[3] + }; + }; +} function setupConfig(_source) { // NativeModule._source diff --git a/src/env.h b/src/env.h index 581d7e9aef3c67..b3bc79d4ce9d04 100644 --- a/src/env.h +++ b/src/env.h @@ -106,7 +106,6 @@ namespace node { V(exponent_string, "exponent") \ V(exports_string, "exports") \ V(ext_key_usage_string, "ext_key_usage") \ - V(external_string, "external") \ V(external_stream_string, "_externalStream") \ V(family_string, "family") \ V(fatal_exception_string, "_fatalException") \ @@ -117,8 +116,6 @@ namespace node { V(get_string, "get") \ 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(ignore_string, "ignore") \ @@ -186,7 +183,6 @@ namespace node { V(rename_string, "rename") \ V(replacement_string, "replacement") \ V(retry_string, "retry") \ - V(rss_string, "rss") \ V(serial_string, "serial") \ V(scopeid_string, "scopeid") \ V(sent_shutdown_string, "sentShutdown") \ diff --git a/src/node.cc b/src/node.cc index 2f470ddda0a83b..23630471d24f45 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2247,25 +2247,22 @@ void MemoryUsage(const FunctionCallbackInfo& args) { return env->ThrowUVException(err, "uv_resident_set_memory"); } + Isolate* isolate = env->isolate(); // V8 memory usage HeapStatistics v8_heap_stats; - env->isolate()->GetHeapStatistics(&v8_heap_stats); - - Local heap_total = - Number::New(env->isolate(), v8_heap_stats.total_heap_size()); - Local heap_used = - Number::New(env->isolate(), v8_heap_stats.used_heap_size()); - Local external_mem = - Number::New(env->isolate(), - env->isolate()->AdjustAmountOfExternalAllocatedMemory(0)); - - Local info = Object::New(env->isolate()); - info->Set(env->rss_string(), Number::New(env->isolate(), rss)); - info->Set(env->heap_total_string(), heap_total); - info->Set(env->heap_used_string(), heap_used); - info->Set(env->external_string(), external_mem); - - args.GetReturnValue().Set(info); + isolate->GetHeapStatistics(&v8_heap_stats); + + // Get the double array pointer from the Float64Array argument. + CHECK(args[0]->IsFloat64Array()); + Local array = args[0].As(); + CHECK_EQ(array->Length(), 4); + Local ab = array->Buffer(); + double* fields = static_cast(ab->GetContents().Data()); + + fields[0] = rss; + fields[1] = v8_heap_stats.total_heap_size(); + fields[2] = v8_heap_stats.used_heap_size(); + fields[3] = isolate->AdjustAmountOfExternalAllocatedMemory(0); } From 237db9c497b7e9a2825c38e761b937ecf652b146 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Fri, 17 Feb 2017 15:42:21 -0800 Subject: [PATCH 144/164] util: cleanup internalUtil.deprecate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There were two functions `deprecate` and `_deprecate` that were really just aliases of each other. Simplify PR-URL: https://github.com/nodejs/node/pull/11450 Reviewed-By: Michaël Zasso Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca --- lib/internal/util.js | 10 ++-------- lib/util.js | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/lib/internal/util.js b/lib/internal/util.js index 4f7e9924a94186..b4a938f9c22a89 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -10,12 +10,6 @@ const kDecoratedPrivateSymbolIndex = binding['decorated_private_symbol']; // `util` module makes it accessible without having to `require('util')` there. exports.customInspectSymbol = Symbol('util.inspect.custom'); -// All the internal deprecations have to use this function only, as this will -// prepend the prefix to the actual message. -exports.deprecate = function(fn, msg) { - return exports._deprecate(fn, msg); -}; - exports.trace = function(msg) { console.trace(`${prefix}${msg}`); }; @@ -23,11 +17,11 @@ exports.trace = function(msg) { // Mark that a method should not be used. // Returns a modified function which warns once by default. // If --no-deprecation is set, then it is a no-op. -exports._deprecate = function(fn, msg) { +exports.deprecate = function deprecate(fn, msg, code) { // Allow for deprecating things in the process of starting up. if (global.process === undefined) { return function() { - return exports._deprecate(fn, msg).apply(this, arguments); + return exports.deprecate(fn, msg, code).apply(this, arguments); }; } diff --git a/lib/util.js b/lib/util.js index 8f4ada10ce5bad..64c4c94c29a81f 100644 --- a/lib/util.js +++ b/lib/util.js @@ -131,7 +131,7 @@ exports.format = function(f) { }; -exports.deprecate = internalUtil._deprecate; +exports.deprecate = internalUtil.deprecate; var debugs = {}; From b01fd8ce3a76cb0d917e48e8cec8565341180b0e Mon Sep 17 00:00:00 2001 From: Vse Mozhet Byt Date: Mon, 13 Feb 2017 04:49:35 +0200 Subject: [PATCH 145/164] doc: fix sorting in API references PR-URL: https://github.com/nodejs/node/pull/11529 Backport-Of: https://github.com/nodejs/node/pull/11331 Reviewed-By: James M Snell Reviewed-By: Sam Roberts --- doc/api/buffer.md | 192 ++++++++++++++++++++++----------------------- doc/api/crypto.md | 32 ++++---- doc/api/dgram.md | 32 ++++---- doc/api/dns.md | 18 ++--- doc/api/domain.md | 152 +++++++++++++++++------------------ doc/api/fs.md | 36 ++++----- doc/api/http.md | 24 +++--- doc/api/process.md | 154 ++++++++++++++++++------------------ doc/api/tls.md | 100 +++++++++++------------ doc/api/url.md | 84 ++++++++++---------- doc/api/util.md | 42 +++++----- doc/api/v8.md | 78 +++++++++--------- 12 files changed, 472 insertions(+), 472 deletions(-) diff --git a/doc/api/buffer.md b/doc/api/buffer.md index ace16159a64a9f..983d2bbe453c57 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -313,32 +313,6 @@ Example: const buf = new Buffer([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); ``` -### new Buffer(buffer) - - -> Stability: 0 - Deprecated: Use [`Buffer.from(buffer)`] instead. - -* `buffer` {Buffer} An existing `Buffer` to copy data from - -Copies the passed `buffer` data onto a new `Buffer` instance. - -Example: - -```js -const buf1 = new Buffer('buffer'); -const buf2 = new Buffer(buf1); - -buf1[0] = 0x61; - -// Prints: auffer -console.log(buf1.toString()); - -// Prints: buffer -console.log(buf2.toString()); -``` - ### new Buffer(arrayBuffer[, byteOffset [, length]]) + +> Stability: 0 - Deprecated: Use [`Buffer.from(buffer)`] instead. + +* `buffer` {Buffer} An existing `Buffer` to copy data from + +Copies the passed `buffer` data onto a new `Buffer` instance. + +Example: + +```js +const buf1 = new Buffer('buffer'); +const buf2 = new Buffer(buf1); + +buf1[0] = 0x61; + +// Prints: auffer +console.log(buf1.toString()); + +// Prints: buffer +console.log(buf2.toString()); +``` + ### new Buffer(size) + +* `value` {String | Buffer | Integer} What to search for +* `byteOffset` {Integer} Where to begin searching in `buf`. **Default:** `0` +* `encoding` {String} If `value` is a string, this is its encoding. + **Default:** `'utf8'` +* Returns: {Boolean} `true` if `value` was found in `buf`, `false` otherwise + +Equivalent to [`buf.indexOf() !== -1`][`buf.indexOf()`]. + +Examples: + +```js +const buf = Buffer.from('this is a buffer'); + +// Prints: true +console.log(buf.includes('this')); + +// Prints: true +console.log(buf.includes('is')); + +// Prints: true +console.log(buf.includes(Buffer.from('a buffer'))); + +// Prints: true +// (97 is the decimal ASCII value for 'a') +console.log(buf.includes(97)); + +// Prints: false +console.log(buf.includes(Buffer.from('a buffer example'))); + +// Prints: true +console.log(buf.includes(Buffer.from('a buffer example').slice(0, 8))); + +// Prints: false +console.log(buf.includes('this', 4)); +``` + ### buf.indexOf(value[, byteOffset][, encoding]) - -* `value` {String | Buffer | Integer} What to search for -* `byteOffset` {Integer} Where to begin searching in `buf`. **Default:** `0` -* `encoding` {String} If `value` is a string, this is its encoding. - **Default:** `'utf8'` -* Returns: {Boolean} `true` if `value` was found in `buf`, `false` otherwise - -Equivalent to [`buf.indexOf() !== -1`][`buf.indexOf()`]. - -Examples: - -```js -const buf = Buffer.from('this is a buffer'); - -// Prints: true -console.log(buf.includes('this')); - -// Prints: true -console.log(buf.includes('is')); - -// Prints: true -console.log(buf.includes(Buffer.from('a buffer'))); - -// Prints: true -// (97 is the decimal ASCII value for 'a') -console.log(buf.includes(97)); - -// Prints: false -console.log(buf.includes(Buffer.from('a buffer example'))); - -// Prints: true -console.log(buf.includes(Buffer.from('a buffer example').slice(0, 8))); - -// Prints: false -console.log(buf.includes('this', 4)); -``` - ### buf.keys() + +* Returns: {Object} + +Returns a JSON representation of `buf`. [`JSON.stringify()`] implicitly calls +this function when stringifying a `Buffer` instance. + +Example: + +```js +const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); +const json = JSON.stringify(buf); + +// Prints: {"type":"Buffer","data":[1,2,3,4,5]} +console.log(json); + +const copy = JSON.parse(json, (key, value) => { + return value && value.type === 'Buffer' + ? Buffer.from(value.data) + : value; +}); + +// Prints: +console.log(copy); +``` + ### buf.toString([encoding[, start[, end]]]) - -* Returns: {Object} - -Returns a JSON representation of `buf`. [`JSON.stringify()`] implicitly calls -this function when stringifying a `Buffer` instance. - -Example: - -```js -const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); -const json = JSON.stringify(buf); - -// Prints: {"type":"Buffer","data":[1,2,3,4,5]} -console.log(json); - -const copy = JSON.parse(json, (key, value) => { - return value && value.type === 'Buffer' - ? Buffer.from(value.data) - : value; -}); - -// Prints: -console.log(copy); -``` - ### buf.values() - -Returns true if `a` is equal to `b`, without leaking timing information that -would allow an attacker to guess one of the values. This is suitable for -comparing HMAC digests or secret values like authentication cookies or -[capability urls](https://www.w3.org/TR/capability-urls/). - -`a` and `b` must both be `Buffer`s, and they must have the same length. - -**Note**: Use of `crypto.timingSafeEqual` does not guarantee that the -*surrounding* code is timing-safe. Care should be taken to ensure that the -surrounding code does not introduce timing vulnerabilities. - ### crypto.privateEncrypt(private_key, buffer) + +Returns true if `a` is equal to `b`, without leaking timing information that +would allow an attacker to guess one of the values. This is suitable for +comparing HMAC digests or secret values like authentication cookies or +[capability urls](https://www.w3.org/TR/capability-urls/). + +`a` and `b` must both be `Buffer`s, and they must have the same length. + +**Note**: Use of `crypto.timingSafeEqual` does not guarantee that the +*surrounding* code is timing-safe. Care should be taken to ensure that the +surrounding code does not introduce timing vulnerabilities. + ## Notes ### Legacy Streams API (pre Node.js v0.10) diff --git a/doc/api/dgram.md b/doc/api/dgram.md index 91db049fd1ad75..b763620f2c58e2 100644 --- a/doc/api/dgram.md +++ b/doc/api/dgram.md @@ -225,6 +225,22 @@ never have reason to call this. If `multicastInterface` is not specified, the operating system will attempt to drop membership on all valid interfaces. +### socket.ref() + + +By default, binding a socket will cause it to block the Node.js process from +exiting as long as the socket is open. The `socket.unref()` method can be used +to exclude the socket from the reference counting that keeps the Node.js +process active. The `socket.ref()` method adds the socket back to the reference +counting and restores the default behavior. + +Calling `socket.ref()` multiples times will have no additional effect. + +The `socket.ref()` method returns a reference to the socket so calls can be +chained. + ### socket.send(msg, [offset, length,] port, address[, callback]) - -By default, binding a socket will cause it to block the Node.js process from -exiting as long as the socket is open. The `socket.unref()` method can be used -to exclude the socket from the reference counting that keeps the Node.js -process active. The `socket.ref()` method adds the socket back to the reference -counting and restores the default behavior. - -Calling `socket.ref()` multiples times will have no additional effect. - -The `socket.ref()` method returns a reference to the socket so calls can be -chained. - ### socket.unref() + +Uses the DNS protocol to resolve pointer records (`PTR` records) for the +`hostname`. The `addresses` argument passed to the `callback` function will +be an array of strings containing the reply records. + ## dns.resolveSoa(hostname, callback) - -Uses the DNS protocol to resolve pointer records (`PTR` records) for the -`hostname`. The `addresses` argument passed to the `callback` function will -be an array of strings containing the reply records. - ## dns.resolveTxt(hostname, callback) -* `fd` {Integer} Integer file descriptor used by the ReadStream. - -Emitted when the ReadStream's file is opened. +Emitted when the `ReadStream`'s underlying file descriptor has been closed +using the `fs.close()` method. -### Event: 'close' +### Event: 'open' -Emitted when the `ReadStream`'s underlying file descriptor has been closed -using the `fs.close()` method. +* `fd` {Integer} Integer file descriptor used by the ReadStream. + +Emitted when the ReadStream's file is opened. ### readStream.bytesRead -* `fd` {Integer} Integer file descriptor used by the WriteStream. - -Emitted when the WriteStream's file is opened. +Emitted when the `WriteStream`'s underlying file descriptor has been closed +using the `fs.close()` method. -### Event: 'close' +### Event: 'open' -Emitted when the `WriteStream`'s underlying file descriptor has been closed -using the `fs.close()` method. +* `fd` {Integer} Integer file descriptor used by the WriteStream. + +Emitted when the WriteStream's file is opened. ### writeStream.bytesWritten + +* {net.Socket} + +The [`net.Socket`][] object associated with the connection. + +With HTTPS support, use [`request.socket.getPeerCertificate()`][] to obtain the +client's authentication details. + ### message.statusCode - -* {net.Socket} - -The [`net.Socket`][] object associated with the connection. - -With HTTPS support, use [`request.socket.getPeerCertificate()`][] to obtain the -client's authentication details. - ### message.trailers - -* {Object} - -The `process.env` property returns an object containing the user environment. -See environ(7). - -An example of this object looks like: - -```js -{ - TERM: 'xterm-256color', - SHELL: '/usr/local/bin/bash', - USER: 'maciej', - PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', - PWD: '/Users/maciej', - EDITOR: 'vim', - SHLVL: '1', - HOME: '/Users/maciej', - LOGNAME: 'maciej', - _: '/usr/local/bin/node' -} -``` - -It is possible to modify this object, but such modifications will not be -reflected outside the Node.js process. In other words, the following example -would not work: - -```console -$ node -e 'process.env.foo = "bar"' && echo $foo -``` - -While the following will: - -```js -process.env.foo = 'bar'; -console.log(process.env.foo); -``` - -Assigning a property on `process.env` will implicitly convert the value -to a string. - -Example: - -```js -process.env.test = null; -console.log(process.env.test); -// => 'null' -process.env.test = undefined; -console.log(process.env.test); -// => 'undefined' -``` - -Use `delete` to delete a property from `process.env`. - -Example: - -```js -process.env.TEST = 1; -delete process.env.TEST; -console.log(process.env.TEST); -// => undefined -``` - -On Windows operating systems, environment variables are case-insensitive. - -Example: - -```js -process.env.TEST = 1; -console.log(process.env.test); -// => 1 -``` - ## process.emitWarning(warning[, name][, ctor]) + +* {Object} + +The `process.env` property returns an object containing the user environment. +See environ(7). + +An example of this object looks like: + +```js +{ + TERM: 'xterm-256color', + SHELL: '/usr/local/bin/bash', + USER: 'maciej', + PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', + PWD: '/Users/maciej', + EDITOR: 'vim', + SHLVL: '1', + HOME: '/Users/maciej', + LOGNAME: 'maciej', + _: '/usr/local/bin/node' +} +``` + +It is possible to modify this object, but such modifications will not be +reflected outside the Node.js process. In other words, the following example +would not work: + +```console +$ node -e 'process.env.foo = "bar"' && echo $foo +``` + +While the following will: + +```js +process.env.foo = 'bar'; +console.log(process.env.foo); +``` + +Assigning a property on `process.env` will implicitly convert the value +to a string. + +Example: + +```js +process.env.test = null; +console.log(process.env.test); +// => 'null' +process.env.test = undefined; +console.log(process.env.test); +// => 'undefined' +``` + +Use `delete` to delete a property from `process.env`. + +Example: + +```js +process.env.TEST = 1; +delete process.env.TEST; +console.log(process.env.TEST); +// => undefined +``` + +On Windows operating systems, environment variables are case-insensitive. + +Example: + +```js +process.env.TEST = 1; +console.log(process.env.test); +// => 1 +``` + ## process.execArgv - -The `'tlsClientError'` event is emitted when an error occurs before a secure -connection is established. The listener callback is passed two arguments when -called: - -* `exception` {Error} The `Error` object describing the error -* `tlsSocket` {tls.TLSSocket} The `tls.TLSSocket` instance from which the - error originated. - ### Event: 'newSession' + +The `'tlsClientError'` event is emitted when an error occurs before a secure +connection is established. The listener callback is passed two arguments when +called: + +* `exception` {Error} The `Error` object describing the error +* `tlsSocket` {tls.TLSSocket} The `tls.TLSSocket` instance from which the + error originated. + ### server.addContext(hostname, context) -Returns `true` if the peer certificate was signed by one of the CAs specified -when creating the `tls.TLSSocket` instance, otherwise `false`. +Returns the reason why the peer's certificate was not been verified. This +property is set only when `tlsSocket.authorized === false`. -### tlsSocket.authorizationError +### tlsSocket.authorized -Returns the reason why the peer's certificate was not been verified. This -property is set only when `tlsSocket.authorized === false`. +Returns `true` if the peer certificate was signed by one of the CAs specified +when creating the `tls.TLSSocket` instance, otherwise `false`. ### tlsSocket.encrypted - -* `port` {number} Default value for `options.port`. -* `host` {string} Optional default value for `options.host`. -* `options` {Object} See [`tls.connect()`][]. -* `callback` {Function} See [`tls.connect()`][]. - -Same as [`tls.connect()`][] except that `port` and `host` can be provided -as arguments instead of options. - -*Note*: A port or host option, if specified, will take precedence over any port -or host argument. - -## tls.connect(path[, options][, callback]) - - -* `path` {string} Default value for `options.path`. -* `options` {Object} See [`tls.connect()`][]. -* `callback` {Function} See [`tls.connect()`][]. - -Same as [`tls.connect()`][] except that `path` can be provided -as an argument instead of an option. - -*Note*: A path option, if specified, will take precedence over the path -argument. - ## tls.connect(options[, callback]) + +* `path` {string} Default value for `options.path`. +* `options` {Object} See [`tls.connect()`][]. +* `callback` {Function} See [`tls.connect()`][]. + +Same as [`tls.connect()`][] except that `path` can be provided +as an argument instead of an option. + +*Note*: A path option, if specified, will take precedence over the path +argument. + +## tls.connect(port[, host][, options][, callback]) + + +* `port` {number} Default value for `options.port`. +* `host` {string} Optional default value for `options.host`. +* `options` {Object} See [`tls.connect()`][]. +* `callback` {Function} See [`tls.connect()`][]. + +Same as [`tls.connect()`][] except that `port` and `host` can be provided +as arguments instead of options. + +*Note*: A port or host option, if specified, will take precedence over any port +or host argument. + ## tls.createSecureContext(options) + +A Symbol that can be used to declare custom inspect functions, see +[Custom inspection functions on Objects][]. + ### util.inspect.defaultOptions -A Symbol that can be used to declare custom inspect functions, see -[Custom inspection functions on Objects][]. +> Stability: 0 - Deprecated: Use [`Object.assign()`] instead. -## Deprecated APIs +The `util._extend()` method was never intended to be used outside of internal +Node.js modules. The community found and used it anyway. -The following APIs have been deprecated and should no longer be used. Existing -applications and modules should be updated to find alternative approaches. +It is deprecated and should not be used in new code. JavaScript comes with very +similar built-in functionality through [`Object.assign()`]. ### util.debug(string) - -> Stability: 0 - Deprecated: Use [`Object.assign()`] instead. - -The `util._extend()` method was never intended to be used outside of internal -Node.js modules. The community found and used it anyway. - -It is deprecated and should not be used in new code. JavaScript comes with very -similar built-in functionality through [`Object.assign()`]. - [`Array.isArray`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray [constructor]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/constructor [semantically incompatible]: https://github.com/nodejs/node/issues/4179 diff --git a/doc/api/v8.md b/doc/api/v8.md index 8cec6bdfdf8007..528f8967e2069e 100644 --- a/doc/api/v8.md +++ b/doc/api/v8.md @@ -9,45 +9,6 @@ const v8 = require('v8'); *Note*: The APIs and implementation are subject to change at any time. -## v8.getHeapStatistics() - - -Returns an object with the following properties: - -* `total_heap_size` {number} -* `total_heap_size_executable` {number} -* `total_physical_size` {number} -* `total_available_size` {number} -* `used_heap_size` {number} -* `heap_size_limit` {number} -* `malloced_memory` {number} -* `peak_malloced_memory` {number} -* `does_zap_garbage` {number} - -`does_zap_garbage` is a 0/1 boolean, which signifies whether the `--zap_code_space` -option is enabled or not. This makes V8 overwrite heap garbage with a bit -pattern. The RSS footprint (resident memory set) gets bigger because it -continuously touches all heap pages and that makes them less likely to get -swapped out by the operating system. - -For example: - -```js -{ - total_heap_size: 7326976, - total_heap_size_executable: 4194304, - total_physical_size: 7326976, - total_available_size: 1152656, - used_heap_size: 3476208, - heap_size_limit: 1535115264, - malloced_memory: 16384, - peak_malloced_memory: 1127496, - does_zap_garbage: 0 -} -``` - ## v8.getHeapSpaceStatistics() + +Returns an object with the following properties: + +* `total_heap_size` {number} +* `total_heap_size_executable` {number} +* `total_physical_size` {number} +* `total_available_size` {number} +* `used_heap_size` {number} +* `heap_size_limit` {number} +* `malloced_memory` {number} +* `peak_malloced_memory` {number} +* `does_zap_garbage` {number} + +`does_zap_garbage` is a 0/1 boolean, which signifies whether the `--zap_code_space` +option is enabled or not. This makes V8 overwrite heap garbage with a bit +pattern. The RSS footprint (resident memory set) gets bigger because it +continuously touches all heap pages and that makes them less likely to get +swapped out by the operating system. + +For example: + +```js +{ + total_heap_size: 7326976, + total_heap_size_executable: 4194304, + total_physical_size: 7326976, + total_available_size: 1152656, + used_heap_size: 3476208, + heap_size_limit: 1535115264, + malloced_memory: 16384, + peak_malloced_memory: 1127496, + does_zap_garbage: 0 +} +``` + ## v8.setFlagsFromString(string) Returns statistics about the V8 heap spaces, i.e. the segments which make up @@ -72,6 +76,14 @@ For example: ## v8.getHeapStatistics() Returns an object with the following properties: From b1b6b8b73057dce08ff949fcaf3f43aaea5099be Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 21 Feb 2017 23:38:42 +0100 Subject: [PATCH 147/164] doc: add changelogs for buffer PR-URL: https://github.com/nodejs/node/pull/11489 Reviewed-By: Ben Noordhuis Reviewed-By: Sam Roberts Reviewed-By: Roman Reiss Reviewed-By: James M Snell Reviewed-By: Italo A. Casas --- doc/api/buffer.md | 88 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 983d2bbe453c57..9aa7d0d9cbbbda 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -138,6 +138,15 @@ extra care *must* be taken in order to avoid introducing security vulnerabilities into an application. ## Buffers and Character Encodings + `Buffer` instances are commonly used to represent sequences of encoded characters such as UTF-8, UCS2, Base64 or even Hex-encoded data. It is possible to @@ -188,6 +197,12 @@ that the server actually returned win-1252-encoded data, and using `'latin1'` encoding may incorrectly decode the characters. ## Buffers and TypedArray + `Buffer` instances are also [`Uint8Array`] instances. However, there are subtle incompatibilities with the TypedArray specification in ECMAScript 2015. @@ -298,6 +313,13 @@ It can be constructed in a variety of ways. ### new Buffer(array) > Stability: 0 - Deprecated: Use [`Buffer.from(array)`] instead. @@ -315,7 +337,18 @@ const buf = new Buffer([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]); ### new Buffer(arrayBuffer[, byteOffset [, length]]) > Stability: 0 - Deprecated: Use @@ -360,6 +393,13 @@ console.log(buf); ### new Buffer(buffer) > Stability: 0 - Deprecated: Use [`Buffer.from(buffer)`] instead. @@ -386,6 +426,13 @@ console.log(buf2.toString()); ### new Buffer(size) > Stability: 0 - Deprecated: Use [`Buffer.alloc()`] instead (also see @@ -419,6 +466,13 @@ console.log(buf); ### new Buffer(string[, encoding]) > Stability: 0 - Deprecated: @@ -508,6 +562,10 @@ A `TypeError` will be thrown if `size` is not a number. ### Class Method: Buffer.allocUnsafe(size) * `size` {Integer} The desired length of the new `Buffer` @@ -606,6 +664,14 @@ A `TypeError` will be thrown if `size` is not a number. ### Class Method: Buffer.byteLength(string[, encoding]) * `string` {String | Buffer | TypedArray | DataView | ArrayBuffer} A value to @@ -886,6 +952,10 @@ console.log(buf.toString('ascii')); ### buf.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]]) * `target` {Buffer} A `Buffer` to compare to @@ -1066,6 +1136,10 @@ console.log(buf1.equals(buf3)); ### buf.fill(value[, offset[, end]][, encoding]) * `value` {String | Buffer | Integer} The value to fill `buf` with @@ -1144,6 +1218,11 @@ console.log(buf.includes('this', 4)); ### buf.indexOf(value[, byteOffset][, encoding]) * `value` {String | Buffer | Integer} What to search for @@ -1710,6 +1789,15 @@ console.log(buf.readUIntBE(1, 6).toString(16)); ### buf.slice([start[, end]]) * `start` {Integer} Where the new `Buffer` will start. **Default:** `0` From 614742b67faed1054fc08ba8f8836cb182f2efae Mon Sep 17 00:00:00 2001 From: Josh Gavant Date: Thu, 9 Feb 2017 15:12:32 -0800 Subject: [PATCH 148/164] lib: deprecate node --debug at runtime PR-URL: https://github.com/nodejs/node/pull/11275 Backport-of: https://github.com/nodejs/node/pull/10970 Reviewed-By: James M Snell --- lib/_debug_agent.js | 4 ++++ test/parallel/test-debug-port-from-cmdline.js | 23 +++++++++++++++---- test/parallel/test-debug-signal-cluster.js | 3 ++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/lib/_debug_agent.js b/lib/_debug_agent.js index eedca7ef5843bb..c731ca374b5e87 100644 --- a/lib/_debug_agent.js +++ b/lib/_debug_agent.js @@ -1,5 +1,9 @@ 'use strict'; +process.emitWarning( + 'node --debug is deprecated. Please use node --inspect instead.', + 'DeprecationWarning'); + const assert = require('assert'); const net = require('net'); const util = require('util'); diff --git a/test/parallel/test-debug-port-from-cmdline.js b/test/parallel/test-debug-port-from-cmdline.js index 53f35877a2f382..fe22473d56625e 100644 --- a/test/parallel/test-debug-port-from-cmdline.js +++ b/test/parallel/test-debug-port-from-cmdline.js @@ -2,12 +2,19 @@ const common = require('../common'); const assert = require('assert'); const spawn = require('child_process').spawn; +const os = require('os'); const debugPort = common.PORT; const args = ['--interactive', '--debug-port=' + debugPort]; const childOptions = { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] }; const child = spawn(process.execPath, args, childOptions); +const reDeprecationWarning = new RegExp( + /^\(node:\d+\) DeprecationWarning: /.source + + /node --debug is deprecated. /.source + + /Please use node --inspect instead.$/.source +); + child.stdin.write("process.send({ msg: 'childready' });\n"); child.stderr.on('data', function(data) { @@ -37,12 +44,20 @@ function processStderrLine(line) { } function assertOutputLines() { - const expectedLines = [ - 'Starting debugger agent.', - 'Debugger listening on 127.0.0.1:' + debugPort, + // need a var so can swap the first two lines in following + // eslint-disable-next-line no-var + var expectedLines = [ + /^Starting debugger agent.$/, + reDeprecationWarning, + new RegExp(`^Debugger listening on 127.0.0.1:${debugPort}$`) ]; + if (os.platform() === 'win32') { + expectedLines[1] = expectedLines[0]; + expectedLines[0] = reDeprecationWarning; + } + assert.strictEqual(outputLines.length, expectedLines.length); for (let i = 0; i < expectedLines.length; i++) - assert(expectedLines[i].includes(outputLines[i])); + assert(expectedLines[i].test(outputLines[i])); } diff --git a/test/parallel/test-debug-signal-cluster.js b/test/parallel/test-debug-signal-cluster.js index 89b3ca456d3248..059a3c2433a72b 100644 --- a/test/parallel/test-debug-signal-cluster.js +++ b/test/parallel/test-debug-signal-cluster.js @@ -8,7 +8,8 @@ const path = require('path'); const port = common.PORT; const serverPath = path.join(common.fixturesDir, 'clustered-server', 'app.js'); -const args = [`--debug-port=${port}`, serverPath]; +// cannot use 'Flags: --no-deprecation' since it doesn't effect child +const args = [`--debug-port=${port}`, '--no-deprecation', serverPath]; const options = { stdio: ['inherit', 'inherit', 'pipe', 'ipc'] }; const child = spawn(process.execPath, args, options); From fe7a722468f9691370b5a7b643e7da288db469ab Mon Sep 17 00:00:00 2001 From: levsthings Date: Wed, 22 Feb 2017 17:17:42 +0300 Subject: [PATCH 149/164] process: fix typo in comments Fixing a typo in comments, the word 'remaining' had a typo. PR-URL: https://github.com/nodejs/node/pull/11503 Fixes: https://github.com/nodejs/node/issues/11491 Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Yuta Hiroto Reviewed-By: Benjamin Gruenbaum Reviewed-By: Luigi Pinca --- lib/internal/process.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/internal/process.js b/lib/internal/process.js index 0f514a50e31745..5334d8c58bc0a2 100644 --- a/lib/internal/process.js +++ b/lib/internal/process.js @@ -74,7 +74,9 @@ function setup_cpuUsage() { }; } - +// The 3 entries filled in by the original process.hrtime contains +// the upper/lower 32 bits of the second part of the value, +// and the remaining nanoseconds of the value. function setup_hrtime() { const _hrtime = process.hrtime; const hrValues = new Uint32Array(3); From db06c7311b87e35556ab36fb6aa89f6ba45e1580 Mon Sep 17 00:00:00 2001 From: Brian White Date: Thu, 23 Feb 2017 03:22:01 -0500 Subject: [PATCH 150/164] os: improve loadavg() performance PR-URL: https://github.com/nodejs/node/pull/11516 Reviewed-By: Jackson Tian Reviewed-By: Ben Noordhuis Reviewed-By: Jeremiah Senkpiel Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Michael Dawson --- benchmark/os/loadavg.js | 17 +++++++++++++++++ lib/os.js | 8 +++++++- src/node_os.cc | 14 +++++++------- 3 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 benchmark/os/loadavg.js diff --git a/benchmark/os/loadavg.js b/benchmark/os/loadavg.js new file mode 100644 index 00000000000000..6e3c57ed44b777 --- /dev/null +++ b/benchmark/os/loadavg.js @@ -0,0 +1,17 @@ +'use strict'; + +const common = require('../common.js'); +const loadavg = require('os').loadavg; + +const bench = common.createBenchmark(main, { + n: [5e6] +}); + +function main(conf) { + const n = +conf.n; + + bench.start(); + for (var i = 0; i < n; ++i) + loadavg(); + bench.end(n); +} diff --git a/lib/os.js b/lib/os.js index a59cc49bae8c51..6d8ebd1ca55659 100644 --- a/lib/os.js +++ b/lib/os.js @@ -1,12 +1,12 @@ 'use strict'; const binding = process.binding('os'); +const getLoadAvg = binding.getLoadAvg; const constants = process.binding('constants').os; const internalUtil = require('internal/util'); const isWindows = process.platform === 'win32'; exports.hostname = binding.getHostname; -exports.loadavg = binding.getLoadAvg; exports.uptime = binding.getUptime; exports.freemem = binding.getFreeMem; exports.totalmem = binding.getTotalMem; @@ -17,6 +17,12 @@ exports.networkInterfaces = binding.getInterfaceAddresses; exports.homedir = binding.getHomeDirectory; exports.userInfo = binding.getUserInfo; +const avgValues = new Float64Array(3); +exports.loadavg = function loadavg() { + getLoadAvg(avgValues); + return [avgValues[0], avgValues[1], avgValues[2]]; +}; + Object.defineProperty(exports, 'constants', { configurable: false, enumerable: true, diff --git a/src/node_os.cc b/src/node_os.cc index 97b1a1d08da6ed..211ac3d01dd8b2 100644 --- a/src/node_os.cc +++ b/src/node_os.cc @@ -28,8 +28,10 @@ namespace node { namespace os { using v8::Array; +using v8::ArrayBuffer; using v8::Boolean; using v8::Context; +using v8::Float64Array; using v8::FunctionCallbackInfo; using v8::Integer; using v8::Local; @@ -182,14 +184,12 @@ static void GetUptime(const FunctionCallbackInfo& args) { static void GetLoadAvg(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - double loadavg[3]; + CHECK(args[0]->IsFloat64Array()); + Local array = args[0].As(); + CHECK_EQ(array->Length(), 3); + Local ab = array->Buffer(); + double* loadavg = static_cast(ab->GetContents().Data()); uv_loadavg(loadavg); - Local loads = Array::New(env->isolate(), 3); - loads->Set(0, Number::New(env->isolate(), loadavg[0])); - loads->Set(1, Number::New(env->isolate(), loadavg[1])); - loads->Set(2, Number::New(env->isolate(), loadavg[2])); - args.GetReturnValue().Set(loads); } From 758126301ec0af32772dd0ba450d6dfd42744090 Mon Sep 17 00:00:00 2001 From: Brian White Date: Thu, 23 Feb 2017 12:45:10 -0500 Subject: [PATCH 151/164] fs: improve performance for sync stat() functions PR-URL: https://github.com/nodejs/node/pull/11522 Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell Reviewed-By: Anna Henningsen Reviewed-By: Matteo Collina Reviewed-By: Colin Ihrig --- benchmark/fs/bench-statSync.js | 32 +++++++++++---- lib/fs.js | 26 +++++++++--- src/node_file.cc | 72 +++++++++++++++++++++++++++------- 3 files changed, 102 insertions(+), 28 deletions(-) diff --git a/benchmark/fs/bench-statSync.js b/benchmark/fs/bench-statSync.js index ba1e8168b4aaf5..4bc2ecd65a3624 100644 --- a/benchmark/fs/bench-statSync.js +++ b/benchmark/fs/bench-statSync.js @@ -5,17 +5,35 @@ const fs = require('fs'); const bench = common.createBenchmark(main, { n: [1e4], - kind: ['lstatSync', 'statSync'] + kind: ['fstatSync', 'lstatSync', 'statSync'] }); function main(conf) { const n = conf.n >>> 0; - const fn = fs[conf.kind]; - - bench.start(); - for (var i = 0; i < n; i++) { - fn(__filename); + var fn; + var i; + switch (conf.kind) { + case 'statSync': + case 'lstatSync': + fn = fs[conf.kind]; + bench.start(); + for (i = 0; i < n; i++) { + fn(__filename); + } + bench.end(n); + break; + case 'fstatSync': + fn = fs.fstatSync; + const fd = fs.openSync(__filename, 'r'); + bench.start(); + for (i = 0; i < n; i++) { + fn(fd); + } + bench.end(n); + fs.closeSync(fd); + break; + default: + throw new Error('Invalid kind argument'); } - bench.end(n); } diff --git a/lib/fs.js b/lib/fs.js index b90dcf9e9487ee..c30de937c2afed 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -132,7 +132,7 @@ function isFd(path) { } // Static method to set the stats properties on a Stats object. -fs.Stats = function( +function Stats( dev, mode, nlink, @@ -161,7 +161,8 @@ fs.Stats = function( this.mtime = new Date(mtim_msec); this.ctime = new Date(ctim_msec); this.birthtime = new Date(birthtim_msec); -}; +} +fs.Stats = Stats; // Create a C++ binding to the function which creates a Stats object. binding.FSInitialize(fs.Stats); @@ -263,7 +264,7 @@ fs.existsSync = function(path) { try { handleError((path = getPathFromURL(path))); nullCheck(path); - binding.stat(pathModule._makeLong(path)); + binding.stat(pathModule._makeLong(path), statValues); return true; } catch (e) { return false; @@ -938,20 +939,33 @@ fs.stat = function(path, callback) { binding.stat(pathModule._makeLong(path), req); }; +const statValues = new Float64Array(14); +function statsFromValues() { + return new Stats(statValues[0], statValues[1], statValues[2], statValues[3], + statValues[4], statValues[5], + statValues[6] < 0 ? undefined : statValues[6], statValues[7], + statValues[8], statValues[9] < 0 ? undefined : statValues[9], + statValues[10], statValues[11], statValues[12], + statValues[13]); +} + fs.fstatSync = function(fd) { - return binding.fstat(fd); + binding.fstat(fd, statValues); + return statsFromValues(); }; fs.lstatSync = function(path) { handleError((path = getPathFromURL(path))); nullCheck(path); - return binding.lstat(pathModule._makeLong(path)); + binding.lstat(pathModule._makeLong(path), statValues); + return statsFromValues(); }; fs.statSync = function(path) { handleError((path = getPathFromURL(path))); nullCheck(path); - return binding.stat(pathModule._makeLong(path)); + binding.stat(pathModule._makeLong(path), statValues); + return statsFromValues(); }; fs.readlink = function(path, options, callback) { diff --git a/src/node_file.cc b/src/node_file.cc index 0abb88088786ae..99048b223478df 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -27,8 +27,10 @@ namespace node { using v8::Array; +using v8::ArrayBuffer; using v8::Context; using v8::EscapableHandleScope; +using v8::Float64Array; using v8::Function; using v8::FunctionCallbackInfo; using v8::FunctionTemplate; @@ -528,6 +530,37 @@ Local BuildStatsObject(Environment* env, const uv_stat_t* s) { return handle_scope.Escape(stats); } +void FillStatsArray(double* fields, const uv_stat_t* s) { + fields[0] = s->st_dev; + fields[1] = s->st_mode; + fields[2] = s->st_nlink; + fields[3] = s->st_uid; + fields[4] = s->st_gid; + fields[5] = s->st_rdev; +#if defined(__POSIX__) + fields[6] = s->st_blksize; +#else + fields[6] = -1; +#endif + fields[7] = s->st_ino; + fields[8] = s->st_size; +#if defined(__POSIX__) + fields[9] = s->st_blocks; +#else + fields[9] = -1; +#endif + // Dates. +#define X(idx, name) \ + fields[idx] = (static_cast(s->st_##name.tv_sec) * 1000) + \ + (static_cast(s->st_##name.tv_nsec / 1000000)); \ + + X(10, atim) + X(11, mtim) + X(12, ctim) + X(13, birthtim) +#undef X +} + // Used to speed up module loading. Returns the contents of the file as // a string or undefined when the file cannot be opened. The speedup // comes from not creating Error objects on failure. @@ -612,12 +645,15 @@ static void Stat(const FunctionCallbackInfo& args) { BufferValue path(env->isolate(), args[0]); ASSERT_PATH(path) - if (args[1]->IsObject()) { - ASYNC_CALL(stat, args[1], UTF8, *path) - } else { + if (args[1]->IsFloat64Array()) { + Local array = args[1].As(); + CHECK_EQ(array->Length(), 14); + Local ab = array->Buffer(); + double* fields = static_cast(ab->GetContents().Data()); SYNC_CALL(stat, *path, *path) - args.GetReturnValue().Set( - BuildStatsObject(env, static_cast(SYNC_REQ.ptr))); + FillStatsArray(fields, static_cast(SYNC_REQ.ptr)); + } else if (args[1]->IsObject()) { + ASYNC_CALL(stat, args[1], UTF8, *path) } } @@ -630,12 +666,15 @@ static void LStat(const FunctionCallbackInfo& args) { BufferValue path(env->isolate(), args[0]); ASSERT_PATH(path) - if (args[1]->IsObject()) { - ASYNC_CALL(lstat, args[1], UTF8, *path) - } else { + if (args[1]->IsFloat64Array()) { + Local array = args[1].As(); + CHECK_EQ(array->Length(), 14); + Local ab = array->Buffer(); + double* fields = static_cast(ab->GetContents().Data()); SYNC_CALL(lstat, *path, *path) - args.GetReturnValue().Set( - BuildStatsObject(env, static_cast(SYNC_REQ.ptr))); + FillStatsArray(fields, static_cast(SYNC_REQ.ptr)); + } else if (args[1]->IsObject()) { + ASYNC_CALL(lstat, args[1], UTF8, *path) } } @@ -649,12 +688,15 @@ static void FStat(const FunctionCallbackInfo& args) { int fd = args[0]->Int32Value(); - if (args[1]->IsObject()) { - ASYNC_CALL(fstat, args[1], UTF8, fd) - } else { + if (args[1]->IsFloat64Array()) { + Local array = args[1].As(); + CHECK_EQ(array->Length(), 14); + Local ab = array->Buffer(); + double* fields = static_cast(ab->GetContents().Data()); SYNC_CALL(fstat, 0, fd) - args.GetReturnValue().Set( - BuildStatsObject(env, static_cast(SYNC_REQ.ptr))); + FillStatsArray(fields, static_cast(SYNC_REQ.ptr)); + } else if (args[1]->IsObject()) { + ASYNC_CALL(fstat, args[1], UTF8, fd) } } From 4408437796fd3980be570daa972e28683c72cf52 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Fri, 24 Feb 2017 00:39:53 +0800 Subject: [PATCH 152/164] build: add rule to clean addon tests build Add a `test-addons-clean` to the Makefile to clean up files generated during testing addons. PR-URL: https://github.com/nodejs/node/pull/11519 Reviewed-By: James M Snell Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: Myles Borins --- Makefile | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 1ad56f61042ab4..410f643c91bd59 100644 --- a/Makefile +++ b/Makefile @@ -358,6 +358,11 @@ test-npm-publish: $(NODE_EXE) test-addons: test-build $(PYTHON) tools/test.py --mode=release addons +test-addons-clean: + $(RM) -rf test/addons/??_*/ + $(RM) -rf test/addons/*/build + $(RM) test/addons/.buildstamp test/addons/.docbuildstamp + test-timers: $(MAKE) --directory=tools faketime $(PYTHON) tools/test.py --mode=release timers @@ -857,10 +862,11 @@ endif .PHONY: lint cpplint jslint bench clean docopen docclean doc dist distclean \ check uninstall install install-includes install-bin all staticlib \ - dynamiclib test test-all test-addons build-addons website-upload pkg \ - blog blogclean tar binary release-only bench-http-simple bench-idle \ - bench-all bench bench-misc bench-array bench-buffer bench-net \ - bench-http bench-fs bench-tls cctest run-ci test-v8 test-v8-intl \ - test-v8-benchmarks test-v8-all v8 lint-ci bench-ci jslint-ci doc-only \ - $(TARBALL)-headers test-ci test-ci-native test-ci-js build-ci clear-stalled \ - coverage-clean coverage-build coverage-test coverage list-gtests + dynamiclib test test-all test-addons test-addons-clean build-addons \ + website-upload pkg blog blogclean tar binary release-only \ + bench-http-simple bench-idle bench-all bench bench-misc bench-array \ + bench-buffer bench-net bench-http bench-fs bench-tls cctest run-ci test-v8 \ + test-v8-intl test-v8-benchmarks test-v8-all v8 lint-ci bench-ci jslint-ci \ + doc-only $(TARBALL)-headers test-ci test-ci-native test-ci-js build-ci \ + clear-stalled coverage-clean coverage-build coverage-test coverage \ + list-gtests From 4b05ec3b95b7acca293e6eafee29bfaef7a63e50 Mon Sep 17 00:00:00 2001 From: Howard Hellyer Date: Tue, 14 Feb 2017 14:14:05 +0000 Subject: [PATCH 153/164] test: run test-setproctitle where supported Setting the process title has been enabled in libuv on AIX and z/OS. The latest level of libuv skips only skips testing of uv_set_process_title when __sun is #defined. This change simplifies the skip test so the test is only skipped when common.isSunOS is true to match libuv. Skip running the `ps` part of the test on Windows. PR-URL: https://github.com/nodejs/node/pull/11416 Reviewed-By: Colin Ihrig Reviewed-By: James M Snell Reviewed-By: Gibson Fahnestock Reviewed-By: Michael Dawson --- test/parallel/test-setproctitle.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/parallel/test-setproctitle.js b/test/parallel/test-setproctitle.js index 9dd603bfdc3327..a971d604b37d14 100644 --- a/test/parallel/test-setproctitle.js +++ b/test/parallel/test-setproctitle.js @@ -3,7 +3,7 @@ const common = require('../common'); // FIXME add sunos support -if (!(common.isFreeBSD || common.isOSX || common.isLinux)) { +if (common.isSunOS) { console.log(`1..0 # Skipped: Unsupported platform [${process.platform}]`); return; } @@ -21,6 +21,10 @@ assert.notStrictEqual(process.title, title); process.title = title; assert.strictEqual(process.title, title); +// Test setting the title but do not try to run `ps` on Windows. +if (common.isWindows) + return; + exec(`ps -p ${process.pid} -o args=`, function callback(error, stdout, stderr) { assert.ifError(error); assert.strictEqual(stderr, ''); From 128f812157effe0260818052541038e3876236cf Mon Sep 17 00:00:00 2001 From: Amelia Clarke Date: Fri, 24 Feb 2017 23:17:53 -0800 Subject: [PATCH 154/164] doc: argument types for assert methods Refs: https://github.com/nodejs/node/issues/9399 PR-URL: https://github.com/nodejs/node/pull/11548 Reviewed-By: Timothy Gu Reviewed-By: Luigi Pinca Reviewed-By: Yuta Hiroto Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- doc/api/assert.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/doc/api/assert.md b/doc/api/assert.md index b94f6ee9080ea0..8478c235e783b6 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -9,6 +9,8 @@ test invariants. +* `value` {any} +* `message` {any} An alias of [`assert.ok()`][] . @@ -41,6 +43,9 @@ changes: pr-url: https://github.com/nodejs/node/pull/5910 description: Handle non-`Uint8Array` typed arrays correctly. --> +* `actual` {any} +* `expected` {any} +* `message` {any} Tests for deep equality between the `actual` and `expected` parameters. Primitive values are compared with the equal comparison operator ( `==` ). @@ -112,6 +117,9 @@ changes: pr-url: https://github.com/nodejs/node/pull/5910 description: Handle non-`Uint8Array` typed arrays correctly. --> +* `actual` {any} +* `expected` {any} +* `message` {any} Generally identical to `assert.deepEqual()` with two exceptions. First, primitive values are compared using the strict equality operator ( `===` ). @@ -143,6 +151,9 @@ changes: pr-url: https://github.com/nodejs/node/pull/3276 description: The `error` parameter can now be an arrow function. --> +* `block` {Function} +* `error` {RegExp|Function} +* `message` {any} Asserts that the function `block` does not throw an error. See [`assert.throws()`][] for more details. @@ -198,6 +209,9 @@ assert.doesNotThrow( +* `actual` {any} +* `expected` {any} +* `message` {any} Tests shallow, coercive equality between the `actual` and `expected` parameters using the equal comparison operator ( `==` ). @@ -224,6 +238,10 @@ parameter is undefined, a default error message is assigned. +* `actual` {any} +* `expected` {any} +* `message` {any} +* `operator` {String} Throws an `AssertionError`. If `message` is falsy, the error message is set as the values of `actual` and `expected` separated by the provided `operator`. @@ -243,6 +261,7 @@ assert.fail(1, 2, 'whoops', '>'); +* `value` {any} Throws `value` if `value` is truthy. This is useful when testing the `error` argument in callbacks. @@ -264,6 +283,9 @@ assert.ifError(new Error()); +* `actual` {any} +* `expected` {any} +* `message` {any} Tests for any deep inequality. Opposite of [`assert.deepEqual()`][]. @@ -308,6 +330,9 @@ parameter is undefined, a default error message is assigned. +* `actual` {any} +* `expected` {any} +* `message` {any} Tests for deep strict inequality. Opposite of [`assert.deepStrictEqual()`][]. @@ -329,6 +354,9 @@ the `message` parameter is undefined, a default error message is assigned. +* `actual` {any} +* `expected` {any} +* `message` {any} Tests shallow, coercive inequality with the not equal comparison operator ( `!=` ). @@ -354,6 +382,9 @@ parameter is undefined, a default error message is assigned. +* `actual` {any} +* `expected` {any} +* `message` {any} Tests strict inequality as determined by the strict not equal operator ( `!==` ). @@ -379,6 +410,8 @@ If the values are strictly equal, an `AssertionError` is thrown with a +* `value` {any} +* `message` {any} Tests if `value` is truthy. It is equivalent to `assert.equal(!!value, true, message)`. @@ -406,6 +439,9 @@ assert.ok(false, 'it\'s false'); +* `actual` {any} +* `expected` {any} +* `message` {any} Tests strict equality as determined by the strict equality operator ( `===` ). @@ -434,6 +470,9 @@ changes: pr-url: https://github.com/nodejs/node/pull/3276 description: The `error` parameter can now be an arrow function. --> +* `block` {Function} +* `error` {RegExp|Function} +* `message` {any} Expects the function `block` to throw an error. From f193c6f996bce6979c017bdb94886dee9f3bc6f4 Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Fri, 24 Feb 2017 22:18:25 -0800 Subject: [PATCH 155/164] test: favor assertions over console logging Communicate about leaked globals via `AssertionError` rather than `console.log()`. PR-URL: https://github.com/nodejs/node/pull/11547 Reviewed-By: Luigi Pinca Reviewed-By: Gibson Fahnestock Reviewed-By: Timothy Gu Reviewed-By: Yuta Hiroto Reviewed-By: Anna Henningsen Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- test/common.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/common.js b/test/common.js index b451b455ea1565..270115263e6cd1 100644 --- a/test/common.js +++ b/test/common.js @@ -399,8 +399,7 @@ process.on('exit', function() { if (!exports.globalCheck) return; const leaked = leakedGlobals(); if (leaked.length > 0) { - console.error('Unknown globals: %s', leaked); - fail('Unknown global found'); + fail(`Unexpected global(s) found: ${leaked.join(', ')}`); } }); From 3b66ccf0ff7e4254db22d31755250cb4b254e27d Mon Sep 17 00:00:00 2001 From: Zach Bjornson Date: Fri, 24 Feb 2017 12:47:18 -0800 Subject: [PATCH 156/164] doc: document clientRequest.aborted Add documentation for http clientRequest.aborted. PR-URL: https://github.com/nodejs/node/pull/11544 Reviewed-By: Sam Roberts Reviewed-By: James M Snell Reviewed-By: Luigi Pinca Reviewed-By: Colin Ihrig --- doc/api/http.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/api/http.md b/doc/api/http.md index 7c224aa60ba9f1..468b20a635d3da 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -450,6 +450,14 @@ added: v0.3.8 Marks the request as aborting. Calling this will cause remaining data in the response to be dropped and the socket to be destroyed. +### request.aborted + + +If a request has been aborted, this value is the time when the request was +aborted, in milliseconds since 1 January 1970 00:00:00 UTC. + ### request.end([data][, encoding][, callback]) + +* Returns: {Array} + +Returns an array containing the unique names of the current outgoing headers. +All header names are lowercase. + +Example: + +```js +response.setHeader('Foo', 'bar'); +response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']); + +var headerNames = response.getHeaderNames(); +// headerNames === ['foo', 'set-cookie'] +``` + +### response.getHeaders() + + +* Returns: {Object} + +Returns a shallow copy of the current outgoing headers. Since a shallow copy +is used, array values may be mutated without additional calls to various +header-related http module methods. The keys of the returned object are the +header names and the values are the respective header values. All header names +are lowercase. + +Example: + +```js +response.setHeader('Foo', 'bar'); +response.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']); + +var headers = response.getHeaders(); +// headers === { foo: 'bar', 'set-cookie': ['foo=bar', 'bar=baz'] } +``` + +### response.hasHeader(name) + + +* `name` {String} +* Returns: {Boolean} + +Returns `true` if the header identified by `name` is currently set in the +outgoing headers. Note that the header name matching is case-insensitive. + +Example: + +```js +var hasContentType = response.hasHeader('content-type'); +``` + ### response.headersSent + +Enables the collection of trace event tracing information. + +### `--trace-event-categories` + + +A comma separated list of categories that should be traced when trace event +tracing is enabled using `--trace-events-enabled`. ### `--zero-fill-buffers` Enables the collection of trace event tracing information. ### `--trace-event-categories` A comma separated list of categories that should be traced when trace event @@ -389,7 +389,7 @@ options property is explicitly specified for a TLS or HTTPS client or server. ### `OPENSSL_CONF=file` Load an OpenSSL configuration file on startup. Among other uses, this can be @@ -401,7 +401,7 @@ variable is ignored. ### `SSL_CERT_DIR=dir` If `--use-openssl-ca` is enabled, this overrides and sets OpenSSL's directory @@ -413,7 +413,7 @@ OpenSSL, it may cause them to trust the same CAs as node. ### `SSL_CERT_FILE=file` If `--use-openssl-ca` is enabled, this overrides and sets OpenSSL's file diff --git a/doc/api/http.md b/doc/api/http.md index 9698479c6f6608..1b766c3eea97f4 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -950,7 +950,7 @@ var contentType = response.getHeader('content-type'); ### response.getHeaderNames() * Returns: {Array} @@ -970,7 +970,7 @@ var headerNames = response.getHeaderNames(); ### response.getHeaders() * Returns: {Object} @@ -993,7 +993,7 @@ var headers = response.getHeaders(); ### response.hasHeader(name) * `name` {String} diff --git a/doc/changelogs/CHANGELOG_V7.md b/doc/changelogs/CHANGELOG_V7.md index 3355de15e35795..b1d3310a0668e9 100644 --- a/doc/changelogs/CHANGELOG_V7.md +++ b/doc/changelogs/CHANGELOG_V7.md @@ -6,6 +6,7 @@ +7.7.0
7.6.0
7.5.0
7.4.0
@@ -27,6 +28,184 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + +## 2017-02-28, Version 7.7.0 (Current), @italoacasas + +This release contains a deprecation warning for `node --debug`. You can find more information in the +[Diagnostics Working Group Update](https://nodejs.org/en/blog/wg/diag-wg-update-2017-02/) + +### Notables changes + +* **child_process**: spawnSync() exit code now is null when the child is killed via signal (cjihrig) [#11288](https://github.com/nodejs/node/pull/11288) +* **http**: new functions to access the headers for an outgoing HTTP message (Brian White) [#11562](https://github.com/nodejs/node/pull/11562) +* **lib**: deprecate node --debug at runtime (Josh Gavant) [#11275](https://github.com/nodejs/node/pull/11275) +* **tls**: new tls.TLSSocket() supports sec ctx options (Sam Roberts) [#11005](https://github.com/nodejs/node/pull/11005) +* **url**: adding URL.prototype.toJSON support (Michaël Zasso) [#11236](https://github.com/nodejs/node/pull/11236) +* **doc**: items in the API documentation may now have changelogs (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* **crypto**: adding support for OPENSSL_CONF again (Sam Roberts) [#11006](https://github.com/nodejs/node/pull/11006) +* **src**: adding support for trace-event tracing (misterpoe) [#11106](https://github.com/nodejs/node/pull/11106) + +### Commits + +* [[`18599fc3d7`](https://github.com/nodejs/node/commit/18599fc3d7)] - doc/url: various improvements to WHATWG API (Timothy Gu) +* [[`e7d37a3f09`](https://github.com/nodejs/node/commit/e7d37a3f09)] - tools/doc: add more intrinsic and custom types (Timothy Gu) +* [[`6bcc841786`](https://github.com/nodejs/node/commit/6bcc841786)] - **assert**: apply minor refactoring (Rich Trott) [#11511](https://github.com/nodejs/node/pull/11511) +* [[`6a2f330dbd`](https://github.com/nodejs/node/commit/6a2f330dbd)] - **assert**: remove unneeded condition (Rich Trott) [#11314](https://github.com/nodejs/node/pull/11314) +* [[`0762482339`](https://github.com/nodejs/node/commit/0762482339)] - **assert**: unlock the assert API (Rich Trott) [#11304](https://github.com/nodejs/node/pull/11304) +* [[`842ac583f6`](https://github.com/nodejs/node/commit/842ac583f6)] - **benchmark**: add url.domainTo*() (Timothy Gu) [#11464](https://github.com/nodejs/node/pull/11464) +* [[`3951bd9ac1`](https://github.com/nodejs/node/commit/3951bd9ac1)] - **benchmark**: strip BOM in dgram/bind-params (Anna Henningsen) [#11479](https://github.com/nodejs/node/pull/11479) +* [[`e1573b9fb7`](https://github.com/nodejs/node/commit/e1573b9fb7)] - **benchmark**: add dgram bind(+/- params) benchmark (Vse Mozhet Byt) [#11313](https://github.com/nodejs/node/pull/11313) +* [[`48f6660d78`](https://github.com/nodejs/node/commit/48f6660d78)] - **benchmark**: fix timer display in progress output (Brian White) [#11235](https://github.com/nodejs/node/pull/11235) +* [[`5a81031fd8`](https://github.com/nodejs/node/commit/5a81031fd8)] - **benchmark**: clean up legacy url benchmarks (Joyee Cheung) +* [[`7e37628c51`](https://github.com/nodejs/node/commit/7e37628c51)] - **benchmark**: add url/url-searchparams-sort.js (Timothy Gu) +* [[`4ffad094ba`](https://github.com/nodejs/node/commit/4ffad094ba)] - **buffer**: refactor slowToString (James M Snell) [#11358](https://github.com/nodejs/node/pull/11358) +* [[`d08a8e68e8`](https://github.com/nodejs/node/commit/d08a8e68e8)] - **buffer**: avoid use of arguments (James M Snell) [#11358](https://github.com/nodejs/node/pull/11358) +* [[`4408437796`](https://github.com/nodejs/node/commit/4408437796)] - **build**: add rule to clean addon tests build (Joyee Cheung) [#11519](https://github.com/nodejs/node/pull/11519) +* [[`8d323bb91a`](https://github.com/nodejs/node/commit/8d323bb91a)] - **build**: fail on CI if leftover processes (Rich Trott) [#11269](https://github.com/nodejs/node/pull/11269) +* [[`d4a8631bd1`](https://github.com/nodejs/node/commit/d4a8631bd1)] - **build**: fix newlines in addon build output (Brian White) [#11466](https://github.com/nodejs/node/pull/11466) +* [[`bc9c381027`](https://github.com/nodejs/node/commit/bc9c381027)] - **build**: add code coverage to make (Wayne Andrews) [#10856](https://github.com/nodejs/node/pull/10856) +* [[`9c45758cdf`](https://github.com/nodejs/node/commit/9c45758cdf)] - **build**: fix building with ninja on linux (Kenan Yildirim) [#11348](https://github.com/nodejs/node/pull/11348) +* [[`86a647899f`](https://github.com/nodejs/node/commit/86a647899f)] - **build**: don't rebuild test/gc add-on unnecessarily (Ben Noordhuis) [#11311](https://github.com/nodejs/node/pull/11311) +* [[`c942e2037c`](https://github.com/nodejs/node/commit/c942e2037c)] - **child_process**: refactor internal/child_process.js (Arseniy Maximov) [#11366](https://github.com/nodejs/node/pull/11366) +* [[`0240eb99a2`](https://github.com/nodejs/node/commit/0240eb99a2)] - **child_process**: remove empty if condition (cjihrig) [#11427](https://github.com/nodejs/node/pull/11427) +* [[`60fc567952`](https://github.com/nodejs/node/commit/60fc567952)] - **child_process**: move anonymous class to top level (Jackson Tian) [#11147](https://github.com/nodejs/node/pull/11147) +* [[`58e2517fc0`](https://github.com/nodejs/node/commit/58e2517fc0)] - **child_process**: exit spawnSync with null on signal (cjihrig) [#11288](https://github.com/nodejs/node/pull/11288) +* [[`4b4bc13758`](https://github.com/nodejs/node/commit/4b4bc13758)] - **cluster**: properly handle --inspect-{brk,port} (Ali Ijaz Sheikh) [#11386](https://github.com/nodejs/node/pull/11386) +* [[`570c5e1da8`](https://github.com/nodejs/node/commit/570c5e1da8)] - **(SEMVER-MINOR)** **crypto**: support OPENSSL_CONF again (Sam Roberts) [#11006](https://github.com/nodejs/node/pull/11006) +* [[`d4000e73ed`](https://github.com/nodejs/node/commit/d4000e73ed)] - **deps**: cherry-pick 7c982e7 from V8 upstream (Jaideep Bajwa) [#11263](https://github.com/nodejs/node/pull/11263) +* [[`bd4ccc892c`](https://github.com/nodejs/node/commit/bd4ccc892c)] - **src**: add tracing controller (misterpoe) [#11106](https://github.com/nodejs/node/pull/11106) +* [[`aef67cfe39`](https://github.com/nodejs/node/commit/aef67cfe39)] - **dgram**: fix possibly deoptimizing use of arguments (Vse Mozhet Byt) [#11242](https://github.com/nodejs/node/pull/11242) +* [[`662b0c31ce`](https://github.com/nodejs/node/commit/662b0c31ce)] - **dns**: avoid use of arguments (James M Snell) [#11359](https://github.com/nodejs/node/pull/11359) +* [[`fedf26b235`](https://github.com/nodejs/node/commit/fedf26b235)] - **doc**: update V8 debugger doc to mention --inspect-brk (James Ide) [#11495](https://github.com/nodejs/node/pull/11495) +* [[`1c7f221ef5`](https://github.com/nodejs/node/commit/1c7f221ef5)] - **doc**: adding deprecations.md (Italo A. Casas) [#11621](https://github.com/nodejs/node/pull/11621) +* [[`90bdf16507`](https://github.com/nodejs/node/commit/90bdf16507)] - **doc**: link to readable and writeable stream section (Sebastian Van Sande) [#11517](https://github.com/nodejs/node/pull/11517) +* [[`3b66ccf0ff`](https://github.com/nodejs/node/commit/3b66ccf0ff)] - **doc**: document clientRequest.aborted (Zach Bjornson) [#11544](https://github.com/nodejs/node/pull/11544) +* [[`128f812157`](https://github.com/nodejs/node/commit/128f812157)] - **doc**: argument types for assert methods (Amelia Clarke) [#11548](https://github.com/nodejs/node/pull/11548) +* [[`b1b6b8b730`](https://github.com/nodejs/node/commit/b1b6b8b730)] - **doc**: add changelogs for buffer (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`597945136e`](https://github.com/nodejs/node/commit/597945136e)] - **doc**: add changelogs for v8 (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`b01fd8ce3a`](https://github.com/nodejs/node/commit/b01fd8ce3a)] - **doc**: fix sorting in API references (Vse Mozhet Byt) [#11529](https://github.com/nodejs/node/pull/11529) +* [[`56cd1932c1`](https://github.com/nodejs/node/commit/56cd1932c1)] - **doc**: note message event listeners ref IPC channels (Diego Rodríguez Baquero) [#11494](https://github.com/nodejs/node/pull/11494) +* [[`47034e12ad`](https://github.com/nodejs/node/commit/47034e12ad)] - **doc**: change broken fg(1) links to fg(1p) (Karan Thakkar) [#11504](https://github.com/nodejs/node/pull/11504) +* [[`47dc5662f3`](https://github.com/nodejs/node/commit/47dc5662f3)] - **doc**: add changelogs for zlib (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`4d122700ab`](https://github.com/nodejs/node/commit/4d122700ab)] - **doc**: add changelogs for vm (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`b868468942`](https://github.com/nodejs/node/commit/b868468942)] - **doc**: add changelogs for util (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`93e7639c12`](https://github.com/nodejs/node/commit/93e7639c12)] - **doc**: add changelogs for url (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`f7d59e5568`](https://github.com/nodejs/node/commit/f7d59e5568)] - **doc**: add changelogs for tls (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`fc53547ed4`](https://github.com/nodejs/node/commit/fc53547ed4)] - **doc**: add changelogs for stream (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`c373e07a09`](https://github.com/nodejs/node/commit/c373e07a09)] - **doc**: add changelogs for repl (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`962d27dbde`](https://github.com/nodejs/node/commit/962d27dbde)] - **doc**: add changelogs for readline (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`7c609dc30a`](https://github.com/nodejs/node/commit/7c609dc30a)] - **doc**: add changelogs for querystring (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`6285ff2275`](https://github.com/nodejs/node/commit/6285ff2275)] - **doc**: add changelogs for punycode (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`df30bc869a`](https://github.com/nodejs/node/commit/df30bc869a)] - **doc**: add changelogs for process (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`c1477b9bd3`](https://github.com/nodejs/node/commit/c1477b9bd3)] - **doc**: add changelogs for path (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`ac10a3b306`](https://github.com/nodejs/node/commit/ac10a3b306)] - **doc**: add changelogs for os (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`3183397c8a`](https://github.com/nodejs/node/commit/3183397c8a)] - **doc**: add changelogs for net (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`6cc8f19e99`](https://github.com/nodejs/node/commit/6cc8f19e99)] - **doc**: add changelogs for http (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`f0cee80de7`](https://github.com/nodejs/node/commit/f0cee80de7)] - **doc**: add changelogs for fs (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`354161d804`](https://github.com/nodejs/node/commit/354161d804)] - **doc**: add changelogs for events (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`4f936014ff`](https://github.com/nodejs/node/commit/4f936014ff)] - **doc**: add changelogs for dns (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`5bc9349d40`](https://github.com/nodejs/node/commit/5bc9349d40)] - **doc**: add changelogs for dgram (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`e23598d09f`](https://github.com/nodejs/node/commit/e23598d09f)] - **doc**: add changelogs for crypto (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`296e22adce`](https://github.com/nodejs/node/commit/296e22adce)] - **doc**: add changelogs for console (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`de83e215cb`](https://github.com/nodejs/node/commit/de83e215cb)] - **doc**: add changelogs for cluster (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`5d4e638e34`](https://github.com/nodejs/node/commit/5d4e638e34)] - **doc**: add changelogs for cli (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`ad1ad4d06d`](https://github.com/nodejs/node/commit/ad1ad4d06d)] - **doc**: add changelogs for child_process (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`42413b611b`](https://github.com/nodejs/node/commit/42413b611b)] - **doc**: add changelogs for assert (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`d3013678fb`](https://github.com/nodejs/node/commit/d3013678fb)] - **doc**: change STYLE-GUIDE to STYLE_GUIDE (Dean Coakley) [#11460](https://github.com/nodejs/node/pull/11460) +* [[`c5ff76dadf`](https://github.com/nodejs/node/commit/c5ff76dadf)] - **doc**: restrict the ES.Next features usage in tests (DavidCai) [#11452](https://github.com/nodejs/node/pull/11452) +* [[`98eb18ba3f`](https://github.com/nodejs/node/commit/98eb18ba3f)] - **doc**: add comment for net.Server's error event (QianJin2013) [#11136](https://github.com/nodejs/node/pull/11136) +* [[`20d86db9bb`](https://github.com/nodejs/node/commit/20d86db9bb)] - **doc**: add version meta for SSL_CERT_DIR/FILE (Sam Roberts) [#11007](https://github.com/nodejs/node/pull/11007) +* [[`66f9506c63`](https://github.com/nodejs/node/commit/66f9506c63)] - **doc**: improve test/README.md (Joyee Cheung) [#11237](https://github.com/nodejs/node/pull/11237) +* [[`5d12fd9a4b`](https://github.com/nodejs/node/commit/5d12fd9a4b)] - **doc**: add benchmark/README.md and fix guide (Joyee Cheung) [#11237](https://github.com/nodejs/node/pull/11237) +* [[`22a6eddc5c`](https://github.com/nodejs/node/commit/22a6eddc5c)] - **doc**: move benchmark/README.md to doc/guides (Joyee Cheung) [#11237](https://github.com/nodejs/node/pull/11237) +* [[`12cf359423`](https://github.com/nodejs/node/commit/12cf359423)] - **doc**: add comment for net.Server.listen IPv6 '::' (QianJin2013) [#11134](https://github.com/nodejs/node/pull/11134) +* [[`83fe819131`](https://github.com/nodejs/node/commit/83fe819131)] - **doc**: add STYLE_GUIDE (moved from nodejs/docs) (Gibson Fahnestock) [#11321](https://github.com/nodejs/node/pull/11321) +* [[`ef1731d972`](https://github.com/nodejs/node/commit/ef1731d972)] - **doc**: add missing function to test common doc (Rich Trott) [#11382](https://github.com/nodejs/node/pull/11382) +* [[`c3c874f514`](https://github.com/nodejs/node/commit/c3c874f514)] - **doc**: dns examples implied string args were arrays (Sam Roberts) [#11350](https://github.com/nodejs/node/pull/11350) +* [[`5f1a568ccc`](https://github.com/nodejs/node/commit/5f1a568ccc)] - **doc**: describe when stdout/err is sync (Sam Roberts) [#10884](https://github.com/nodejs/node/pull/10884) +* [[`5a2db15736`](https://github.com/nodejs/node/commit/5a2db15736)] - **doc**: add documentation for url.format(URL\[, options\]); (James M Snell) +* [[`4d7c9427c1`](https://github.com/nodejs/node/commit/4d7c9427c1)] - **doc**: synchronize + update _toc.md and all.md (Vse Mozhet Byt) [#11206](https://github.com/nodejs/node/pull/11206) +* [[`6a45265e81`](https://github.com/nodejs/node/commit/6a45265e81)] - **doc**: update code examples in domain.md (Vse Mozhet Byt) [#11110](https://github.com/nodejs/node/pull/11110) +* [[`89b66dc636`](https://github.com/nodejs/node/commit/89b66dc636)] - **doc,test**: args to `buffer.copy` can be Uint8Arrays (Anna Henningsen) [#11486](https://github.com/nodejs/node/pull/11486) +* [[`4f6a3d38c3`](https://github.com/nodejs/node/commit/4f6a3d38c3)] - **domain,events**: support non-object 'error' argument (Ben Noordhuis) [#11438](https://github.com/nodejs/node/pull/11438) +* [[`214a39294a`](https://github.com/nodejs/node/commit/214a39294a)] - **(SEMVER-MINOR)** **errors**: add internal/errors.js (James M Snell) [#11220](https://github.com/nodejs/node/pull/11220) +* [[`758126301e`](https://github.com/nodejs/node/commit/758126301e)] - **fs**: improve performance for sync stat() functions (Brian White) [#11522](https://github.com/nodejs/node/pull/11522) +* [[`3e8d43d165`](https://github.com/nodejs/node/commit/3e8d43d165)] - **http**: add new functions to OutgoingMessage (Brian White) [#11562](https://github.com/nodejs/node/pull/11562) +* [[`614742b67f`](https://github.com/nodejs/node/commit/614742b67f)] - **(SEMVER-MINOR)** **lib**: deprecate node --debug at runtime (Josh Gavant) [#11275](https://github.com/nodejs/node/pull/11275) +* [[`a710167c79`](https://github.com/nodejs/node/commit/a710167c79)] - **lib**: rename kMaxCallbacksUntilQueueIsShortened (JungMinu) [#11473](https://github.com/nodejs/node/pull/11473) +* [[`61e1af2155`](https://github.com/nodejs/node/commit/61e1af2155)] - **lib**: remove unnecessary assignments with _extend (Sakthipriyan Vairamani (thefourtheye)) [#11364](https://github.com/nodejs/node/pull/11364) +* [[`d1549bf8d9`](https://github.com/nodejs/node/commit/d1549bf8d9)] - **lib**: add constant kMaxCallbacksUntilQueueIsShortened (Daniel Bevenius) [#11199](https://github.com/nodejs/node/pull/11199) +* [[`3afe90dc9b`](https://github.com/nodejs/node/commit/3afe90dc9b)] - **net**: prefer === to == (Arseniy Maximov) [#11513](https://github.com/nodejs/node/pull/11513) +* [[`db06c7311b`](https://github.com/nodejs/node/commit/db06c7311b)] - **os**: improve loadavg() performance (Brian White) [#11516](https://github.com/nodejs/node/pull/11516) +* [[`fe7a722468`](https://github.com/nodejs/node/commit/fe7a722468)] - **process**: fix typo in comments (levsthings) [#11503](https://github.com/nodejs/node/pull/11503) +* [[`54e1f0c219`](https://github.com/nodejs/node/commit/54e1f0c219)] - **process**: improve memoryUsage() performance (Brian White) [#11497](https://github.com/nodejs/node/pull/11497) +* [[`fb85f5049e`](https://github.com/nodejs/node/commit/fb85f5049e)] - **src**: clean up MaybeStackBuffer (Timothy Gu) [#11464](https://github.com/nodejs/node/pull/11464) +* [[`beda32675f`](https://github.com/nodejs/node/commit/beda32675f)] - **src**: don't assume v8::Local is using-declared (Timothy Gu) [#11464](https://github.com/nodejs/node/pull/11464) +* [[`64a92565e0`](https://github.com/nodejs/node/commit/64a92565e0)] - **src**: update http-parser link (Daniel Bevenius) [#11477](https://github.com/nodejs/node/pull/11477) +* [[`539e83a820`](https://github.com/nodejs/node/commit/539e83a820)] - **src**: remove usage of deprecated debug API (Yang Guo) [#11437](https://github.com/nodejs/node/pull/11437) +* [[`8be6702539`](https://github.com/nodejs/node/commit/8be6702539)] - **(SEMVER-MINOR)** **src**: add SafeGetenv() to internal API (Sam Roberts) [#11006](https://github.com/nodejs/node/pull/11006) +* [[`7d47f27049`](https://github.com/nodejs/node/commit/7d47f27049)] - **src**: remove unused variable in node_crypto (cjihrig) [#11361](https://github.com/nodejs/node/pull/11361) +* [[`8a5c0fb0ff`](https://github.com/nodejs/node/commit/8a5c0fb0ff)] - **src**: remove unused typedef (Ben Noordhuis) [#11322](https://github.com/nodejs/node/pull/11322) +* [[`39b00349b8`](https://github.com/nodejs/node/commit/39b00349b8)] - **src, i18n**: cleanup usage of MaybeStackBuffer (Timothy Gu) [#11464](https://github.com/nodejs/node/pull/11464) +* [[`d0483ee47b`](https://github.com/nodejs/node/commit/d0483ee47b)] - **test**: change common.expectsError() signature (Rich Trott) [#11512](https://github.com/nodejs/node/pull/11512) +* [[`f193c6f996`](https://github.com/nodejs/node/commit/f193c6f996)] - **test**: favor assertions over console logging (Rich Trott) [#11547](https://github.com/nodejs/node/pull/11547) +* [[`4b05ec3b95`](https://github.com/nodejs/node/commit/4b05ec3b95)] - **test**: run test-setproctitle where supported (Howard Hellyer) [#11416](https://github.com/nodejs/node/pull/11416) +* [[`ff854834b6`](https://github.com/nodejs/node/commit/ff854834b6)] - **test**: fix flaky test-vm-timeout-rethrow (Kunal Pathak) [#11530](https://github.com/nodejs/node/pull/11530) +* [[`d7fd694cee`](https://github.com/nodejs/node/commit/d7fd694cee)] - **test**: remove redundant additional url tests (Joyee Cheung) [#11439](https://github.com/nodejs/node/pull/11439) +* [[`e92ddd46bb`](https://github.com/nodejs/node/commit/e92ddd46bb)] - **test**: synchronize WPT url test data (Joyee Cheung) [#11439](https://github.com/nodejs/node/pull/11439) +* [[`4109e0edc4`](https://github.com/nodejs/node/commit/4109e0edc4)] - **test**: remove WHATWG URL test data file extension (Joyee Cheung) [#11439](https://github.com/nodejs/node/pull/11439) +* [[`ecb3a7e933`](https://github.com/nodejs/node/commit/ecb3a7e933)] - **(SEMVER-MINOR)** **test**: make tls-socket-default-options tests run (Sam Roberts) [#11005](https://github.com/nodejs/node/pull/11005) +* [[`f5b4849208`](https://github.com/nodejs/node/commit/f5b4849208)] - **test**: test bottom-up merge sort in URLSearchParams (Daijiro Wachi) [#11399](https://github.com/nodejs/node/pull/11399) +* [[`ff927b2cf8`](https://github.com/nodejs/node/commit/ff927b2cf8)] - **test**: add cases for unescape & unescapeBuffer (Daijiro Wachi) [#11326](https://github.com/nodejs/node/pull/11326) +* [[`ea29d4852a`](https://github.com/nodejs/node/commit/ea29d4852a)] - **test**: use expectsError in test-debug-agent.js (Arseniy Maximov) [#11410](https://github.com/nodejs/node/pull/11410) +* [[`8e455a9093`](https://github.com/nodejs/node/commit/8e455a9093)] - **test**: add test for URLSearchParams inspection (Daijiro Wachi) [#11428](https://github.com/nodejs/node/pull/11428) +* [[`ae9b891a39`](https://github.com/nodejs/node/commit/ae9b891a39)] - **test**: use expectsError in require-invalid-package (Rich Trott) [#11409](https://github.com/nodejs/node/pull/11409) +* [[`91fac08c3b`](https://github.com/nodejs/node/commit/91fac08c3b)] - **test**: use common.expectsError() (Rich Trott) [#11408](https://github.com/nodejs/node/pull/11408) +* [[`46084e3270`](https://github.com/nodejs/node/commit/46084e3270)] - **test**: refactor common.expectsError() (Rich Trott) [#11381](https://github.com/nodejs/node/pull/11381) +* [[`8fdb6c24f9`](https://github.com/nodejs/node/commit/8fdb6c24f9)] - **test**: throw check in test-zlib-write-after-close (Jason Wilson) [#11482](https://github.com/nodejs/node/pull/11482) +* [[`b395ed9407`](https://github.com/nodejs/node/commit/b395ed9407)] - **test**: increase coverage of vm (DavidCai) [#11377](https://github.com/nodejs/node/pull/11377) +* [[`000b2a14c1`](https://github.com/nodejs/node/commit/000b2a14c1)] - **test**: add support for --gtest_filter (Daniel Bevenius) [#11474](https://github.com/nodejs/node/pull/11474) +* [[`34220b75e2`](https://github.com/nodejs/node/commit/34220b75e2)] - **test**: add regex check to test-module-loading (Tarang Hirani) [#11413](https://github.com/nodejs/node/pull/11413) +* [[`4509d84095`](https://github.com/nodejs/node/commit/4509d84095)] - **test**: improve coverage in test-crypto.dh (Eric Christie) [#11253](https://github.com/nodejs/node/pull/11253) +* [[`da10e2649d`](https://github.com/nodejs/node/commit/da10e2649d)] - **test**: add error checking in callback (Rich Trott) [#11446](https://github.com/nodejs/node/pull/11446) +* [[`7b8087630f`](https://github.com/nodejs/node/commit/7b8087630f)] - **test**: refactor test-http-response-splitting (Arseniy Maximov) [#11429](https://github.com/nodejs/node/pull/11429) +* [[`c37e2b7690`](https://github.com/nodejs/node/commit/c37e2b7690)] - **test**: add test cases for path (Yuta Hiroto) [#11453](https://github.com/nodejs/node/pull/11453) +* [[`a523482cca`](https://github.com/nodejs/node/commit/a523482cca)] - **test**: enhance test-common.js (Rich Trott) [#11433](https://github.com/nodejs/node/pull/11433) +* [[`1d86a9f5eb`](https://github.com/nodejs/node/commit/1d86a9f5eb)] - **test**: fix over-dependence on native promise impl (Ali Ijaz Sheikh) [#11437](https://github.com/nodejs/node/pull/11437) +* [[`b457f38e68`](https://github.com/nodejs/node/commit/b457f38e68)] - **test**: add coverage for utf8CheckIncomplete() (xiaoyu) [#11419](https://github.com/nodejs/node/pull/11419) +* [[`ca1bae6f3e`](https://github.com/nodejs/node/commit/ca1bae6f3e)] - **test**: remove unused args and comparison fix (Alexander) [#11396](https://github.com/nodejs/node/pull/11396) +* [[`8ee236f85a`](https://github.com/nodejs/node/commit/8ee236f85a)] - **test**: improve crypto coverage (樋口 彰) [#11279](https://github.com/nodejs/node/pull/11279) +* [[`add762550c`](https://github.com/nodejs/node/commit/add762550c)] - **test**: consolidate buffer.read() in a file (larissayvette) [#11297](https://github.com/nodejs/node/pull/11297) +* [[`e416967244`](https://github.com/nodejs/node/commit/e416967244)] - **test**: cases to querystring related to empty string (Daijiro Wachi) [#11329](https://github.com/nodejs/node/pull/11329) +* [[`5723087cdd`](https://github.com/nodejs/node/commit/5723087cdd)] - **test**: refactor test-dgram-membership (Rich Trott) [#11388](https://github.com/nodejs/node/pull/11388) +* [[`aea0d501d7`](https://github.com/nodejs/node/commit/aea0d501d7)] - **test**: improve message in net-connect-local-error (Rich Trott) [#11393](https://github.com/nodejs/node/pull/11393) +* [[`82882f4e90`](https://github.com/nodejs/node/commit/82882f4e90)] - **test**: cover dgram socket close during bind case (cjihrig) [#11383](https://github.com/nodejs/node/pull/11383) +* [[`f495389d67`](https://github.com/nodejs/node/commit/f495389d67)] - **test**: refactor test-tls-cert-chains-in-ca (Rich Trott) [#11367](https://github.com/nodejs/node/pull/11367) +* [[`348f2ef59f`](https://github.com/nodejs/node/commit/348f2ef59f)] - **test**: improve crypto coverage (Akito Ito) [#11280](https://github.com/nodejs/node/pull/11280) +* [[`e7978f04a4`](https://github.com/nodejs/node/commit/e7978f04a4)] - **test**: cover dgram socket close during cluster bind (cjihrig) [#11292](https://github.com/nodejs/node/pull/11292) +* [[`66081d1ddb`](https://github.com/nodejs/node/commit/66081d1ddb)] - **test**: increase coverage of buffer (DavidCai) [#11312](https://github.com/nodejs/node/pull/11312) +* [[`7aaa960f4c`](https://github.com/nodejs/node/commit/7aaa960f4c)] - **test, url**: synchronize WPT url tests (Joyee Cheung) +* [[`506a1cb03f`](https://github.com/nodejs/node/commit/506a1cb03f)] - **timer,domain**: maintain order of timer callbacks (John Barboza) [#10522](https://github.com/nodejs/node/pull/10522) +* [[`4e327708a9`](https://github.com/nodejs/node/commit/4e327708a9)] - **(SEMVER-MINOR)** **tls**: new tls.TLSSocket() supports sec ctx options (Sam Roberts) [#11005](https://github.com/nodejs/node/pull/11005) +* [[`f37ab7968e`](https://github.com/nodejs/node/commit/f37ab7968e)] - **tls**: do not crash on STARTTLS when OCSP requested (Fedor Indutny) [#10706](https://github.com/nodejs/node/pull/10706) +* [[`5f94ff6231`](https://github.com/nodejs/node/commit/5f94ff6231)] - **tls**: avoid potentially deoptimizing use of arguments (James M Snell) [#11357](https://github.com/nodejs/node/pull/11357) +* [[`0934a27c75`](https://github.com/nodejs/node/commit/0934a27c75)] - **tools**: enable unicode-bom ESLint rule (Anna Henningsen) [#11479](https://github.com/nodejs/node/pull/11479) +* [[`eea2eb9111`](https://github.com/nodejs/node/commit/eea2eb9111)] - **tools**: enable one-var-declaration-per-line ESLint rule (Michaël Zasso) [#11462](https://github.com/nodejs/node/pull/11462) +* [[`5b5dca9076`](https://github.com/nodejs/node/commit/5b5dca9076)] - **tools**: suggest python2 command in configure (Roman Reiss) [#11375](https://github.com/nodejs/node/pull/11375) +* [[`d9d541d564`](https://github.com/nodejs/node/commit/d9d541d564)] - **tools,doc**: enable changelogs for items (Anna Henningsen) [#11489](https://github.com/nodejs/node/pull/11489) +* [[`4ee9220565`](https://github.com/nodejs/node/commit/4ee9220565)] - **tty**: avoid oob warning in TTYWrap::GetWindowSize() (Dmitry Tsvettsikh) [#11454](https://github.com/nodejs/node/pull/11454) +* [[`5f10827248`](https://github.com/nodejs/node/commit/5f10827248)] - **url**: fix handling of ? in URLSearchParams creation (Timothy Gu) [#11372](https://github.com/nodejs/node/pull/11372) +* [[`72da362d6e`](https://github.com/nodejs/node/commit/72da362d6e)] - **url**: fix file state clarification in binding (Daijiro Wachi) [#11123](https://github.com/nodejs/node/pull/11123) +* [[`4366ab539f`](https://github.com/nodejs/node/commit/4366ab539f)] - **url**: implement URL.prototype.toJSON (Michaël Zasso) [#11236](https://github.com/nodejs/node/pull/11236) +* [[`8dbd562590`](https://github.com/nodejs/node/commit/8dbd562590)] - **url**: fix surrogate handling in encodeAuth() (Timothy Gu) +* [[`c25c16cc1b`](https://github.com/nodejs/node/commit/c25c16cc1b)] - **url**: add urlSearchParams.sort() (Timothy Gu) +* [[`d8cb65aa6e`](https://github.com/nodejs/node/commit/d8cb65aa6e)] - **url, test**: synchronize WPT url tests for file URL (Daijiro Wachi) [#11123](https://github.com/nodejs/node/pull/11123) +* [[`237db9c497`](https://github.com/nodejs/node/commit/237db9c497)] - **util**: cleanup internalUtil.deprecate (James M Snell) [#11450](https://github.com/nodejs/node/pull/11450) +* [[`95bee8f202`](https://github.com/nodejs/node/commit/95bee8f202)] - **util**: eliminate unnecessary exports (James M Snell) [#11451](https://github.com/nodejs/node/pull/11451) +* [[`3bdac54e67`](https://github.com/nodejs/node/commit/3bdac54e67)] - **util**: use ES2015+ Object.is to check negative zero (Shinnosuke Watanabe) [#11332](https://github.com/nodejs/node/pull/11332) +* [[`3d133ebd3d`](https://github.com/nodejs/node/commit/3d133ebd3d)] - **util, debugger**: remove internalUtil.error (James M Snell) [#11448](https://github.com/nodejs/node/pull/11448) +* [[`f55c628b2a`](https://github.com/nodejs/node/commit/f55c628b2a)] - **vm**: refactor vm module (James M Snell) [#11392](https://github.com/nodejs/node/pull/11392) + ## 2017-02-21, Version 7.6.0 (Current), @italoacasas diff --git a/src/node_version.h b/src/node_version.h index 7175e5824dd26d..48c5a3b2b807bf 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -2,10 +2,10 @@ #define SRC_NODE_VERSION_H_ #define NODE_MAJOR_VERSION 7 -#define NODE_MINOR_VERSION 6 -#define NODE_PATCH_VERSION 1 +#define NODE_MINOR_VERSION 7 +#define NODE_PATCH_VERSION 0 -#define NODE_VERSION_IS_RELEASE 0 +#define NODE_VERSION_IS_RELEASE 1 #ifndef NODE_STRINGIFY #define NODE_STRINGIFY(n) NODE_STRINGIFY_HELPER(n)