From 0a1cc9e7a2cbad34b0f4a1600a7615a7a50c3e50 Mon Sep 17 00:00:00 2001 From: Evan Lucas Date: Fri, 9 Dec 2016 17:13:14 -0600 Subject: [PATCH 01/14] crypto: add randomFill and randomFillSync crypto.randomFill and crypto.randomFillSync are similar to crypto.randomBytes, but allow passing in a buffer as the first argument. This allows us to reuse buffers to prevent having to create a new one on every call. PR-URL: https://github.com/nodejs/node/pull/10209 Reviewed-By: Sam Roberts Reviewed-By: James M Snell Reviewed-By: Ben Noordhuis Reviewed-By: Anna Henningsen --- doc/api/crypto.md | 62 +++++++++ lib/crypto.js | 90 +++++++++++++ src/node_crypto.cc | 111 +++++++++++++-- test/parallel/test-crypto-random.js | 202 ++++++++++++++++++++++++++++ test/parallel/test-domain-crypto.js | 2 + 5 files changed, 453 insertions(+), 14 deletions(-) diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 4a7488ba6f2f70..b5a3dbf69cf3e8 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1588,6 +1588,66 @@ This should normally never take longer than a few milliseconds. The only time when generating the random bytes may conceivably block for a longer period of time is right after boot, when the whole system is still low on entropy. +### crypto.randomFillSync(buf[, offset][, size]) + + +* `buf` {Buffer|Uint8Array} Must be supplied. +* `offset` {number} Defaults to `0`. +* `size` {number} Defaults to `buf.length - offset`. + +Synchronous version of [`crypto.randomFill()`][]. + +Returns `buf` + +```js +const buf = Buffer.alloc(10); +console.log(crypto.randomFillSync(buf).toString('hex')); + +crypto.randomFillSync(buf, 5); +console.log(buf.toString('hex')); + +// The above is equivalent to the following: +crypto.randomFillSync(buf, 5, 5); +console.log(buf.toString('hex')); +``` + +### crypto.randomFill(buf[, offset][, size], callback) + + +* `buf` {Buffer|Uint8Array} Must be supplied. +* `offset` {number} Defaults to `0`. +* `size` {number} Defaults to `buf.length - offset`. +* `callback` {Function} `function(err, buf) {}`. + +This function is similar to [`crypto.randomBytes()`][] but requires the first +argument to be a [`Buffer`][] that will be filled. It also +requires that a callback is passed in. + +If the `callback` function is not provided, an error will be thrown. + +```js +const buf = Buffer.alloc(10); +crypto.randomFill(buf, (err, buf) => { + if (err) throw err; + console.log(buf.toString('hex')); +}); + +crypto.randomFill(buf, 5, (err, buf) => { + if (err) throw err; + console.log(buf.toString('hex')); +}); + +// The above is equivalent to the following: +crypto.randomFill(buf, 5, 5, (err, buf) => { + if (err) throw err; + console.log(buf.toString('hex')); +}); +``` + ### crypto.setEngine(engine[, flags]) -* `buf` {Buffer|Uint8Array} Must be supplied. +* `buffer` {Buffer|Uint8Array} Must be supplied. * `offset` {number} Defaults to `0`. -* `size` {number} Defaults to `buf.length - offset`. +* `size` {number} Defaults to `buffer.length - offset`. Synchronous version of [`crypto.randomFill()`][]. -Returns `buf` +Returns `buffer` ```js const buf = Buffer.alloc(10); @@ -1613,14 +1613,14 @@ crypto.randomFillSync(buf, 5, 5); console.log(buf.toString('hex')); ``` -### crypto.randomFill(buf[, offset][, size], callback) +### crypto.randomFill(buffer[, offset][, size], callback) -* `buf` {Buffer|Uint8Array} Must be supplied. +* `buffer` {Buffer|Uint8Array} Must be supplied. * `offset` {number} Defaults to `0`. -* `size` {number} Defaults to `buf.length - offset`. +* `size` {number} Defaults to `buffer.length - offset`. * `callback` {Function} `function(err, buf) {}`. This function is similar to [`crypto.randomBytes()`][] but requires the first @@ -2067,7 +2067,7 @@ the `crypto`, `tls`, and `https` modules and are generally specific to OpenSSL. [`crypto.getHashes()`]: #crypto_crypto_gethashes [`crypto.pbkdf2()`]: #crypto_crypto_pbkdf2_password_salt_iterations_keylen_digest_callback [`crypto.randomBytes()`]: #crypto_crypto_randombytes_size_callback -[`crypto.randomFill()`]: #crypto_crypto_randombytesbuffer_buf_size_offset_cb +[`crypto.randomFill()`]: #crypto_crypto_randomfill_buffer_offset_size_callback [`decipher.final()`]: #crypto_decipher_final_output_encoding [`decipher.update()`]: #crypto_decipher_update_data_input_encoding_output_encoding [`diffieHellman.setPublicKey()`]: #crypto_diffiehellman_setpublickey_public_key_encoding From 97c290dd380cab939962b07a2a3651173c8cd610 Mon Sep 17 00:00:00 2001 From: Sam Roberts Date: Mon, 5 Jun 2017 12:35:43 -0700 Subject: [PATCH 03/14] lib: return this from net.Socket.end() PR-URL: https://github.com/nodejs/node/pull/13481 Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: Refael Ackermann Reviewed-By: Evan Lucas Reviewed-By: Brian White --- doc/api/net.md | 2 ++ lib/net.js | 2 ++ test/parallel/test-socket-write-after-fin.js | 5 +++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/api/net.md b/doc/api/net.md index 5c9c3dea6051b4..35e7abcee85cad 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -575,6 +575,8 @@ server will still send some data. If `data` is specified, it is equivalent to calling `socket.write(data, encoding)` followed by `socket.end()`. +Returns `socket`. + ### socket.localAddress +* Returns {net.Server} + Asynchronously get the number of concurrent connections on the server. Works when sockets were sent to forks. diff --git a/lib/net.js b/lib/net.js index 9cd648953eb25b..c819ac1516ebef 100644 --- a/lib/net.js +++ b/lib/net.js @@ -1487,7 +1487,8 @@ Server.prototype.getConnections = function(cb) { } if (!this._usingSlaves) { - return end(null, this._connections); + end(null, this._connections); + return this; } // Poll slaves @@ -1507,6 +1508,8 @@ Server.prototype.getConnections = function(cb) { this._slaves.forEach(function(slave) { slave.getConnections(oncount); }); + + return this; }; diff --git a/test/parallel/test-net-pingpong.js b/test/parallel/test-net-pingpong.js index b2f756c1ba7147..1bcf5992124342 100644 --- a/test/parallel/test-net-pingpong.js +++ b/test/parallel/test-net-pingpong.js @@ -16,10 +16,13 @@ function pingPongTest(port, host) { function onSocket(socket) { assert.strictEqual(socket.server, server); - server.getConnections(common.mustCall(function(err, connections) { - assert.ifError(err); - assert.strictEqual(connections, 1); - })); + assert.strictEqual( + server, + server.getConnections(common.mustCall(function(err, connections) { + assert.ifError(err); + assert.strictEqual(connections, 1); + })) + ); socket.setNoDelay(); socket.timeout = 0; From e48d7df41fbb542703a260302b6cf44054b364fd Mon Sep 17 00:00:00 2001 From: Alexey Orlenko Date: Fri, 21 Jul 2017 11:30:07 +0300 Subject: [PATCH 05/14] repl: improve require() autocompletion Currently REPL supports autocompletion for core modules and those found in node_modules. This commit adds tab completion for modules relative to the current directory. PR-URL: https://github.com/nodejs/node/pull/14409 Reviewed-By: Refael Ackermann Reviewed-By: Timothy Gu Reviewed-By: Khaidi Chu Reviewed-By: James M Snell --- lib/repl.js | 13 ++++++- test/parallel/test-repl-tab-complete.js | 50 +++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/lib/repl.js b/lib/repl.js index f841b3e3eff34b..2287af180899ce 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -870,7 +870,18 @@ function complete(line, callback) { filter = match[1]; var dir, files, f, name, base, ext, abs, subfiles, s; group = []; - var paths = module.paths.concat(Module.globalPaths); + let paths = []; + + if (completeOn === '.') { + group = ['./', '../']; + } else if (completeOn === '..') { + group = ['../']; + } else if (/^\.\.?\//.test(completeOn)) { + paths = [process.cwd()]; + } else { + paths = module.paths.concat(Module.globalPaths); + } + for (i = 0; i < paths.length; i++) { dir = path.resolve(paths[i], subdir); try { diff --git a/test/parallel/test-repl-tab-complete.js b/test/parallel/test-repl-tab-complete.js index 1179259c79d026..0d05196869cda9 100644 --- a/test/parallel/test-repl-tab-complete.js +++ b/test/parallel/test-repl-tab-complete.js @@ -212,6 +212,56 @@ testMe.complete('require(\'n', common.mustCall(function(error, data) { })); } +// Test tab completion for require() relative to the current directory +{ + putIn.run(['.clear']); + + const cwd = process.cwd(); + process.chdir(__dirname); + + ['require(\'.', 'require(".'].forEach((input) => { + testMe.complete(input, common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[1], '.'); + assert.strictEqual(data[0].length, 2); + assert.ok(data[0].includes('./')); + assert.ok(data[0].includes('../')); + })); + }); + + ['require(\'..', 'require("..'].forEach((input) => { + testMe.complete(input, common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.deepStrictEqual(data, [['../'], '..']); + })); + }); + + ['./', './test-'].forEach((path) => { + [`require('${path}`, `require("${path}`].forEach((input) => { + testMe.complete(input, common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[1], path); + assert.ok(data[0].includes('./test-repl-tab-complete')); + })); + }); + }); + + ['../parallel/', '../parallel/test-'].forEach((path) => { + [`require('${path}`, `require("${path}`].forEach((input) => { + testMe.complete(input, common.mustCall((err, data) => { + assert.strictEqual(err, null); + assert.strictEqual(data.length, 2); + assert.strictEqual(data[1], path); + assert.ok(data[0].includes('../parallel/test-repl-tab-complete')); + })); + }); + }); + + process.chdir(cwd); +} + // Make sure tab completion works on context properties putIn.run(['.clear']); From 17fb9facbec427d0ffdaa94adaaa288be0a43c99 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 26 Apr 2017 12:42:18 -0700 Subject: [PATCH 06/14] console: add console.count() and console.clear() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both are simple utility functions defined by the WHATWG console spec (https://console.spec.whatwg.org/). PR-URL: https://github.com/nodejs/node/pull/12678 Ref: https://github.com/nodejs/node/issues/12675 Reviewed-By: Anna Henningsen Reviewed-By: Benjamin Gruenbaum Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: Daijiro Wachi Reviewed-By: Timothy Gu Reviewed-By: Tobias Nießen --- doc/api/console.md | 70 +++++++++++++++++++++++++++++ lib/console.js | 39 ++++++++++++++++ test/parallel/test-console-clear.js | 22 +++++++++ test/parallel/test-console-count.js | 63 ++++++++++++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 test/parallel/test-console-clear.js create mode 100644 test/parallel/test-console-count.js diff --git a/doc/api/console.md b/doc/api/console.md index cc7e8b0022c25b..6d8050ab1152a0 100644 --- a/doc/api/console.md +++ b/doc/api/console.md @@ -155,6 +155,76 @@ console.assert(false, 'this message will print, but no error thrown'); console.log('this will also print'); ``` +### console.clear() + + +When `stdout` is a TTY, calling `console.clear()` will attempt to clear the +TTY. When `stdout` is not a TTY, this method does nothing. + +*Note*: The specific operation of `console.clear()` can vary across operating +systems and terminal types. For most Linux operating systems, `console.clear()` +operates similarly to the `clear` shell command. On Windows, `console.clear()` +will clear only the output in the current terminal viewport for the Node.js +binary. + +### console.count([label]) + + +* `label` {string} The display label for the counter. Defaults to `'default'`. + +Maintains an internal counter specific to `label` and outputs to `stdout` the +number of times `console.count()` has been called with the given `label`. + + +```js +> console.count() +default: 1 +undefined +> console.count('default') +default: 2 +undefined +> console.count('abc') +abc: 1 +undefined +> console.count('xyz') +xyz: 1 +undefined +> console.count('abc') +abc: 2 +undefined +> console.count() +default: 3 +undefined +> +``` + +### console.countReset([label = 'default']) + + +* `label` {string} The display label for the counter. Defaults to `'default'`. + +Resets the internal counter specific to `label`. + + +```js +> console.count('abc'); +abc: 1 +undefined +> console.countReset('abc'); +undefined +> console.count('abc'); +abc: 1 +undefined +> +``` + + ### console.dir(obj[, options]) + +* `multicastInterface` {String} + +*Note: All references to scope in this section are refering to +[IPv6 Zone Indices][], which are defined by [RFC 4007][]. In string form, an IP +with a scope index is written as `'IP%scope'` where scope is an interface name or +interface number.* + +Sets the default outgoing multicast interface of the socket to a chosen +interface or back to system interface selection. The `multicastInterface` must +be a valid string representation of an IP from the socket's family. + +For IPv4 sockets, this should be the IP configured for the desired physical +interface. All packets sent to multicast on the socket will be sent on the +interface determined by the most recent successful use of this call. + +For IPv6 sockets, `multicastInterface` should include a scope to indicate the +interface as in the examples that follow. In IPv6, individual `send` calls can +also use explicit scope in addresses, so only packets sent to a multicast +address without specifying an explicit scope are affected by the most recent +successful use of this call. + +#### Examples: IPv6 Outgoing Multicast Interface + +On most systems, where scope format uses the interface name: + +```js +const socket = dgram.createSocket('udp6'); + +socket.bind(1234, () => { + socket.setMulticastInterface('::%eth1'); +}); +``` + +On Windows, where scope format uses an interface number: + +```js +const socket = dgram.createSocket('udp6'); + +socket.bind(1234, () => { + socket.setMulticastInterface('::%2'); +}); +``` + +#### Example: IPv4 Outgoing Multicast Interface +All systems use an IP of the host on the desired physical interface: +```js +const socket = dgram.createSocket('udp4'); + +socket.bind(1234, () => { + socket.setMulticastInterface('10.0.0.2'); +}); +``` + +#### Call Results + +A call on a socket that is not ready to send or no longer open may throw a *Not +running* [`Error`][]. + +If `multicastInterface` can not be parsed into an IP then an *EINVAL* +[`System Error`][] is thrown. + +On IPv4, if `multicastInterface` is a valid address but does not match any +interface, or if the address does not match the family then +a [`System Error`][] such as `EADDRNOTAVAIL` or `EPROTONOSUP` is thrown. + +On IPv6, most errors with specifying or omiting scope will result in the socket +continuing to use (or returning to) the system's default interface selection. + +A socket's address family's ANY address (IPv4 `'0.0.0.0'` or IPv6 `'::'`) can be +used to return control of the sockets default outgoing interface to the system +for future multicast packets. + + ### socket.setMulticastLoopback(flag) + +* {integer} + +The `process.ppid` property returns the PID of the current parent process. + +```js +console.log(`The parent process is pid ${process.ppid}`); +``` + ## process.release