diff --git a/.eslintrc b/.eslintrc index 8d3689443bd1de..618b3d51116053 100644 --- a/.eslintrc +++ b/.eslintrc @@ -93,6 +93,7 @@ rules: no-multiple-empty-lines: [2, {max: 2, maxEOF: 0, maxBOF: 0}] no-tabs: 2 no-trailing-spaces: 2 + operator-linebreak: [2, after, {overrides: {'?': ignore, ':': ignore}}] quotes: [2, single, avoid-escape] semi: 2 semi-spacing: 2 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6bf44097890794..7b004801207054 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -9,7 +9,7 @@ Contributors guide: https://github.com/nodejs/node/blob/master/CONTRIBUTING.md ##### Checklist -- [ ] `make -j8 test` (UNIX), or `vcbuild test nosign` (Windows) passes +- [ ] `make -j4 test` (UNIX), or `vcbuild test nosign` (Windows) passes - [ ] tests and/or benchmarks are included - [ ] documentation is changed or added - [ ] commit message follows commit guidelines diff --git a/BUILDING.md b/BUILDING.md index 5051da343353b3..b1962d53c2caf4 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -24,6 +24,15 @@ On OS X, you will also need: this under the menu `Xcode -> Preferences -> Downloads` * This step will install `gcc` and the related toolchain containing `make` +* You may want to setup [firewall rules](tools/macosx-firewall.sh) to avoid +popups asking to accept incoming network connections when running tests: + +```console +$ sudo ./tools/macosx-firewall.sh +``` +Running this script will add rules for the executable `node` in the out +directory and the symbolic `node` link in the projects root directory. + On FreeBSD and OpenBSD, you may also need: * libexecinfo @@ -31,9 +40,17 @@ To build Node.js: ```console $ ./configure -$ make +$ make -j4 ``` +Running `make` with the `-j4` flag will cause it to run 4 compilation jobs +concurrently which may significantly reduce build time. The number after `-j` +can be changed to best suit the number of processor cores on your machine. If +you run into problems running `make` with concurrency, try running it without +the `-j4` flag. See the +[GNU Make Documentation](https://www.gnu.org/software/make/manual/html_node/Parallel.html) +for more information. + Note that the above requires that `python` resolve to Python 2.6 or 2.7 and not a newer version. To run the tests: diff --git a/CHANGELOG.md b/CHANGELOG.md index f5263390e5c07c..8d8f2d68e12005 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,7 +28,8 @@ release. - 7.2.1
+ 7.3.0
+ 7.2.1
7.2.0
7.1.0
7.0.0
diff --git a/COLLABORATOR_GUIDE.md b/COLLABORATOR_GUIDE.md index 702d539d460301..abf91289fcfdec 100644 --- a/COLLABORATOR_GUIDE.md +++ b/COLLABORATOR_GUIDE.md @@ -126,7 +126,7 @@ information regarding the change process: - Protects against the assumption that GitHub will be around forever. Review the commit message to ensure that it adheres to the guidelines -outlined in the [contributing](https://github.com/nodejs/node/blob/master/CONTRIBUTING.md#step-3-commit) guide. +outlined in the [contributing](./CONTRIBUTING.md#step-3-commit) guide. See the commit log for examples such as [this one](https://github.com/nodejs/node/commit/b636ba8186) if unsure @@ -237,7 +237,8 @@ Save the file and close the editor. You'll be asked to enter a new commit message for that commit. This is a good moment to fix incorrect commit logs, ensure that they are properly formatted, and add `Reviewed-By` lines. -* The commit message text must conform to the [commit message guidelines](../CONTRIBUTING.md#step-3-commit). +* The commit message text must conform to the +[commit message guidelines](./CONTRIBUTING.md#step-3-commit). Time to push it: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6f44949a31e0ca..830f2615528170 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -156,7 +156,7 @@ to see how they should be structured can also help. To run the tests on Unix / OS X: ```text -$ ./configure && make -j8 test +$ ./configure && make -j4 test ``` Windows: @@ -189,7 +189,7 @@ You can run tests directly with node: $ ./node ./test/parallel/test-stream2-transform.js ``` -Remember to recompile with `make -j8` in between test runs if you change +Remember to recompile with `make -j4` in between test runs if you change core modules. ### Step 6: Push diff --git a/Makefile b/Makefile index 975efc96866009..d17930776f3d67 100644 --- a/Makefile +++ b/Makefile @@ -64,13 +64,18 @@ endif # to check for changes. .PHONY: $(NODE_EXE) $(NODE_G_EXE) +# The -r/-L check stops it recreating the link if it is already in place, +# otherwise $(NODE_EXE) being a .PHONY target means it is always re-run. +# Without the check there is a race condition between the link being deleted +# and recreated which can break the addons build when running test-ci +# See comments on the build-addons target for some more info $(NODE_EXE): config.gypi out/Makefile $(MAKE) -C out BUILDTYPE=Release V=$(V) - ln -fs out/Release/$(NODE_EXE) $@ + if [ ! -r $@ -o ! -L $@ ]; then ln -fs out/Release/$(NODE_EXE) $@; fi $(NODE_G_EXE): config.gypi out/Makefile $(MAKE) -C out BUILDTYPE=Debug V=$(V) - ln -fs out/Debug/$(NODE_EXE) $@ + if [ ! -r $@ -o ! -L $@ ]; then ln -fs out/Debug/$(NODE_EXE) $@; fi out/Makefile: common.gypi deps/uv/uv.gyp deps/http_parser/http_parser.gyp \ deps/zlib/zlib.gyp deps/v8/gypfiles/toolchain.gypi \ diff --git a/README.md b/README.md index 68ffbb90598d0f..bdb74b5446ac40 100644 --- a/README.md +++ b/README.md @@ -237,8 +237,8 @@ more information about the governance of the Node.js project, see **Ilkka Myller** <ilkka.myller@nodefield.com> * [isaacs](https://github.com/isaacs) - **Isaac Z. Schlueter** <i@izs.me> -* [italoacasas](https://github.com/italoacasas) -**Italo A. Casas** <me@italoacasas.com> +* [italoacasas](https://github.com/italoacasas) - +**Italo A. Casas** <me@italoacasas.com> * [iWuzHere](https://github.com/iWuzHere) - **Imran Iqbal** <imran@imraniqbal.org> * [JacksonTian](https://github.com/JacksonTian) - diff --git a/benchmark/README.md b/benchmark/README.md index a90f0f548fdab3..bbabcf4c4e9fde 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -50,6 +50,21 @@ 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. + +If we used the "http://cran.us.r-project.org" mirror, it could look somehting like +this: + +```R +install.packages("ggplot2", repo="http://cran.us.r-project.org") +``` + +Of course, use the mirror that suits your location. +A list of mirrors is [located here](https://cran.r-project.org/mirrors.html). + ## Running benchmarks ### Running individual benchmarks diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index df187b8307a6f6..009a3b10425ee4 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 4 #define V8_BUILD_NUMBER 500 -#define V8_PATCH_LEVEL 44 +#define V8_PATCH_LEVEL 45 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/base/platform/time.cc b/deps/v8/src/base/platform/time.cc index 76a820955fb98d..6b483382f02ea7 100644 --- a/deps/v8/src/base/platform/time.cc +++ b/deps/v8/src/base/platform/time.cc @@ -639,7 +639,7 @@ bool TimeTicks::IsHighResolutionClockWorking() { bool ThreadTicks::IsSupported() { #if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ - defined(V8_OS_MACOSX) || defined(V8_OS_ANDROID) + defined(V8_OS_MACOSX) || defined(V8_OS_ANDROID) || defined(V8_OS_SOLARIS) return true; #elif defined(V8_OS_WIN) return IsSupportedWin(); @@ -655,6 +655,8 @@ ThreadTicks ThreadTicks::Now() { #elif(defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \ defined(V8_OS_ANDROID) return ThreadTicks(ClockNow(CLOCK_THREAD_CPUTIME_ID)); +#elif V8_OS_SOLARIS + return ThreadTicks(gethrvtime() / Time::kNanosecondsPerMicrosecond); #elif V8_OS_WIN return ThreadTicks::GetForThread(::GetCurrentThread()); #else diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 2eef3512a0c22a..b9f8369335a0d6 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -282,7 +282,7 @@ const buf = Buffer.from([1, 2, 3]); // 1 // 2 // 3 -for (var b of buf) { +for (const b of buf) { console.log(b); } ``` @@ -392,9 +392,9 @@ deprecated: v6.0.0 * `size` {Integer} The desired length of the new `Buffer` -Allocates a new `Buffer` of `size` bytes. The `size` must be less than or equal -to the value of [`buffer.kMaxLength`]. Otherwise, a [`RangeError`] is thrown. -A zero-length `Buffer` will be created if `size <= 0`. +Allocates a new `Buffer` of `size` bytes. If the `size` is larger than +[`buffer.kMaxLength`] or smaller than 0, a [`RangeError`] will be thrown. +A zero-length `Buffer` will be created if `size` is 0. Unlike [`ArrayBuffers`][`ArrayBuffer`], the underlying memory for `Buffer` instances created in this way is *not initialized*. The contents of a newly created `Buffer` @@ -404,14 +404,14 @@ are unknown and *could contain sensitive data*. Use Example: ```js -const buf = new Buffer(5); +const buf = new Buffer(10); -// Prints: (contents may vary): +// Prints: (contents may vary): console.log(buf); buf.fill(0); -// Prints: +// Prints: console.log(buf); ``` @@ -470,9 +470,9 @@ const buf = Buffer.alloc(5); console.log(buf); ``` -The `size` must be less than or equal to the value of [`buffer.kMaxLength`]. -Otherwise, a [`RangeError`] is thrown. A zero-length `Buffer` will be created if -`size <= 0`. +Allocates a new `Buffer` of `size` bytes. If the `size` is larger than +[`buffer.kMaxLength`] or smaller than 0, a [`RangeError`] will be thrown. +A zero-length `Buffer` will be created if `size` is 0. If `fill` is specified, the allocated `Buffer` will be initialized by calling [`buf.fill(fill)`][`buf.fill()`]. @@ -511,9 +511,9 @@ added: v5.10.0 * `size` {Integer} The desired length of the new `Buffer` -Allocates a new *non-zero-filled* `Buffer` of `size` bytes. The `size` must -be less than or equal to the value of [`buffer.kMaxLength`]. Otherwise, a -[`RangeError`] is thrown. A zero-length `Buffer` will be created if `size <= 0`. +Allocates a new `Buffer` of `size` bytes. If the `size` is larger than +[`buffer.kMaxLength`] or smaller than 0, a [`RangeError`] will be thrown. +A zero-length `Buffer` will be created if `size` is 0. The underlying memory for `Buffer` instances created in this way is *not initialized*. The contents of the newly created `Buffer` are unknown and @@ -523,14 +523,14 @@ initialized*. The contents of the newly created `Buffer` are unknown and Example: ```js -const buf = Buffer.allocUnsafe(5); +const buf = Buffer.allocUnsafe(10); -// Prints: (contents may vary): +// Prints: (contents may vary): console.log(buf); buf.fill(0); -// Prints: +// Prints: console.log(buf); ``` @@ -557,10 +557,9 @@ added: v5.10.0 * `size` {Integer} The desired length of the new `Buffer` -Allocates a new *non-zero-filled* and non-pooled `Buffer` of `size` bytes. The -`size` must be less than or equal to the value of [`buffer.kMaxLength`]. -Otherwise, a [`RangeError`] is thrown. A zero-length `Buffer` will be created if -`size <= 0`. +Allocates a new `Buffer` of `size` bytes. If the `size` is larger than +[`buffer.kMaxLength`] or smaller than 0, a [`RangeError`] will be thrown. +A zero-length `Buffer` will be created if `size` is 0. The underlying memory for `Buffer` instances created in this way is *not initialized*. The contents of the newly created `Buffer` are unknown and @@ -995,7 +994,7 @@ overlapping region within the same `Buffer` ```js const buf = Buffer.allocUnsafe(26); -for (var i = 0 ; i < 26 ; i++) { +for (let i = 0 ; i < 26 ; i++) { // 97 is the decimal ASCII value for 'a' buf[i] = i + 97; } @@ -1028,7 +1027,7 @@ const buf = Buffer.from('buffer'); // [3, 102] // [4, 101] // [5, 114] -for (var pair of buf.entries()) { +for (const pair of buf.entries()) { console.log(pair); } ``` @@ -1122,7 +1121,7 @@ Examples: const buf = Buffer.from('this is a buffer'); // Prints: 0 -console.log(buf.indexOf('this'))); +console.log(buf.indexOf('this')); // Prints: 2 console.log(buf.indexOf('is')); @@ -1212,7 +1211,7 @@ const buf = Buffer.from('buffer'); // 3 // 4 // 5 -for (var key of buf.keys()) { +for (const key of buf.keys()) { console.log(key); } ``` @@ -1223,8 +1222,8 @@ added: v6.0.0 --> * `value` {String | Buffer | Integer} What to search for -* `byteOffset` {Integer} Where to begin searching in `buf` (not inclusive). - **Default:** [`buf.length`] +* `byteOffset` {Integer} Where to begin searching in `buf`. + **Default:** [`buf.length`]` - 1` * `encoding` {String} If `value` is a string, this is its encoding. **Default:** `'utf8'` * Returns: {Integer} The index of the last occurrence of `value` in `buf` or `-1` @@ -1264,7 +1263,7 @@ console.log(buf.lastIndexOf('buffer', 4)); const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2'); // Prints: 6 -console.log(utf16Buffer.lastIndexOf('\u03a3', null, 'ucs2')); +console.log(utf16Buffer.lastIndexOf('\u03a3', undefined, 'ucs2')); // Prints: 4 console.log(utf16Buffer.lastIndexOf('\u03a3', -5, 'ucs2')); @@ -1302,7 +1301,7 @@ use [`buf.slice()`] to create a new `Buffer`. Examples: ```js -var buf = Buffer.allocUnsafe(10); +let buf = Buffer.allocUnsafe(10); buf.write('abcdefghj', 0, 'ascii'); @@ -1446,7 +1445,7 @@ const buf = Buffer.from([0, 5]); console.log(buf.readInt16BE()); // Prints: 1280 -console.log(buf.readInt16LE(1)); +console.log(buf.readInt16LE()); // Throws an exception: RangeError: Index out of range console.log(buf.readInt16LE(1)); @@ -1509,10 +1508,10 @@ Examples: ```js const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); -// Prints: 1234567890ab +// Prints: -546f87a9cbee console.log(buf.readIntLE(0, 6).toString(16)); -// Prints: -546f87a9cbee +// Prints: 1234567890ab console.log(buf.readIntBE(0, 6).toString(16)); // Throws an exception: RangeError: Index out of range @@ -1673,7 +1672,7 @@ one byte from the original `Buffer` ```js const buf1 = Buffer.allocUnsafe(26); -for (var i = 0 ; i < 26 ; i++) { +for (let i = 0 ; i < 26 ; i++) { // 97 is the decimal ASCII value for 'a' buf1[i] = i + 97; } @@ -1737,7 +1736,7 @@ console.log(buf1); const buf2 = Buffer.from([0x1, 0x2, 0x3]); // Throws an exception: RangeError: Buffer size must be a multiple of 16-bits -buf2.swap32(); +buf2.swap16(); ``` ### buf.swap32() @@ -1822,7 +1821,7 @@ Examples: ```js const buf1 = Buffer.allocUnsafe(26); -for (var i = 0 ; i < 26 ; i++) { +for (let i = 0 ; i < 26 ; i++) { // 97 is the decimal ASCII value for 'a' buf1[i] = i + 97; } @@ -1897,7 +1896,7 @@ const buf = Buffer.from('buffer'); // 102 // 101 // 114 -for (var value of buf.values()) { +for (const value of buf.values()) { console.log(value); } @@ -1908,7 +1907,7 @@ for (var value of buf.values()) { // 102 // 101 // 114 -for (var value of buf) { +for (const value of buf) { console.log(value); } ``` @@ -2293,7 +2292,7 @@ Returns the maximum number of bytes that will be returned when `buf.inspect()` is called. This can be overridden by user modules. See [`util.inspect()`] for more details on `buf.inspect()` behavior. -Note that this is a property on the `buffer` module as returned by +Note that this is a property on the `buffer` module returned by `require('buffer')`, not on the `Buffer` global or a `Buffer` instance. ## buffer.kMaxLength @@ -2306,6 +2305,9 @@ added: v3.0.0 On 32-bit architectures, this value is `(2^30)-1` (~1GB). On 64-bit architectures, this value is `(2^31)-1` (~2GB). +Note that this is a property on the `buffer` module returned by +`require('buffer')`, not on the `Buffer` global or a `Buffer` instance. + ## buffer.transcode(source, fromEnc, toEnc) +* Returns: {Worker} A reference to `worker`. + In a worker, this function will close all servers, wait for the `'close'` event on those servers, and then disconnect the IPC channel. diff --git a/doc/api/crypto.md b/doc/api/crypto.md index ef9db7ffc65420..7f77d3f940768c 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1082,26 +1082,15 @@ deprecated: v0.11.13 > Stability: 0 - Deprecated: Use [`tls.createSecureContext()`][] instead. -The `crypto.createCredentials()` method is a deprecated alias for creating -and returning a `tls.SecureContext` object. The `crypto.createCredentials()` -method should not be used. +- `details` {Object} Identical to [`tls.createSecureContext()`][]. -The optional `details` argument is a hash object with keys: +The `crypto.createCredentials()` method is a deprecated function for creating +and returning a `tls.SecureContext`. It should not be used. Replace it with +[`tls.createSecureContext()`][] which has the exact same arguments and return +value. -* `pfx` : {String|Buffer} - PFX or PKCS12 encoded private - key, certificate and CA certificates -* `key` : {String} - PEM encoded private key -* `passphrase` : {String} - passphrase for the private key or PFX -* `cert` : {String} - PEM encoded certificate -* `ca` : {String|Array} - Either a string or array of strings of PEM encoded CA - certificates to trust. -* `crl` : {String|Array} - Either a string or array of strings of PEM encoded CRLs - (Certificate Revocation List) -* `ciphers`: {String} using the [OpenSSL cipher list format][] describing the - cipher algorithms to use or exclude. - -If no 'ca' details are given, Node.js will use Mozilla's default -[publicly trusted list of CAs][]. +Returns a `tls.SecureContext`, as-if [`tls.createSecureContext()`][] had been +called. ### crypto.createDecipher(algorithm, password) -* `options` {Object} - * `host` {string} Host the client should connect to. - * `port` {number} Port the client should connect to. - * `socket` {net.Socket} Establish secure connection on a given socket rather - than creating a new socket. If this option is specified, `host` and `port` - are ignored. - * `path` {string} Creates unix socket connection to path. If this option is - specified, `host` and `port` are ignored. - * `pfx` {string|Buffer} A string or `Buffer` containing the private key, - certificate, and CA certs of the client in PFX or PKCS12 format. - * `key` {string|string[]|Buffer|Buffer[]} A string, `Buffer`, array of - strings, or array of `Buffer`s containing the private key of the client in - PEM format. - * `passphrase` {string} A string containing the passphrase for the private key - or pfx. - * `cert` {string|string[]|Buffer|Buffer[]} A string, `Buffer`, array of - strings, or array of `Buffer`s containing the certificate key of the client - in PEM format. - * `ca` {string|string[]|Buffer|Buffer[]} A string, `Buffer`, array of strings, - or array of `Buffer`s of trusted certificates in PEM format. If this is - omitted several well known "root" CAs (like VeriSign) will be used. These - are used to authorize connections. - * `ciphers` {string} A string describing the ciphers to use or exclude, - separated by `:`. Uses the same default cipher suite as - [`tls.createServer()`][]. - * `rejectUnauthorized` {boolean} If `true`, the server certificate is verified - against the list of supplied CAs. An `'error'` event is emitted if - verification fails; `err.code` contains the OpenSSL error code. Defaults to - `true`. - * `NPNProtocols` {string[]|Buffer[]} An array of strings or `Buffer`s - containing supported NPN protocols. `Buffer`s should have the format - `[len][name][len][name]...` e.g. `0x05hello0x05world`, where the first - byte is the length of the next protocol name. Passing an array is usually - much simpler, e.g. `['hello', 'world']`. - * `ALPNProtocols`: {string[]|Buffer[]} An array of strings or `Buffer`s - containing the supported ALPN protocols. `Buffer`s should have the format - `[len][name][len][name]...` e.g. `0x05hello0x05world`, where the first byte - is the length of the next protocol name. Passing an array is usually much - simpler: `['hello', 'world']`.) - * `servername`: {string} Server name for the SNI (Server Name Indication) TLS - extension. - * `checkServerIdentity(servername, cert)` {Function} A callback function - to be used when checking the server's hostname against the certificate. - This should throw an error if verification fails. The method should return - `undefined` if the `servername` and `cert` are verified. - * `secureProtocol` {string} The SSL method to use, e.g. `SSLv3_method` to - force SSL version 3. The possible values depend on the version of OpenSSL - installed in the environment and are defined in the constant - [SSL_METHODS][]. - * `secureContext` {object} An optional TLS context object as returned by from - `tls.createSecureContext( ... )`. It can be used for caching client - certificates, keys, and CA certificates. - * `session` {Buffer} A `Buffer` instance, containing TLS session. - * `minDHSize` {number} Minimum size of the DH parameter in bits to accept a - TLS connection. When a server offers a DH parameter with a size less - than `minDHSize`, the TLS connection is destroyed and an error is thrown. - Defaults to `1024`. -* `callback` {Function} +* `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()`][]. -Creates a new client connection to the given `options.port` and `options.host` -If `options.host` is omitted, it defaults to `localhost`. +Same as [`tls.connect()`][] except that `port` and `host` can be provided +as arguments instead of options. -The `callback` function, if specified, will be added as a listener for the -[`'secureConnect'`][] event. +*Note*: A port or host option, if specified, will take precedence over any port +or host argument. -`tls.connect()` returns a [`tls.TLSSocket`][] object. +## tls.connect(path[, options][, callback]) + -## tls.connect(port[, host][, 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]) -* `port` {number} -* `host` {string} * `options` {Object} - * `host` {string} Host the client should connect to. + * `host` {string} Host the client should connect to, defaults to 'localhost'. * `port` {number} Port the client should connect to. - * `socket` {net.Socket} Establish secure connection on a given socket rather - than creating a new socket. If this option is specified, `host` and `port` - are ignored. * `path` {string} Creates unix socket connection to path. If this option is specified, `host` and `port` are ignored. - * `pfx` {string|Buffer} A string or `Buffer` containing the private key, - certificate, and CA certs of the client in PFX or PKCS12 format. - * `key` {string|string[]|Buffer|Buffer[]} A string, `Buffer`, array of - strings, or array of `Buffer`s containing the private key of the client in - PEM format. - * `passphrase` {string} A string containing the passphrase for the private key - or pfx. - * `cert` {string|string[]|Buffer|Buffer[]} A string, `Buffer`, array of - strings, or array of `Buffer`s containing the certificate key of the client - in PEM format. - * `ca` {string|string[]|Buffer|Buffer[]} A string, `Buffer`, array of strings, - or array of `Buffer`s of trusted certificates in PEM format. If this is - omitted several well known "root" CAs (like VeriSign) will be used. These - are used to authorize connections. - * `ciphers` {string} A string describing the ciphers to use or exclude, - separated by `:`. Uses the same default cipher suite as - [`tls.createServer()`][]. + * `socket` {net.Socket} Establish secure connection on a given socket rather + than creating a new socket. If this option is specified, `path`, `host` and + `port` are ignored. Usually, a socket is already connected when passed to + `tls.connect()`, but it can be connected later. Note that + connection/disconnection/destruction of `socket` is the user's + responsibility, calling `tls.connect()` will not cause `net.connect()` to be + called. * `rejectUnauthorized` {boolean} If `true`, the server certificate is verified against the list of supplied CAs. An `'error'` event is emitted if verification fails; `err.code` contains the OpenSSL error code. Defaults to @@ -833,24 +806,21 @@ added: v0.11.3 to be used when checking the server's hostname against the certificate. This should throw an error if verification fails. The method should return `undefined` if the `servername` and `cert` are verified. - * `secureProtocol` {string} The SSL method to use, e.g. `SSLv3_method` to - force SSL version 3. The possible values depend on the version of OpenSSL - installed in the environment and are defined in the constant - [SSL_METHODS][]. - * `secureContext` {object} An optional TLS context object as returned by from - `tls.createSecureContext( ... )`. It can be used for caching client - certificates, keys, and CA certificates. * `session` {Buffer} A `Buffer` instance, containing TLS session. * `minDHSize` {number} Minimum size of the DH parameter in bits to accept a TLS connection. When a server offers a DH parameter with a size less than `minDHSize`, the TLS connection is destroyed and an error is thrown. Defaults to `1024`. + * `secureContext`: Optional TLS context object created with + [`tls.createSecureContext()`][]. If a `secureContext` is _not_ provided, one + 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. * `callback` {Function} -Creates a new client connection to the given `port` and `host` or -`options.port` and `options.host`. (If `host` is omitted, it defaults to -`localhost`.) - The `callback` function, if specified, will be added as a listener for the [`'secureConnect'`][] event. @@ -918,81 +888,88 @@ added: v0.11.13 --> * `options` {Object} - * `pfx` {string|Buffer} A string or `Buffer` holding the PFX or PKCS12 encoded - private key, certificate, and CA certificates. - * `key` {string|string[]|Buffer|Object[]} The private key of the server in - PEM format. To support multiple keys using different algorithms, an array - can be provided either as an array of key strings or as an array of objects - in the format `{pem: key, passphrase: passphrase}`. This option is - *required* for ciphers that make use of private keys. - * `passphrase` {string} A string containing the passphrase for the private key - or pfx. - * `cert` {string} A string containing the PEM encoded certificate - * `ca`{string|string[]|Buffer|Buffer[]} A string, `Buffer`, array of strings, - or array of `Buffer`s of trusted certificates in PEM format. If omitted, - several well known "root" CAs (like VeriSign) will be used. These are used - to authorize connections. - * `crl` {string|string[]} Either a string or array of strings of PEM encoded - CRLs (Certificate Revocation List). - * `ciphers` {string} A string describing the ciphers to use or exclude. - Consult - - for details on the format. - * `honorCipherOrder` {boolean} If `true`, when a cipher is being selected, - the server's preferences will be used instead of the client preferences. + * `pfx` {string|Buffer} Optional PFX or PKCS12 encoded private key and + certificate chain. `pfx` is an alternative to providing `key` and `cert` + individually. PFX is usually encrypted, if it is, `passphrase` will be used + to decrypt it. + * `key` {string|string[]|Buffer|Buffer[]|Object[]} Optional private keys in + PEM format. PEM allows the option of private keys being encrypted. Encrypted + keys will be decrypted with `options.passphrase`. Multiple keys using + different algorithms can be provided either as an array of unencrypted key + strings or buffers, or an array of objects in the form `{pem: + [, passphrase: ]}`. The object form can only occur in + an array. `object.passphrase` is optional. Encrypted keys will be decrypted + with `object.passphrase` if provided, or `options.passphrase` if it is not. + * `passphrase` {string} Optional shared passphrase used for a single private + key and/or a PFX. + * `cert` {string|string[]|Buffer|Buffer[]} Optional cert chains in PEM format. + One cert chain should be provided per private key. Each cert chain should + consist of the PEM formatted certificate for a provided private `key`, + followed by the PEM formatted intermediate certificates (if any), in order, + and not including the root CA (the root CA must be pre-known to the peer, + see `ca`). When providing multiple cert chains, they do not have to be in + the same order as their private keys in `key`. If the intermediate + certificates are not provided, the peer will not be able to validate the + certificate, and the handshake will fail. + * `ca`{string|string[]|Buffer|Buffer[]} Optional CA certificates to trust. + Default is the well-known CAs from Mozilla. When connecting to peers that + use certificates issued privately, or self-signed, the private root CA or + self-signed certificate must be provided to verify the peer. + * `crl` {string|string[]|Buffer|Buffer[]} Optional PEM formatted + CRLs (Certificate Revocation Lists). + * `ciphers` {string} Optional cipher suite specification, replacing the + default. For more information, see [modifying the default cipher suite][]. + * `honorCipherOrder` {boolean} Attempt to use the server's cipher suite + preferences instead of the client's. When `true`, causes + `SSL_OP_CIPHER_SERVER_PREFERENCE` to be set in `secureOptions`, see + [OpenSSL Options][] for more information. + *Note*: [`tls.createServer()`][] sets the default value to `true`, other + APIs that create secure contexts leave it unset. + * `ecdhCurve` {string} A string describing a named curve to use for ECDH key + agreement or `false` to disable ECDH. Defaults to `prime256v1` (NIST P-256). + Use [`crypto.getCurves()`][] to obtain a list of available curve names. On + recent releases, `openssl ecparam -list_curves` will also display the name + and description of each available elliptic curve. + * `dhparam` {string|Buffer} Diffie Hellman parameters, required for + [Perfect Forward Secrecy][]. Use `openssl dhparam` to create the parameters. + The key length must be greater than or equal to 1024 bits, otherwise an + error will be thrown. It is strongly recommended to use 2048 bits or larger + for stronger security. If omitted or invalid, the parameters are silently + discarded and DHE ciphers will not be available. + * `secureProtocol` {string} Optional SSL method to use, default is + `"SSLv23_method"`. The possible values are listed as [SSL_METHODS][], use + the function names as strings. For example, `"SSLv3_method"` to force SSL + version 3. + * `secureOptions` {number} Optionally affect the OpenSSL protocol behaviour, + which is not usually necessary. This should be used carefully if at all! + Value is a numeric bitmask of the `SSL_OP_*` options from + [OpenSSL Options][]. + * `sessionIdContext` {string} Optional opaque identifier used by servers to + ensure session state is not shared between applications. Unused by clients. + *Note*: [`tls.createServer()`][] uses a 128 bit truncated SHA1 hash value + generated from `process.argv`, other APIs that create secure contexts + have no default value. The `tls.createSecureContext()` method creates a credentials object. +A key is *required* for ciphers that make use of certificates. Either `key` or +`pfx` can be used to provide it. + If the 'ca' option is not given, then Node.js will use the default publicly trusted list of CAs as given in . -## tls.createServer(options[, secureConnectionListener]) +## tls.createServer([options][, secureConnectionListener]) * `options` {Object} - * `pfx` {string|Buffer} A string or `Buffer` containing the private key, - certificate and CA certs of the server in PFX or PKCS12 format. (Mutually - exclusive with the `key`, `cert`, and `ca` options.) - * `key` {string|string[]|Buffer|Object[]} The private key of the server in - PEM format. To support multiple keys using different algorithms an array can - be provided either as a plain array of key strings or an array of objects - in the format `{pem: key, passphrase: passphrase}`. This option is - *required* for ciphers that make use of private keys. - * `passphrase` {string} A string containing the passphrase for the private - key or pfx. - * `cert` {string|string[]|Buffer|Buffer[]} A string, `Buffer`, array of - strings, or array of `Buffer`s containing the certificate key of the server - in PEM format. (Required) - * `ca` {string|string[]|Buffer|Buffer[]} A string, `Buffer`, array of strings, - or array of `Buffer`s of trusted certificates in PEM format. If this is - omitted several well known "root" CAs (like VeriSign) will be used. These - are used to authorize connections. - * `crl` {string|string[]} Either a string or array of strings of PEM encoded - CRLs (Certificate Revocation List). - * `ciphers` {string} A string describing the ciphers to use or exclude, - separated by `:`. - * `ecdhCurve` {string} A string describing a named curve to use for ECDH key - agreement or `false` to disable ECDH. Defaults to `prime256v1` (NIST P-256). - Use [`crypto.getCurves()`][] to obtain a list of available curve names. On - recent releases, `openssl ecparam -list_curves` will also display the name - and description of each available elliptic curve. - * `dhparam` {string|Buffer} A string or `Buffer` containing Diffie Hellman - parameters, required for [Perfect Forward Secrecy][]. Use - `openssl dhparam` to create the parameters. The key length must be greater - than or equal to 1024 bits, otherwise an error will be thrown. It is - strongly recommended to use 2048 bits or larger for stronger security. If - omitted or invalid, the parameters are silently discarded and DHE ciphers - will not be available. * `handshakeTimeout` {number} Abort the connection if the SSL/TLS handshake does not finish in the specified number of milliseconds. Defaults to `120` seconds. A `'clientError'` is emitted on the `tls.Server` object whenever a handshake times out. - * `honorCipherOrder` {boolean} When choosing a cipher, use the server's - preferences instead of the client preferences. Defaults to `true`. * `requestCert` {boolean} If `true` the server will request a certificate from clients that connect and attempt to verify that certificate. Defaults to `false`. @@ -1019,58 +996,13 @@ added: v0.3.2 a 16-byte HMAC key, and a 16-byte AES key. This can be used to accept TLS session tickets on multiple instances of the TLS server. *Note* that this is automatically shared between `cluster` module workers. - * `sessionIdContext` {string} A string containing an opaque identifier for - session resumption. If `requestCert` is `true`, the default is a 128 bit - truncated SHA1 hash value generated from the command-line. Otherwise, a - default is not provided. - * `secureProtocol` {string} The SSL method to use, e.g. `SSLv3_method` to - force SSL version 3. The possible values depend on the version of OpenSSL - installed in the environment and are defined in the constant - [SSL_METHODS][]. + * ...: Any [`tls.createSecureContext()`][] options can be provided. For + servers, the identity options (`pfx` or `key`/`cert`) are usually required. * `secureConnectionListener` {Function} Creates a new [tls.Server][]. The `secureConnectionListener`, if provided, is automatically set as a listener for the [`'secureConnection'`][] event. -For the `ciphers` option, the default cipher suite is: - -```text -ECDHE-RSA-AES128-GCM-SHA256: -ECDHE-ECDSA-AES128-GCM-SHA256: -ECDHE-RSA-AES256-GCM-SHA384: -ECDHE-ECDSA-AES256-GCM-SHA384: -DHE-RSA-AES128-GCM-SHA256: -ECDHE-RSA-AES128-SHA256: -DHE-RSA-AES128-SHA256: -ECDHE-RSA-AES256-SHA384: -DHE-RSA-AES256-SHA384: -ECDHE-RSA-AES256-SHA256: -DHE-RSA-AES256-SHA256: -HIGH: -!aNULL: -!eNULL: -!EXPORT: -!DES: -!RC4: -!MD5: -!PSK: -!SRP: -!CAMELLIA -``` - -The default cipher suite prefers GCM ciphers for [Chrome's 'modern -cryptography' setting] and also prefers ECDHE and DHE ciphers for Perfect -Forward Secrecy, while offering *some* backward compatibility. - -128 bit AES is preferred over 192 and 256 bit AES in light of [specific -attacks affecting larger AES key sizes]. - -Old clients that rely on insecure and deprecated RC4 or DES-based ciphers -(like Internet Explorer 6) cannot complete the handshaking process with -the default configuration. If these clients _must_ be supported, the -[TLS recommendations] may offer a compatible cipher suite. For more details -on the format, see the [OpenSSL cipher list format documentation]. - The following illustrates a simple echo server: ```js @@ -1254,6 +1186,8 @@ where `secure_socket` has the same API as `pair.cleartext`. [OpenSSL cipher list format documentation]: https://www.openssl.org/docs/man1.0.2/apps/ciphers.html#CIPHER-LIST-FORMAT [Chrome's 'modern cryptography' setting]: https://www.chromium.org/Home/chromium-security/education/tls#TOC-Cipher-Suites +[OpenSSL Options]: crypto.html#crypto_openssl_options +[modifying the default cipher suite]: #tls_modifying_the_default_tls_cipher_suite [specific attacks affecting larger AES key sizes]: https://www.schneier.com/blog/archives/2009/07/another_new_aes.html [`crypto.getCurves()`]: crypto.html#crypto_crypto_getcurves [`tls.createServer()`]: #tls_tls_createserver_options_secureconnectionlistener diff --git a/doc/api/tty.md b/doc/api/tty.md index f9be1fc4ffd3e5..8f250e45d655f9 100644 --- a/doc/api/tty.md +++ b/doc/api/tty.md @@ -50,6 +50,13 @@ raw device. Defaults to `false`. added: v0.7.7 --> +Allows configuration of `tty.ReadStream` so that it operates as a raw device. + +When in raw mode, input is always available character-by-character, not +including modifiers. Additionally, all special processing of characters by the +terminal is disabled, including echoing input characters. +Note that `CTRL`+`C` will no longer cause a `SIGINT` when in this mode. + * `mode` {boolean} If `true`, configures the `tty.ReadStream` to operate as a raw device. If `false`, configures the `tty.ReadStream` to operate in its default mode. The `readStream.isRaw` property will be set to the resulting diff --git a/doc/changelogs/CHANGELOG_V7.md b/doc/changelogs/CHANGELOG_V7.md index cdb0f692fab7ce..68753cb522d061 100644 --- a/doc/changelogs/CHANGELOG_V7.md +++ b/doc/changelogs/CHANGELOG_V7.md @@ -6,7 +6,8 @@ -7.2.1
+7.3.0
+7.2.1
7.2.0
7.1.0
7.0.0
@@ -23,6 +24,158 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + +## 2016-12-20, Version 7.3.0 (Current), @cjihrig + +Thank you to @italoacasas for preparing the majority of this release. + +### Notable changes + +* **buffer**: + - buffer.fill() now works properly for the UCS2 encoding on Big-Endian machines. (Anna Henningsen) [#9837](https://github.com/nodejs/node/pull/9837) +* **cluster**: + - disconnect() now returns a reference to the disconnected worker. (Sean Villars) [#10019](https://github.com/nodejs/node/pull/10019) +* **crypto**: + - The built-in list of Well-Known CAs (Certificate Authorities) can now be extended via a NODE_EXTRA_CA_CERTS environment variable. (Sam Roberts) [#9139](https://github.com/nodejs/node/pull/9139) +* **http**: + - Remove stale timeout listeners in order to prevent a memory leak when using keep alive. (Karl Böhlmark) [#9440](https://github.com/nodejs/node/pull/9440) +* **tls**: + - Allow obvious key/passphrase combinations. (Sam Roberts) [#10294](https://github.com/nodejs/node/pull/10294) +* **url**: + - Including base argument in URL.originFor() to meet specification compliance. (joyeecheung) [#10021](https://github.com/nodejs/node/pull/10021) + - Improve URLSearchParams to meet specification compliance. (Timothy Gu) [#9484](https://github.com/nodejs/node/pull/9484) + +### Commits + +* [[`c2cc11b3c6`](https://github.com/nodejs/node/commit/c2cc11b3c6)] - Working on v7.2.2 (Jeremiah Senkpiel) [#10127](https://github.com/nodejs/node/pull/10127) +* [[`b99a372e91`](https://github.com/nodejs/node/commit/b99a372e91)] - **buffer**: fix single-character string filling (Anna Henningsen) [#9837](https://github.com/nodejs/node/pull/9837) +* [[`d8b6723096`](https://github.com/nodejs/node/commit/d8b6723096)] - **buffer**: handle UCS2 `.fill()` properly on BE (Anna Henningsen) [#9837](https://github.com/nodejs/node/pull/9837) +* [[`e61331ee9b`](https://github.com/nodejs/node/commit/e61331ee9b)] - **build**: fix node_g target (Daniel Bevenius) [#10153](https://github.com/nodejs/node/pull/10153) +* [[`9d04152e15`](https://github.com/nodejs/node/commit/9d04152e15)] - **build**: Don't regenerate node symlink (sxa555) [#9827](https://github.com/nodejs/node/pull/9827) +* [[`5d14602181`](https://github.com/nodejs/node/commit/5d14602181)] - **(SEMVER-MINOR)** **cluster**: return worker reference from disconnect() (Sean Villars) [#10019](https://github.com/nodejs/node/pull/10019) +* [[`6963e8aa9d`](https://github.com/nodejs/node/commit/6963e8aa9d)] - **(SEMVER-MINOR)** **crypto**: allow adding extra certs to well-known CAs (Sam Roberts) [#9139](https://github.com/nodejs/node/pull/9139) +* [[`a308a2fae4`](https://github.com/nodejs/node/commit/a308a2fae4)] - **deps**: cherry-pick 081fce3 from V8 upstream (Matt Loring) [#10342](https://github.com/nodejs/node/pull/10342) +* [[`7c3d280bf0`](https://github.com/nodejs/node/commit/7c3d280bf0)] - **doc**: rework tls for accuracy and clarity (Sam Roberts) [#9800](https://github.com/nodejs/node/pull/9800) +* [[`6b98906a08`](https://github.com/nodejs/node/commit/6b98906a08)] - **doc**: document R CRAN mirror process (Lucas Holmquist) [#10211](https://github.com/nodejs/node/pull/10211) +* [[`7e8c5e3490`](https://github.com/nodejs/node/commit/7e8c5e3490)] - **doc**: expand common module material in test guide (Rich Trott) [#10251](https://github.com/nodejs/node/pull/10251) +* [[`ee736b276c`](https://github.com/nodejs/node/commit/ee736b276c)] - **doc**: fix broken link in COLLABORATOR_GUIDE.md (Michael Dawson) [#10267](https://github.com/nodejs/node/pull/10267) +* [[`40b0ca1329`](https://github.com/nodejs/node/commit/40b0ca1329)] - **doc**: fix typo in code example of 'path' module (pallxk) [#10136](https://github.com/nodejs/node/pull/10136) +* [[`b44e7891d0`](https://github.com/nodejs/node/commit/b44e7891d0)] - **doc**: standardizing on make -j4 (Jonathan Darling) [#9961](https://github.com/nodejs/node/pull/9961) +* [[`ff8fdb14fb`](https://github.com/nodejs/node/commit/ff8fdb14fb)] - **doc**: add note to parallelize make (Jonathan Darling) [#9961](https://github.com/nodejs/node/pull/9961) +* [[`5a64187bed`](https://github.com/nodejs/node/commit/5a64187bed)] - **doc**: buffer allocation throws for negative size (joyeecheung) [#10151](https://github.com/nodejs/node/pull/10151) +* [[`20fdf3aec6`](https://github.com/nodejs/node/commit/20fdf3aec6)] - **doc**: add some info on `tty#setRawMode()` (Jeremiah Senkpiel) [#10147](https://github.com/nodejs/node/pull/10147) +* [[`ae53a6e12b`](https://github.com/nodejs/node/commit/ae53a6e12b)] - **doc**: update `path.format` description and examples (anoff) [#10046](https://github.com/nodejs/node/pull/10046) +* [[`30340388f1`](https://github.com/nodejs/node/commit/30340388f1)] - **doc**: add a variable declaration in the buffer.md (Vse Mozhet Byt) [#9795](https://github.com/nodejs/node/pull/9795) +* [[`d64e52c68d`](https://github.com/nodejs/node/commit/d64e52c68d)] - **doc**: adding missing - in README (Italo A. Casas) [#10170](https://github.com/nodejs/node/pull/10170) +* [[`39bf5bfaf1`](https://github.com/nodejs/node/commit/39bf5bfaf1)] - **doc**: removing extra space in README (Italo A. Casas) [#10168](https://github.com/nodejs/node/pull/10168) +* [[`bc64a63440`](https://github.com/nodejs/node/commit/bc64a63440)] - **doc**: fix a wrong note in the buffer.md (Vse Mozhet Byt) [#9795](https://github.com/nodejs/node/pull/9795) +* [[`d4c73d4823`](https://github.com/nodejs/node/commit/d4c73d4823)] - **doc**: remove an extraneous word in the buffer.md (Vse Mozhet Byt) [#9795](https://github.com/nodejs/node/pull/9795) +* [[`d373b2f2fb`](https://github.com/nodejs/node/commit/d373b2f2fb)] - **doc**: fix examples in buffer.md to avoid confusion (Vse Mozhet Byt) [#9795](https://github.com/nodejs/node/pull/9795) +* [[`7a39a44dbc`](https://github.com/nodejs/node/commit/7a39a44dbc)] - **doc**: remove a wrong remark in the buffer.md (Vse Mozhet Byt) [#9795](https://github.com/nodejs/node/pull/9795) +* [[`39b083eb51`](https://github.com/nodejs/node/commit/39b083eb51)] - **doc**: repeat a remark as needed in the buffer.md (Vse Mozhet Byt) [#9795](https://github.com/nodejs/node/pull/9795) +* [[`622690f242`](https://github.com/nodejs/node/commit/622690f242)] - **doc**: fix copy-paste artifacts in the buffer.md (Vse Mozhet Byt) [#9795](https://github.com/nodejs/node/pull/9795) +* [[`3b848a279b`](https://github.com/nodejs/node/commit/3b848a279b)] - **doc**: fix wrong function arguments in the buffer.md (Vse Mozhet Byt) [#9795](https://github.com/nodejs/node/pull/9795) +* [[`9e47b943a7`](https://github.com/nodejs/node/commit/9e47b943a7)] - **doc**: fix a syntax error in the buffer.md (Vse Mozhet Byt) [#9795](https://github.com/nodejs/node/pull/9795) +* [[`1864222d50`](https://github.com/nodejs/node/commit/1864222d50)] - **doc**: var => const/let in the buffer.md (Vse Mozhet Byt) [#9795](https://github.com/nodejs/node/pull/9795) +* [[`7b924f1713`](https://github.com/nodejs/node/commit/7b924f1713)] - **doc**: fix typo in ecdhCurve, a tls property name (Sam Roberts) [#10345](https://github.com/nodejs/node/pull/10345) +* [[`2673be676a`](https://github.com/nodejs/node/commit/2673be676a)] - **fs**: remove unused argument from copyObject() (Ethan Arrowood) [#10041](https://github.com/nodejs/node/pull/10041) +* [[`1081f0f33d`](https://github.com/nodejs/node/commit/1081f0f33d)] - **fs**: remove needless assignment of null (Francis Gulotta) [#10260](https://github.com/nodejs/node/pull/10260) +* [[`dded482bb8`](https://github.com/nodejs/node/commit/dded482bb8)] - **http**: remove stale timeout listeners (Karl Böhlmark) [#9440](https://github.com/nodejs/node/pull/9440) +* [[`b41db3396b`](https://github.com/nodejs/node/commit/b41db3396b)] - **inspector**: check if connected before waiting (Eugene Ostroukhov) [#10094](https://github.com/nodejs/node/pull/10094) +* [[`b6a8bc6ac3`](https://github.com/nodejs/node/commit/b6a8bc6ac3)] - **lib,test**: use consistent operator linebreak style (Michaël Zasso) [#10178](https://github.com/nodejs/node/pull/10178) +* [[`ef2fa56314`](https://github.com/nodejs/node/commit/ef2fa56314)] - **src**: fix string format mistake for 32 bit node (Alex Newman) [#10082](https://github.com/nodejs/node/pull/10082) +* [[`d4e160c946`](https://github.com/nodejs/node/commit/d4e160c946)] - **(SEMVER-MINOR)** **src**: add wrapper for process.emitWarning() (Sam Roberts) [#9139](https://github.com/nodejs/node/pull/9139) +* [[`ec2f13fe66`](https://github.com/nodejs/node/commit/ec2f13fe66)] - **src**: don't overwrite non-writable vm globals (Ben Noordhuis) [#10227](https://github.com/nodejs/node/pull/10227) +* [[`28ffd593e2`](https://github.com/nodejs/node/commit/28ffd593e2)] - **stream, test**: test _readableState.emittedReadable (Joyee Cheung) [#10249](https://github.com/nodejs/node/pull/10249) +* [[`729fecf390`](https://github.com/nodejs/node/commit/729fecf390)] - **stream_base**: homogenize req_wrap_obj use (Fedor Indutny) [#10184](https://github.com/nodejs/node/pull/10184) +* [[`8b9131c1f8`](https://github.com/nodejs/node/commit/8b9131c1f8)] - **test**: tls key/cert ordering not necessary (Sam Roberts) [#9800](https://github.com/nodejs/node/pull/9800) +* [[`8a34e60b41`](https://github.com/nodejs/node/commit/8a34e60b41)] - **test**: var to const in tls-no-cert-required (Sam Roberts) [#9800](https://github.com/nodejs/node/pull/9800) +* [[`ea16a2ab52`](https://github.com/nodejs/node/commit/ea16a2ab52)] - **test**: stream readable needReadable state (Joyee Cheung) [#10241](https://github.com/nodejs/node/pull/10241) +* [[`e4b29a57f9`](https://github.com/nodejs/node/commit/e4b29a57f9)] - **test**: refactor test-fs-read-stream-inherit (Rich Trott) [#10246](https://github.com/nodejs/node/pull/10246) +* [[`fb297cba8f`](https://github.com/nodejs/node/commit/fb297cba8f)] - **test**: refactor test-dgram-send-callback-multi-buffer (mfrance) [#9999](https://github.com/nodejs/node/pull/9999) +* [[`16fbd4f6bf`](https://github.com/nodejs/node/commit/16fbd4f6bf)] - **test**: refactor test-tls-ecdh-disable (Aaron Williams) [#9989](https://github.com/nodejs/node/pull/9989) +* [[`46c55a6454`](https://github.com/nodejs/node/commit/46c55a6454)] - **test**: cleanup test-stdout-close-catch.js (Travis Bretton) [#10006](https://github.com/nodejs/node/pull/10006) +* [[`8c8b1230da`](https://github.com/nodejs/node/commit/8c8b1230da)] - **test**: use const/let and common.mustCall (Outsider) [#9959](https://github.com/nodejs/node/pull/9959) +* [[`74563f07e9`](https://github.com/nodejs/node/commit/74563f07e9)] - **test**: refactor domain test (Adao Junior) [#10269](https://github.com/nodejs/node/pull/10269) +* [[`d9cfd5484f`](https://github.com/nodejs/node/commit/d9cfd5484f)] - **test**: clean up domain-no-error-handler test (weyj4) [#10291](https://github.com/nodejs/node/pull/10291) +* [[`553a32674a`](https://github.com/nodejs/node/commit/553a32674a)] - **test**: fix http-client-timeout-option-listeners (Rich Trott) [#10224](https://github.com/nodejs/node/pull/10224) +* [[`308cead66e`](https://github.com/nodejs/node/commit/308cead66e)] - **test**: update test-domain-uncaught-exception.js (Andy Chen) [#10193](https://github.com/nodejs/node/pull/10193) +* [[`60542cb98b`](https://github.com/nodejs/node/commit/60542cb98b)] - **test**: refactor test-domain.js (Siddhartha Sahai) [#10207](https://github.com/nodejs/node/pull/10207) +* [[`c0800d9449`](https://github.com/nodejs/node/commit/c0800d9449)] - **test**: refactor test-stream-big-push (Rich Trott) [#10226](https://github.com/nodejs/node/pull/10226) +* [[`b9361cae6e`](https://github.com/nodejs/node/commit/b9361cae6e)] - **test**: refactor test-http-dns-fail (Adrian Estrada) [#10243](https://github.com/nodejs/node/pull/10243) +* [[`a97f26476d`](https://github.com/nodejs/node/commit/a97f26476d)] - **test**: refactor test-crypto-random (Rich Trott) [#10232](https://github.com/nodejs/node/pull/10232) +* [[`2f9c8d977f`](https://github.com/nodejs/node/commit/2f9c8d977f)] - **test**: refactor test-http-pause-resume-one-end (Rich Trott) [#10210](https://github.com/nodejs/node/pull/10210) +* [[`90659bc95c`](https://github.com/nodejs/node/commit/90659bc95c)] - **test**: fix flaky test-dgram-exclusive-implicit-bind (Rich Trott) [#10212](https://github.com/nodejs/node/pull/10212) +* [[`a4f3080595`](https://github.com/nodejs/node/commit/a4f3080595)] - **test**: improvements in test fixtures symlinked (Adrian Estrada) [#10182](https://github.com/nodejs/node/pull/10182) +* [[`d5e30a69e2`](https://github.com/nodejs/node/commit/d5e30a69e2)] - **test**: refactor test-fs-fsync (Rob Adelmann) [#10176](https://github.com/nodejs/node/pull/10176) +* [[`be87441463`](https://github.com/nodejs/node/commit/be87441463)] - **test**: refactor test-http-after-connect.js (larissayvette) [#10229](https://github.com/nodejs/node/pull/10229) +* [[`2b78212445`](https://github.com/nodejs/node/commit/2b78212445)] - **test**: use strictEqual in test-debug-break (Adrian Estrada) [#10181](https://github.com/nodejs/node/pull/10181) +* [[`8b698d89ac`](https://github.com/nodejs/node/commit/8b698d89ac)] - **test**: refactor assert.equal, update syntax to ES6 (Prieto, Marcos) [#10190](https://github.com/nodejs/node/pull/10190) +* [[`3749dc6ce7`](https://github.com/nodejs/node/commit/3749dc6ce7)] - **test**: refactor http pipelined socket test (Rich Trott) [#10189](https://github.com/nodejs/node/pull/10189) +* [[`e1d813f3f8`](https://github.com/nodejs/node/commit/e1d813f3f8)] - **test**: refactor test-handle-wrap-close-abort (Rich Trott) [#10188](https://github.com/nodejs/node/pull/10188) +* [[`7f01484a7a`](https://github.com/nodejs/node/commit/7f01484a7a)] - **test**: add ES6 and strictEqual to test-fs-truncate (Adrian Estrada) [#10167](https://github.com/nodejs/node/pull/10167) +* [[`88839cf204`](https://github.com/nodejs/node/commit/88839cf204)] - **test**: replace var with const in test-require-dot (Amar Zavery) [#9916](https://github.com/nodejs/node/pull/9916) +* [[`09ec5db10b`](https://github.com/nodejs/node/commit/09ec5db10b)] - **test**: fail for missing output files (Anna Henningsen) [#10150](https://github.com/nodejs/node/pull/10150) +* [[`3f269cc760`](https://github.com/nodejs/node/commit/3f269cc760)] - **test**: use ES6 in test-debugger-client.js (Adrian Estrada) [#10183](https://github.com/nodejs/node/pull/10183) +* [[`1f11deb58f`](https://github.com/nodejs/node/commit/1f11deb58f)] - **test**: improve buffer transcode (Johnny Reading) [#10043](https://github.com/nodejs/node/pull/10043) +* [[`3e8df733e8`](https://github.com/nodejs/node/commit/3e8df733e8)] - **test**: improving crypto fips (James Tenenbaum) [#10002](https://github.com/nodejs/node/pull/10002) +* [[`6780c0e572`](https://github.com/nodejs/node/commit/6780c0e572)] - **test**: stream readableState readingMore state (Gregory) [#9868](https://github.com/nodejs/node/pull/9868) +* [[`c792e2ac49`](https://github.com/nodejs/node/commit/c792e2ac49)] - **test**: stream readableListening internal state (Italo A. Casas) [#9864](https://github.com/nodejs/node/pull/9864) +* [[`28c6df2604`](https://github.com/nodejs/node/commit/28c6df2604)] - **test**: add stdin-setrawmode.out file (Jonathan Darling) [#10149](https://github.com/nodejs/node/pull/10149) +* [[`f5347abac8`](https://github.com/nodejs/node/commit/f5347abac8)] - **test**: set stdin too for pseudo-tty tests (Anna Henningsen) [#10149](https://github.com/nodejs/node/pull/10149) +* [[`3a460d5469`](https://github.com/nodejs/node/commit/3a460d5469)] - **test**: check for error on invalid signal (Matt Phillips) [#10026](https://github.com/nodejs/node/pull/10026) +* [[`1ebb5b9adb`](https://github.com/nodejs/node/commit/1ebb5b9adb)] - **test**: refactor test-http-unix-socket (davidmarkclements) [#10072](https://github.com/nodejs/node/pull/10072) +* [[`8b7c97bc59`](https://github.com/nodejs/node/commit/8b7c97bc59)] - **test**: increase test coverage of BufferList (joyeecheung) [#10171](https://github.com/nodejs/node/pull/10171) +* [[`53e8e962d4`](https://github.com/nodejs/node/commit/53e8e962d4)] - **test**: fix flaky test-net-socket-timeout (Rich Trott) [#10172](https://github.com/nodejs/node/pull/10172) +* [[`ca38f70dea`](https://github.com/nodejs/node/commit/ca38f70dea)] - **test**: refactor test-net-keepalive.js (Kyle Corsi) [#9995](https://github.com/nodejs/node/pull/9995) +* [[`a9d4bd7a34`](https://github.com/nodejs/node/commit/a9d4bd7a34)] - **test**: refactor test-crypto-hmac (eudaimos) [#9958](https://github.com/nodejs/node/pull/9958) +* [[`778e5f7d0c`](https://github.com/nodejs/node/commit/778e5f7d0c)] - **test**: fix error in test-cluster-worker-death.js (Bruce Lai) [#9981](https://github.com/nodejs/node/pull/9981) +* [[`b67cad1174`](https://github.com/nodejs/node/commit/b67cad1174)] - **test**: use `assert.strictEqual` (anoff) [#9975](https://github.com/nodejs/node/pull/9975) +* [[`72fb05d062`](https://github.com/nodejs/node/commit/72fb05d062)] - **test**: change assert.equal to assert.strictEqual (Aileen) [#9946](https://github.com/nodejs/node/pull/9946) +* [[`dac757e502`](https://github.com/nodejs/node/commit/dac757e502)] - **test**: changed assert.equal to assert.strictEqual (vazina robertson) [#10015](https://github.com/nodejs/node/pull/10015) +* [[`d7988e0355`](https://github.com/nodejs/node/commit/d7988e0355)] - **test**: renamed assert.Equal to assert.strictEqual (Jared Young) +* [[`9d037cfa44`](https://github.com/nodejs/node/commit/9d037cfa44)] - **test**: improves test-tls-client-verify (Paul Graham) [#10051](https://github.com/nodejs/node/pull/10051) +* [[`2565e48445`](https://github.com/nodejs/node/commit/2565e48445)] - **test**: refactor test-https-agent-session-reuse (Diego Paez) [#10105](https://github.com/nodejs/node/pull/10105) +* [[`11140802f4`](https://github.com/nodejs/node/commit/11140802f4)] - **test**: refactor test-beforeexit-event (Rob Adelmann) [#10121](https://github.com/nodejs/node/pull/10121) +* [[`e695862531`](https://github.com/nodejs/node/commit/e695862531)] - **test**: improve test-fs-read-stream.js (Jenna Vuong) [#9629](https://github.com/nodejs/node/pull/9629) +* [[`be90638487`](https://github.com/nodejs/node/commit/be90638487)] - **test**: refactor test-domain-from-timer (Daniel Sims) [#9889](https://github.com/nodejs/node/pull/9889) +* [[`2c5d5629de`](https://github.com/nodejs/node/commit/2c5d5629de)] - **test**: refactor test-domain-exit-dispose-again (Ethan Arrowood) [#10003](https://github.com/nodejs/node/pull/10003) +* [[`6d4f270f2f`](https://github.com/nodejs/node/commit/6d4f270f2f)] - **test**: use const and strictEqual in test-os-homedir-no-envvar (CodeVana) [#9899](https://github.com/nodejs/node/pull/9899) +* [[`62f5a0bf59`](https://github.com/nodejs/node/commit/62f5a0bf59)] - **test**: check result of uv_loop_init and uv_write (Ben Noordhuis) [#10126](https://github.com/nodejs/node/pull/10126) +* [[`19432f05ff`](https://github.com/nodejs/node/commit/19432f05ff)] - **test**: refactor test-dgram-bind-default-address (Michael-Bryant Choa) [#9947](https://github.com/nodejs/node/pull/9947) +* [[`01509bc67e`](https://github.com/nodejs/node/commit/01509bc67e)] - **test**: move long-running test to sequential (Rich Trott) [#10161](https://github.com/nodejs/node/pull/10161) +* [[`d8dc890352`](https://github.com/nodejs/node/commit/d8dc890352)] - **test**: assert.throws() should include a RegExp (Chris Bystrek) [#9976](https://github.com/nodejs/node/pull/9976) +* [[`6f2f02d5ad`](https://github.com/nodejs/node/commit/6f2f02d5ad)] - **test**: invalid package.json causes error when require()ing in directory (Sam Shull) [#10044](https://github.com/nodejs/node/pull/10044) +* [[`6489a91027`](https://github.com/nodejs/node/commit/6489a91027)] - **test**: refactor test-listen-fd-ebadf (Richard Karmazin) [#10034](https://github.com/nodejs/node/pull/10034) +* [[`eb1664bed9`](https://github.com/nodejs/node/commit/eb1664bed9)] - **test**: refactor test-event-emitter-method-names (Rodrigo Palma) [#10027](https://github.com/nodejs/node/pull/10027) +* [[`c66cf2c1cf`](https://github.com/nodejs/node/commit/c66cf2c1cf)] - **test**: refactor tls-ticket-cluster (Yojan Shrestha) [#10023](https://github.com/nodejs/node/pull/10023) +* [[`de9972678e`](https://github.com/nodejs/node/commit/de9972678e)] - **test**: refactor test-domain-exit-dispose (Chris Henney) [#9938](https://github.com/nodejs/node/pull/9938) +* [[`5ca90777e6`](https://github.com/nodejs/node/commit/5ca90777e6)] - **test**: refactor test-stdin-from-file.js (amrios) [#10012](https://github.com/nodejs/node/pull/10012) +* [[`4d66578997`](https://github.com/nodejs/node/commit/4d66578997)] - **test**: use ES6 to update let & const (Jason Humphrey) [#9917](https://github.com/nodejs/node/pull/9917) +* [[`bb9174745b`](https://github.com/nodejs/node/commit/bb9174745b)] - **test**: fix test for buffer regression #649 (joyeecheung) [#9924](https://github.com/nodejs/node/pull/9924) +* [[`613798335c`](https://github.com/nodejs/node/commit/613798335c)] - **test**: stream readable resumeScheduled state (Italo A. Casas) [#10299](https://github.com/nodejs/node/pull/10299) +* [[`15c71f6c66`](https://github.com/nodejs/node/commit/15c71f6c66)] - **test**: improve code in test-fs-open.js (Adrian Estrada) [#10312](https://github.com/nodejs/node/pull/10312) +* [[`793d8719eb`](https://github.com/nodejs/node/commit/793d8719eb)] - **test**: fix flaky test-debug-port (Santiago Gimeno) [#10316](https://github.com/nodejs/node/pull/10316) +* [[`5e781a3883`](https://github.com/nodejs/node/commit/5e781a3883)] - **test**: refactor the code in test-dns-ipv6 (Adrian Estrada) [#10219](https://github.com/nodejs/node/pull/10219) +* [[`8b367c5ddd`](https://github.com/nodejs/node/commit/8b367c5ddd)] - **test**: improve test-child-process-fork-and-spawn (Adrian Estrada) [#10273](https://github.com/nodejs/node/pull/10273) +* [[`348e69c89d`](https://github.com/nodejs/node/commit/348e69c89d)] - **test**: fix flaky test-http-client-timeout-event (Rich Trott) [#10293](https://github.com/nodejs/node/pull/10293) +* [[`0d3ac89ff7`](https://github.com/nodejs/node/commit/0d3ac89ff7)] - **test**: add known_issues test for #6287 (AnnaMag) [#10272](https://github.com/nodejs/node/pull/10272) +* [[`f7f662cad5`](https://github.com/nodejs/node/commit/f7f662cad5)] - **test**: improve test-child-process-exec-buffer (Adrian Estrada) [#10275](https://github.com/nodejs/node/pull/10275) +* [[`f66461382c`](https://github.com/nodejs/node/commit/f66461382c)] - **timers**: fix handling of cleared immediates (hveldstra) [#9759](https://github.com/nodejs/node/pull/9759) +* [[`8e4b9fa487`](https://github.com/nodejs/node/commit/8e4b9fa487)] - **tls**: fix/annotate connect arg comments (Sam Roberts) [#9800](https://github.com/nodejs/node/pull/9800) +* [[`980acb4b95`](https://github.com/nodejs/node/commit/980acb4b95)] - **tls**: document and test option-less createServer (Sam Roberts) [#9800](https://github.com/nodejs/node/pull/9800) +* [[`41e1e6eb35`](https://github.com/nodejs/node/commit/41e1e6eb35)] - **tls**: do not refer to secureOptions as flags (Sam Roberts) [#9800](https://github.com/nodejs/node/pull/9800) +* [[`0b44384561`](https://github.com/nodejs/node/commit/0b44384561)] - **(SEMVER-MINOR)** **tls**: allow obvious key/passphrase combinations (Sam Roberts) [#10294](https://github.com/nodejs/node/pull/10294) +* [[`a92f2ad19c`](https://github.com/nodejs/node/commit/a92f2ad19c)] - **tools**: enforce consistent operator linebreak style (Michaël Zasso) [#10178](https://github.com/nodejs/node/pull/10178) +* [[`cc5bd9a0cf`](https://github.com/nodejs/node/commit/cc5bd9a0cf)] - **tools**: add macosx-firwall script to avoid popups (Daniel Bevenius) [#10114](https://github.com/nodejs/node/pull/10114) +* [[`7cb98138a9`](https://github.com/nodejs/node/commit/7cb98138a9)] - **tools**: forbid template literals in assert.throws (Michaël Zasso) [#10301](https://github.com/nodejs/node/pull/10301) +* [[`24482d08ce`](https://github.com/nodejs/node/commit/24482d08ce)] - **(SEMVER-MINOR)** **url**: add inspect function to TupleOrigin (Safia Abdalla) [#10039](https://github.com/nodejs/node/pull/10039) +* [[`f08d8a6c6f`](https://github.com/nodejs/node/commit/f08d8a6c6f)] - **url**: improve URLSearchParams spec compliance (Timothy Gu) [#9484](https://github.com/nodejs/node/pull/9484) +* [[`19d7197177`](https://github.com/nodejs/node/commit/19d7197177)] - **url**: add a got host pattern in url.js (Axel Monroy) [#9653](https://github.com/nodejs/node/pull/9653) +* [[`2da71f24de`](https://github.com/nodejs/node/commit/2da71f24de)] - **url, test**: fix typo in inspect output, add test (Jay Brownlee) [#10231](https://github.com/nodejs/node/pull/10231) +* [[`80cccce218`](https://github.com/nodejs/node/commit/80cccce218)] - **url, test**: including base argument in originFor (joyeecheung) [#10021](https://github.com/nodejs/node/pull/10021) +* [[`7a0fe9f471`](https://github.com/nodejs/node/commit/7a0fe9f471)] - **win,msi**: add required UIRef for localized strings (Bill Ticehurst) [#8884](https://github.com/nodejs/node/pull/8884) + ## 2016-12-06, Version 7.2.1 (Current), @Fishrock123 diff --git a/doc/guides/building-node-with-ninja.md b/doc/guides/building-node-with-ninja.md index 027c267e2b243d..29b32c3d7277de 100644 --- a/doc/guides/building-node-with-ninja.md +++ b/doc/guides/building-node-with-ninja.md @@ -16,7 +16,7 @@ ninja: Entering directory `out/Release` The bottom line will change while building, showing the progress as `[finished/total]` build steps. This is useful output that `make` does not produce and is one of the benefits of using Ninja. -Also, Ninja will likely compile much faster than even `make -j8` (or `-j`). +Also, Ninja will likely compile much faster than even `make -j4` (or `-j`). ## Considerations diff --git a/doc/guides/writing-tests.md b/doc/guides/writing-tests.md index d00be9cdbcc4c6..d628e3f6f5873c 100644 --- a/doc/guides/writing-tests.md +++ b/doc/guides/writing-tests.md @@ -19,7 +19,6 @@ Tests can be added for multiple reasons: - When fixing regressions and bugs. - When expanding test coverage. - ## Test structure Let's analyze this very basic test from the Node.js test suite: @@ -55,17 +54,22 @@ Let's analyze this very basic test from the Node.js test suite: const common = require('../common'); ``` -These two lines are mandatory and should be included on every test. -The `common` module is a helper module that provides useful tools for the tests. -If for some reason, no functionality from `common` is used, it should still be -included like this: +The first line enables strict mode. All tests should be in strict mode unless +the nature of the test requires that the test run without it. + +The second line loads the `common` module. The `common` module is a helper +module that provides useful tools for the tests. + +Even if no functions or other properties exported by `common` are used in a +test, the `common` module should still be included. This is because the `common` +module includes code that will cause tests to fail if variables are leaked into +the global space. In situations where no functions or other properties exported +by `common` are used, it can be included without assigning it to an identifier: ```javascript require('../common'); ``` -Why? It checks for leaks of globals. - **Lines 4-5** ```javascript @@ -76,7 +80,6 @@ Why? It checks for leaks of globals. A test should start with a comment containing a brief description of what it is designed to test. - **Lines 7-8** ```javascript diff --git a/doc/onboarding-extras.md b/doc/onboarding-extras.md index 7b7f60fd00705b..9e1a4a7ed7b14b 100644 --- a/doc/onboarding-extras.md +++ b/doc/onboarding-extras.md @@ -71,7 +71,7 @@ Please use these when possible / appropriate * major vs. everything else: run last versions tests against this version, if they pass, **probably** minor or patch * A breaking change helper ([full source](https://gist.github.com/chrisdickinson/ba532fa0e4e243fb7b44)): ```sh - git checkout $(git show -s --pretty='%T' $(git show-ref -d $(git describe --abbrev=0) | tail -n1 | awk '{print $1}')) -- test; make -j8 test + git checkout $(git show -s --pretty='%T' $(git show-ref -d $(git describe --abbrev=0) | tail -n1 | awk '{print $1}')) -- test; make -j4 test ``` diff --git a/lib/_http_client.js b/lib/_http_client.js index 6837c94df98eea..1846e36e12bf88 100644 --- a/lib/_http_client.js +++ b/lib/_http_client.js @@ -562,7 +562,13 @@ function tickOnSocket(req, socket) { socket.on('close', socketCloseListener); if (req.timeout) { - socket.once('timeout', () => req.emit('timeout')); + const emitRequestTimeout = () => req.emit('timeout'); + socket.once('timeout', emitRequestTimeout); + req.once('response', (res) => { + res.once('end', () => { + socket.removeListener('timeout', emitRequestTimeout); + }); + }); } req.emit('socket', socket); } diff --git a/lib/_tls_common.js b/lib/_tls_common.js index 6e98c1ee4d66d2..85ae71f8d15cc1 100644 --- a/lib/_tls_common.js +++ b/lib/_tls_common.js @@ -12,9 +12,9 @@ var crypto = null; const binding = process.binding('crypto'); const NativeSecureContext = binding.SecureContext; -function SecureContext(secureProtocol, flags, context) { +function SecureContext(secureProtocol, secureOptions, context) { if (!(this instanceof SecureContext)) { - return new SecureContext(secureProtocol, flags, context); + return new SecureContext(secureProtocol, secureOptions, context); } if (context) { @@ -29,7 +29,7 @@ function SecureContext(secureProtocol, flags, context) { } } - if (flags) this.context.setOptions(flags); + if (secureOptions) this.context.setOptions(secureOptions); } exports.SecureContext = SecureContext; @@ -78,17 +78,11 @@ exports.createSecureContext = function createSecureContext(options, context) { if (Array.isArray(options.key)) { for (i = 0; i < options.key.length; i++) { const key = options.key[i]; - if (key.passphrase) - c.context.setKey(key.pem, key.passphrase); - else - c.context.setKey(key); + const passphrase = key.passphrase || options.passphrase; + c.context.setKey(key.pem || key, passphrase); } } else { - if (options.passphrase) { - c.context.setKey(options.key, options.passphrase); - } else { - c.context.setKey(options.key); - } + c.context.setKey(options.key, options.passphrase); } } diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js index d9dafceb950dc7..434384cec81595 100644 --- a/lib/_tls_wrap.js +++ b/lib/_tls_wrap.js @@ -745,18 +745,19 @@ TLSSocket.prototype.getProtocol = function() { // "PATH_LENGTH_EXCEEDED", "INVALID_PURPOSE" "CERT_UNTRUSTED", // "CERT_REJECTED" // -function Server(/* [options], listener */) { - var options, listener; +function Server(options, listener) { + if (!(this instanceof Server)) + return new Server(options, listener); - if (arguments[0] !== null && typeof arguments[0] === 'object') { - options = arguments[0]; - listener = arguments[1]; - } else if (typeof arguments[0] === 'function') { + if (typeof options === 'function') { + listener = options; options = {}; - listener = arguments[0]; + } else if (options == null || typeof options === 'object') { + options = options || {}; + } else { + throw new TypeError('options must be an object'); } - if (!(this instanceof Server)) return new Server(options, listener); this._contexts = []; @@ -975,6 +976,11 @@ function normalizeConnectArgs(listArgs) { var options = args[0]; var cb = args[1]; + // If args[0] was options, then normalize dealt with it. + // If args[0] is port, or args[0], args[1] is host,port, we need to + // find the options and merge them in, normalize's options has only + // the host/port/path args that it knows about, not the tls options. + // This means that options.host overrides a host arg. if (listArgs[1] !== null && typeof listArgs[1] === 'object') { options = util._extend(options, listArgs[1]); } else if (listArgs[2] !== null && typeof listArgs[2] === 'object') { @@ -984,7 +990,7 @@ function normalizeConnectArgs(listArgs) { return (cb) ? [options, cb] : [options]; } -exports.connect = function(/* [port, host], options, cb */) { +exports.connect = function(/* [port,] [host,] [options,] [cb] */) { const argsLen = arguments.length; var args = new Array(argsLen); for (var i = 0; i < argsLen; i++) diff --git a/lib/buffer.js b/lib/buffer.js index 3453f5fe8cd6ae..557ac867e2e0fc 100644 --- a/lib/buffer.js +++ b/lib/buffer.js @@ -672,23 +672,27 @@ Buffer.prototype.fill = function fill(val, start, end, encoding) { encoding = end; end = this.length; } - if (val.length === 1) { - var code = val.charCodeAt(0); - if (code < 256) - val = code; - } - if (val.length === 0) { - // Previously, if val === '', the Buffer would not fill, - // which is rather surprising. - val = 0; - } + if (encoding !== undefined && typeof encoding !== 'string') { throw new TypeError('encoding must be a string'); } - if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + var normalizedEncoding = internalUtil.normalizeEncoding(encoding); + if (normalizedEncoding === undefined) { throw new TypeError('Unknown encoding: ' + encoding); } + if (val.length === 0) { + // Previously, if val === '', the Buffer would not fill, + // which is rather surprising. + val = 0; + } else if (val.length === 1) { + var code = val.charCodeAt(0); + if ((normalizedEncoding === 'utf8' && code < 128) || + normalizedEncoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code; + } + } } else if (typeof val === 'number') { val = val & 255; } diff --git a/lib/cluster.js b/lib/cluster.js index 67e8833941789a..e95e19bcc672d4 100644 --- a/lib/cluster.js +++ b/lib/cluster.js @@ -430,6 +430,7 @@ function masterInit() { send(this, { act: 'disconnect' }); removeHandlesForWorker(this); removeWorker(this); + return this; }; Worker.prototype.destroy = function(signo) { @@ -687,6 +688,7 @@ function workerInit() { Worker.prototype.disconnect = function() { _disconnect.call(this); + return this; }; Worker.prototype.destroy = function() { diff --git a/lib/fs.js b/lib/fs.js index 27614e5cf1febc..52f392d749364c 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -56,8 +56,8 @@ function getOptions(options, defaultOptions) { return options; } -function copyObject(source, target) { - target = arguments.length >= 2 ? target : {}; +function copyObject(source) { + const target = {}; for (const key in source) target[key] = source[key]; return target; @@ -1794,7 +1794,6 @@ ReadStream.prototype._read = function(n) { if (!pool || pool.length - pool.used < kMinPoolSpace) { // discard the old pool. - pool = null; allocNewPool(this._readableState.highWaterMark); } diff --git a/lib/internal/url.js b/lib/internal/url.js index 79b9e1cb0f46bb..ba54aa8c233354 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -20,6 +20,11 @@ const kHost = Symbol('host'); const kPort = Symbol('port'); const kDomain = Symbol('domain'); +// https://tc39.github.io/ecma262/#sec-%iteratorprototype%-object +const IteratorPrototype = Object.getPrototypeOf( + Object.getPrototypeOf([][Symbol.iterator]()) +); + function StorageObject() {} StorageObject.prototype = Object.create(null); @@ -69,6 +74,15 @@ class TupleOrigin { result += `:${this.port}`; return result; } + + inspect() { + return `TupleOrigin { + scheme: ${this.scheme}, + host: ${this.host}, + port: ${this.port}, + domain: ${this.domain} + }`; + } } class URL { @@ -92,7 +106,8 @@ class URL { this[context].query = query; this[context].fragment = fragment; this[context].host = host; - this[searchParams] = new URLSearchParams(this); + this[searchParams] = new URLSearchParams(query); + this[searchParams][context] = this; }); } @@ -309,8 +324,31 @@ class URL { } set search(search) { - update(this, search); - this[searchParams][searchParams] = querystring.parse(this.search); + search = String(search); + if (search[0] === '?') search = search.slice(1); + if (!search) { + this[context].query = null; + this[context].flags &= ~binding.URL_FLAGS_HAS_QUERY; + this[searchParams][searchParams] = {}; + return; + } + this[context].query = ''; + binding.parse(search, + binding.kQuery, + null, + this[context], + (flags, protocol, username, password, + host, port, path, query, fragment) => { + if (flags & binding.URL_FLAGS_FAILED) + return; + if (query) { + this[context].query = query; + this[context].flags |= binding.URL_FLAGS_HAS_QUERY; + } else { + this[context].flags &= ~binding.URL_FLAGS_HAS_QUERY; + } + }); + this[searchParams][searchParams] = querystring.parse(search); } get hash() { @@ -411,7 +449,7 @@ class URL { ret += ` hash: ${this.hash}\n`; if (opts.showHidden) { ret += ` cannot-be-base: ${this[cannotBeBase]}\n`; - ret += ` special: ${this[special]}\n;`; + ret += ` special: ${this[special]}\n`; } ret += '}'; return ret; @@ -484,76 +522,129 @@ function encodeAuth(str) { return out; } -function update(url, search) { - search = String(search); - if (!search) { - url[context].query = null; - url[context].flags &= ~binding.URL_FLAGS_HAS_QUERY; +function update(url, params) { + if (!url) return; + + url[context].query = params.toString(); +} + +function getSearchParamPairs(target) { + const obj = target[searchParams]; + const keys = Object.keys(obj); + const values = []; + for (var i = 0; i < keys.length; i++) { + const name = keys[i]; + const value = obj[name]; + if (Array.isArray(value)) { + for (const item of value) + values.push([name, item]); + } else { + values.push([name, value]); + } } - if (search[0] === '?') search = search.slice(1); - url[context].query = ''; - binding.parse(search, - binding.kQuery, - null, - url[context], - (flags, protocol, username, password, - host, port, path, query, fragment) => { - if (flags & binding.URL_FLAGS_FAILED) - return; - if (query) { - url[context].query = query; - url[context].flags |= binding.URL_FLAGS_HAS_QUERY; - } else { - url[context].flags &= ~binding.URL_FLAGS_HAS_QUERY; - } - }); + return values; } class URLSearchParams { - constructor(url) { - this[context] = url; - this[searchParams] = querystring.parse(url[context].search || ''); + constructor(init = '') { + if (init instanceof URLSearchParams) { + const childParams = init[searchParams]; + this[searchParams] = Object.assign(Object.create(null), childParams); + } else { + init = String(init); + if (init[0] === '?') init = init.slice(1); + this[searchParams] = querystring.parse(init); + } + + // "associated url object" + this[context] = null; + + // Class string for an instance of URLSearchParams. This is different from + // the class string of the prototype object (set below). + Object.defineProperty(this, Symbol.toStringTag, { + value: 'URLSearchParams', + writable: false, + enumerable: false, + configurable: true + }); } append(name, value) { + if (!this || !(this instanceof URLSearchParams)) { + throw new TypeError('Value of `this` is not a URLSearchParams'); + } + if (arguments.length < 2) { + throw new TypeError( + 'Both `name` and `value` arguments need to be specified'); + } + const obj = this[searchParams]; name = String(name); value = String(value); var existing = obj[name]; - if (!existing) { + if (existing === undefined) { obj[name] = value; } else if (Array.isArray(existing)) { existing.push(value); } else { obj[name] = [existing, value]; } - update(this[context], querystring.stringify(obj)); + update(this[context], this); } delete(name) { + if (!this || !(this instanceof URLSearchParams)) { + throw new TypeError('Value of `this` is not a URLSearchParams'); + } + if (arguments.length < 1) { + throw new TypeError('The `name` argument needs to be specified'); + } + const obj = this[searchParams]; name = String(name); delete obj[name]; - update(this[context], querystring.stringify(obj)); + update(this[context], this); } set(name, value) { + if (!this || !(this instanceof URLSearchParams)) { + throw new TypeError('Value of `this` is not a URLSearchParams'); + } + if (arguments.length < 2) { + throw new TypeError( + 'Both `name` and `value` arguments need to be specified'); + } + const obj = this[searchParams]; name = String(name); value = String(value); obj[name] = value; - update(this[context], querystring.stringify(obj)); + update(this[context], this); } get(name) { + if (!this || !(this instanceof URLSearchParams)) { + throw new TypeError('Value of `this` is not a URLSearchParams'); + } + if (arguments.length < 1) { + throw new TypeError('The `name` argument needs to be specified'); + } + const obj = this[searchParams]; name = String(name); var value = obj[name]; - return Array.isArray(value) ? value[0] : value; + return value === undefined ? null : Array.isArray(value) ? value[0] : value; } getAll(name) { + if (!this || !(this instanceof URLSearchParams)) { + throw new TypeError('Value of `this` is not a URLSearchParams'); + } + if (arguments.length < 1) { + throw new TypeError('The `name` argument needs to be specified'); + } + const obj = this[searchParams]; name = String(name); var value = obj[name]; @@ -561,32 +652,147 @@ class URLSearchParams { } has(name) { + if (!this || !(this instanceof URLSearchParams)) { + throw new TypeError('Value of `this` is not a URLSearchParams'); + } + if (arguments.length < 1) { + throw new TypeError('The `name` argument needs to be specified'); + } + const obj = this[searchParams]; name = String(name); return name in obj; } - *[Symbol.iterator]() { - const obj = this[searchParams]; - for (const name in obj) { - const value = obj[name]; - if (Array.isArray(value)) { - for (const item of value) - yield [name, item]; - } else { - yield [name, value]; - } + // https://heycam.github.io/webidl/#es-iterators + // Define entries here rather than [Symbol.iterator] as the function name + // must be set to `entries`. + entries() { + if (!this || !(this instanceof URLSearchParams)) { + throw new TypeError('Value of `this` is not a URLSearchParams'); + } + + return createSearchParamsIterator(this, 'key+value'); + } + + forEach(callback, thisArg = undefined) { + if (!this || !(this instanceof URLSearchParams)) { + throw new TypeError('Value of `this` is not a URLSearchParams'); + } + if (arguments.length < 1) { + throw new TypeError('The `callback` argument needs to be specified'); + } + + let pairs = getSearchParamPairs(this); + + var i = 0; + while (i < pairs.length) { + const [key, value] = pairs[i]; + callback.call(thisArg, value, key, this); + pairs = getSearchParamPairs(this); + i++; } } + // https://heycam.github.io/webidl/#es-iterable + keys() { + if (!this || !(this instanceof URLSearchParams)) { + throw new TypeError('Value of `this` is not a URLSearchParams'); + } + + return createSearchParamsIterator(this, 'key'); + } + + values() { + if (!this || !(this instanceof URLSearchParams)) { + throw new TypeError('Value of `this` is not a URLSearchParams'); + } + + return createSearchParamsIterator(this, 'value'); + } + + // https://url.spec.whatwg.org/#urlsearchparams-stringification-behavior toString() { + if (!this || !(this instanceof URLSearchParams)) { + throw new TypeError('Value of `this` is not a URLSearchParams'); + } + return querystring.stringify(this[searchParams]); } } +// https://heycam.github.io/webidl/#es-iterable-entries +URLSearchParams.prototype[Symbol.iterator] = URLSearchParams.prototype.entries; +Object.defineProperty(URLSearchParams.prototype, Symbol.toStringTag, { + value: 'URLSearchParamsPrototype', + writable: false, + enumerable: false, + configurable: true +}); + +// https://heycam.github.io/webidl/#dfn-default-iterator-object +function createSearchParamsIterator(target, kind) { + const iterator = Object.create(URLSearchParamsIteratorPrototype); + iterator[context] = { + target, + kind, + index: 0 + }; + return iterator; +} + +// https://heycam.github.io/webidl/#dfn-iterator-prototype-object +const URLSearchParamsIteratorPrototype = Object.setPrototypeOf({ + next() { + if (!this || + Object.getPrototypeOf(this) !== URLSearchParamsIteratorPrototype) { + throw new TypeError('Value of `this` is not a URLSearchParamsIterator'); + } + + const { + target, + kind, + index + } = this[context]; + const values = getSearchParamPairs(target); + const len = values.length; + if (index >= len) { + return { + value: undefined, + done: true + }; + } + + const pair = values[index]; + this[context].index = index + 1; + + let result; + if (kind === 'key') { + result = pair[0]; + } else if (kind === 'value') { + result = pair[1]; + } else { + result = pair; + } + + return { + value: result, + done: false + }; + } +}, IteratorPrototype); + +// Unlike interface and its prototype object, both default iterator object and +// iterator prototype object of an interface have the same class string. +Object.defineProperty(URLSearchParamsIteratorPrototype, Symbol.toStringTag, { + value: 'URLSearchParamsIterator', + writable: false, + enumerable: false, + configurable: true +}); -URL.originFor = function(url) { +URL.originFor = function(url, base) { if (!(url instanceof URL)) - url = new URL(url); + url = new URL(url, base); var origin; const protocol = url.protocol; switch (protocol) { diff --git a/lib/timers.js b/lib/timers.js index 56af3a92d6bfe2..6d456da36faf67 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -473,8 +473,8 @@ function unrefdHandle() { // Make sure we clean up if the callback is no longer a function // even if the timer is an interval. - if (!this.owner._repeat - || typeof this.owner._onTimeout !== 'function') { + if (!this.owner._repeat || + typeof this.owner._onTimeout !== 'function') { this.owner.close(); } } @@ -580,8 +580,10 @@ function processImmediate() { while (immediate) { domain = immediate.domain; - if (!immediate._onImmediate) + if (!immediate._onImmediate) { + immediate = immediate._idleNext; continue; + } if (domain) domain.enter(); diff --git a/lib/url.js b/lib/url.js index 03a9fb03dfcca7..75f4967ad2b6d3 100644 --- a/lib/url.js +++ b/lib/url.js @@ -42,6 +42,7 @@ function Url() { // compiled once on the first module load. const protocolPattern = /^([a-z0-9.+-]+:)/i; const portPattern = /:[0-9]*$/; +const hostPattern = /^\/\/[^@/]+@[^@/]+/; // Special case for a simple path URL const simplePathPattern = /^(\/\/?(?!\/)[^?\s]*)(\?[^\s]*)?$/; @@ -204,7 +205,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { // user@server is *always* interpreted as a hostname, and url // resolution will treat //foo/bar as host=foo,path=bar because that's // how the browser resolves relative URLs. - if (slashesDenoteHost || proto || /^\/\/[^@/]+@[^@/]+/.test(rest)) { + if (slashesDenoteHost || proto || hostPattern.test(rest)) { var slashes = rest.charCodeAt(0) === 47/*/*/ && rest.charCodeAt(1) === 47/*/*/; if (slashes && !(proto && hostlessProtocol[proto])) { diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc index fd7968ff68ced1..ec713942f50e7e 100644 --- a/src/inspector_agent.cc +++ b/src/inspector_agent.cc @@ -548,10 +548,12 @@ bool AgentImpl::IsStarted() { } void AgentImpl::WaitForDisconnect() { - shutting_down_ = true; - fprintf(stderr, "Waiting for the debugger to disconnect...\n"); - fflush(stderr); - inspector_->runMessageLoopOnPause(0); + if (state_ == State::kConnected) { + shutting_down_ = true; + fprintf(stderr, "Waiting for the debugger to disconnect...\n"); + fflush(stderr); + inspector_->runMessageLoopOnPause(0); + } } #define READONLY_PROPERTY(obj, str, var) \ diff --git a/src/node.cc b/src/node.cc index b33bc0d2a1782a..bdae47ee6c8211 100644 --- a/src/node.cc +++ b/src/node.cc @@ -2563,6 +2563,33 @@ void ClearFatalExceptionHandlers(Environment* env) { Undefined(env->isolate())).FromJust(); } +// Call process.emitWarning(str), fmt is a snprintf() format string +void ProcessEmitWarning(Environment* env, const char* fmt, ...) { + char warning[1024]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(warning, sizeof(warning), fmt, ap); + va_end(ap); + + HandleScope handle_scope(env->isolate()); + Context::Scope context_scope(env->context()); + + Local process = env->process_object(); + MaybeLocal emit_warning = process->Get(env->context(), + FIXED_ONE_BYTE_STRING(env->isolate(), "emitWarning")); + Local arg = node::OneByteString(env->isolate(), warning); + + Local f; + + if (!emit_warning.ToLocal(&f)) return; + if (!f->IsFunction()) return; + + // MakeCallback() unneeded, because emitWarning is internal code, it calls + // process.emit('warning', ..), but does so on the nextTick. + f.As()->Call(process, 1, &arg); +} + static void Binding(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -4508,6 +4535,8 @@ 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); #ifdef NODE_FIPS_MODE // In the case of FIPS builds we should make sure // the random source is properly initialized first. diff --git a/src/node_buffer.cc b/src/node_buffer.cc index 540de1827f9716..0e96fd6deed8d3 100644 --- a/src/node_buffer.cc +++ b/src/node_buffer.cc @@ -606,6 +606,9 @@ void Fill(const FunctionCallbackInfo& args) { } else if (enc == UCS2) { node::TwoByteValue str(env->isolate(), args[1]); + if (IsBigEndian()) + SwapBytes16(reinterpret_cast(&str[0]), str_length); + memcpy(ts_obj_data + start, *str, MIN(str_length, fill_length)); } else { diff --git a/src/node_contextify.cc b/src/node_contextify.cc index d74b01ea0da371..fc8aa451347b94 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -383,19 +383,22 @@ class ContextifyContext { if (ctx->context_.IsEmpty()) return; + auto attributes = PropertyAttribute::None; bool is_declared = - ctx->global_proxy()->HasRealNamedProperty(ctx->context(), - property).FromJust(); - bool is_contextual_store = ctx->global_proxy() != args.This(); + ctx->global_proxy()->GetRealNamedPropertyAttributes(ctx->context(), + property) + .To(&attributes); + bool read_only = + static_cast(attributes) & + static_cast(PropertyAttribute::ReadOnly); + + if (is_declared && read_only) + return; - bool set_property_will_throw = - args.ShouldThrowOnError() && - !is_declared && - is_contextual_store; + if (!is_declared && args.ShouldThrowOnError()) + return; - if (!set_property_will_throw) { - ctx->sandbox()->Set(property, value); - } + ctx->sandbox()->Set(property, value); } diff --git a/src/node_crypto.cc b/src/node_crypto.cc index 4d93dd4cb0723c..7b3bc406091494 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -120,6 +120,8 @@ const char* const root_certs[] = { #include "node_root_certs.h" // NOLINT(build/include_order) }; +std::string extra_root_certs_file; // NOLINT(runtime/string) + X509_STORE* root_cert_store; std::vector* root_certs_vector; @@ -440,7 +442,10 @@ void SecureContext::SetKey(const FunctionCallbackInfo& args) { } if (len == 2) { - THROW_AND_RETURN_IF_NOT_STRING(args[1], "Pass phrase"); + if (args[1]->IsUndefined() || args[1]->IsNull()) + len = 1; + else + THROW_AND_RETURN_IF_NOT_STRING(args[1], "Pass phrase"); } BIO *bio = LoadBIO(env, args[0]); @@ -789,6 +794,39 @@ void SecureContext::AddCRL(const FunctionCallbackInfo& args) { } +void UseExtraCaCerts(const std::string& file) { + extra_root_certs_file = file; +} + + +static unsigned long AddCertsFromFile( // NOLINT(runtime/int) + X509_STORE* store, + const char* file) { + ERR_clear_error(); + MarkPopErrorOnReturn mark_pop_error_on_return; + + BIO* bio = BIO_new_file(file, "r"); + if (!bio) { + return ERR_get_error(); + } + + while (X509* x509 = + PEM_read_bio_X509(bio, nullptr, CryptoPemCallback, nullptr)) { + X509_STORE_add_cert(store, x509); + X509_free(x509); + } + BIO_free_all(bio); + + unsigned long err = ERR_peek_error(); // NOLINT(runtime/int) + // Ignore error if its EOF/no start line found. + if (ERR_GET_LIB(err) == ERR_LIB_PEM && + ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { + return 0; + } + + return err; +} + void SecureContext::AddRootCerts(const FunctionCallbackInfo& args) { SecureContext* sc; ASSIGN_OR_RETURN_UNWRAP(&sc, args.Holder()); @@ -797,6 +835,18 @@ void SecureContext::AddRootCerts(const FunctionCallbackInfo& args) { if (!root_cert_store) { root_cert_store = NewRootCertStore(); + + if (!extra_root_certs_file.empty()) { + unsigned long err = AddCertsFromFile( // NOLINT(runtime/int) + root_cert_store, + extra_root_certs_file.c_str()); + if (err) { + ProcessEmitWarning(sc->env(), + "Ignoring extra certs from `%s`, load failed: %s\n", + extra_root_certs_file.c_str(), + ERR_error_string(err, nullptr)); + } + } } // Increment reference count so global store is not deleted along with CTX. @@ -1489,9 +1539,14 @@ static Local X509ToObject(Environment* env, X509* cert) { String::kNormalString, mem->length)); (void) BIO_reset(bio); - BN_ULONG exponent_word = BN_get_word(rsa->e); - BIO_printf(bio, "0x%lx", exponent_word); - + uint64_t exponent_word = static_cast(BN_get_word(rsa->e)); + uint32_t lo = static_cast(exponent_word); + uint32_t hi = static_cast(exponent_word >> 32); + if (hi == 0) { + BIO_printf(bio, "0x%x", lo); + } else { + BIO_printf(bio, "0x%x%08x", hi, lo); + } BIO_get_mem_ptr(bio, &mem); info->Set(env->exponent_string(), String::NewFromUtf8(env->isolate(), mem->data, diff --git a/src/node_crypto.h b/src/node_crypto.h index 31cbb4e64f0120..175206c40df586 100644 --- a/src/node_crypto.h +++ b/src/node_crypto.h @@ -65,6 +65,8 @@ extern int VerifyCallback(int preverify_ok, X509_STORE_CTX* ctx); extern X509_STORE* root_cert_store; +extern void UseExtraCaCerts(const std::string& file); + // Forward declaration class Connection; diff --git a/src/node_internals.h b/src/node_internals.h index ae284660782cfe..0a65be7642ff2a 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -129,6 +129,8 @@ void AppendExceptionLine(Environment* env, NO_RETURN void FatalError(const char* location, const char* message); +void ProcessEmitWarning(Environment* env, const char* fmt, ...); + v8::Local BuildStatsObject(Environment* env, const uv_stat_t* s); void SetupProcessObject(Environment* env, diff --git a/src/node_version.h b/src/node_version.h index 31ac3fac814e85..d92cfb5b1f3a5f 100644 --- a/src/node_version.h +++ b/src/node_version.h @@ -2,8 +2,8 @@ #define SRC_NODE_VERSION_H_ #define NODE_MAJOR_VERSION 7 -#define NODE_MINOR_VERSION 2 -#define NODE_PATCH_VERSION 2 +#define NODE_MINOR_VERSION 3 +#define NODE_PATCH_VERSION 1 #define NODE_VERSION_IS_RELEASE 0 diff --git a/src/stream_base.cc b/src/stream_base.cc index a12a1efc73be11..3ed622d7ef35a2 100644 --- a/src/stream_base.cc +++ b/src/stream_base.cc @@ -82,10 +82,8 @@ void StreamBase::AfterShutdown(ShutdownWrap* req_wrap, int status) { req_wrap_obj }; - if (req_wrap->object()->Has(env->context(), - env->oncomplete_string()).FromJust()) { + if (req_wrap_obj->Has(env->context(), env->oncomplete_string()).FromJust()) req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); - } delete req_wrap; } @@ -172,9 +170,8 @@ int StreamBase::Writev(const FunctionCallbackInfo& args) { int err = DoWrite(req_wrap, *bufs, count, nullptr); - req_wrap->object()->Set(env->async(), True(env->isolate())); - req_wrap->object()->Set(env->bytes_string(), - Number::New(env->isolate(), bytes)); + req_wrap_obj->Set(env->async(), True(env->isolate())); + req_wrap_obj->Set(env->bytes_string(), Number::New(env->isolate(), bytes)); const char* msg = Error(); if (msg != nullptr) { req_wrap_obj->Set(env->error_string(), OneByteString(env->isolate(), msg)); @@ -328,7 +325,7 @@ int StreamBase::WriteString(const FunctionCallbackInfo& args) { // Reference StreamWrap instance to prevent it from being garbage // collected before `AfterWrite` is called. CHECK_EQ(false, req_wrap->persistent().IsEmpty()); - req_wrap->object()->Set(env->handle_string(), send_handle_obj); + req_wrap_obj->Set(env->handle_string(), send_handle_obj); } err = DoWrite( @@ -338,7 +335,7 @@ int StreamBase::WriteString(const FunctionCallbackInfo& args) { reinterpret_cast(send_handle)); } - req_wrap->object()->Set(env->async(), True(env->isolate())); + req_wrap_obj->Set(env->async(), True(env->isolate())); if (err) req_wrap->Dispose(); @@ -383,10 +380,8 @@ void StreamBase::AfterWrite(WriteWrap* req_wrap, int status) { wrap->ClearError(); } - if (req_wrap->object()->Has(env->context(), - env->oncomplete_string()).FromJust()) { + if (req_wrap_obj->Has(env->context(), env->oncomplete_string()).FromJust()) req_wrap->MakeCallback(env->oncomplete_string(), arraysize(argv), argv); - } req_wrap->Dispose(); } diff --git a/test/cctest/test_inspector_socket.cc b/test/cctest/test_inspector_socket.cc index c7a282b75b4b8d..ada3df3d438ce8 100644 --- a/test/cctest/test_inspector_socket.cc +++ b/test/cctest/test_inspector_socket.cc @@ -121,8 +121,9 @@ static void do_write(const char* data, int len) { uv_buf_t buf[1]; buf[0].base = const_cast(data); buf[0].len = len; - uv_write(&req, reinterpret_cast(&client_socket), buf, 1, - write_done); + GTEST_ASSERT_EQ(0, + uv_write(&req, reinterpret_cast(&client_socket), + buf, 1, write_done)); SPIN_WHILE(req.data); } @@ -360,7 +361,7 @@ class InspectorSocketTest : public ::testing::Test { connected = false; inspector_ready = false; last_event = kInspectorHandshakeHttpGet; - uv_loop_init(&loop); + GTEST_ASSERT_EQ(0, uv_loop_init(&loop)); server = uv_tcp_t(); client_socket = uv_tcp_t(); server.data = &inspector; diff --git a/test/debugger/test-debug-break-on-uncaught.js b/test/debugger/test-debug-break-on-uncaught.js index 4b4602657cca0d..3acd70070bbf61 100644 --- a/test/debugger/test-debug-break-on-uncaught.js +++ b/test/debugger/test-debug-break-on-uncaught.js @@ -100,10 +100,11 @@ function runScenario(scriptName, throwsOnLine, next) { function assertHasPaused(client) { assert(exceptions.length, 'no exceptions thrown, race condition in test?'); - assert.equal(exceptions.length, 1, 'debugger did not pause on exception'); - assert.equal(exceptions[0].uncaught, true); - assert.equal(exceptions[0].script.name, testScript); - assert.equal(exceptions[0].sourceLine + 1, throwsOnLine); + assert.strictEqual(exceptions.length, 1, + 'debugger did not pause on exception'); + assert.strictEqual(exceptions[0].uncaught, true); + assert.strictEqual(exceptions[0].script.name, testScript); + assert.strictEqual(exceptions[0].sourceLine + 1, throwsOnLine); asserted = true; client.reqContinue(assert.ifError); } diff --git a/test/debugger/test-debugger-client.js b/test/debugger/test-debugger-client.js index 04823113ec32c1..743a3c4352e2e1 100644 --- a/test/debugger/test-debugger-client.js +++ b/test/debugger/test-debugger-client.js @@ -1,12 +1,12 @@ 'use strict'; const common = require('../common'); -var assert = require('assert'); -var debug = require('_debugger'); +const assert = require('assert'); +const debug = require('_debugger'); process.env.NODE_DEBUGGER_TIMEOUT = 2000; -var debugPort = common.PORT; +const debugPort = common.PORT; debug.port = debugPort; -var spawn = require('child_process').spawn; +const spawn = require('child_process').spawn; setTimeout(function() { if (nodeProcess) nodeProcess.kill('SIGTERM'); @@ -14,8 +14,8 @@ setTimeout(function() { }, 10000).unref(); -var resCount = 0; -var p = new debug.Protocol(); +let resCount = 0; +const p = new debug.Protocol(); p.onResponse = function(res) { resCount++; }; @@ -29,12 +29,12 @@ assert.strictEqual(resCount, 1); // Make sure split messages go in. -var parts = []; +const parts = []; parts.push('Content-Length: 336\r\n'); assert.strictEqual(parts[0].length, 21); parts.push('\r\n'); assert.strictEqual(parts[1].length, 2); -var bodyLength = 0; +let bodyLength = 0; parts.push('{"seq":12,"type":"event","event":"break","body":' + '{"invocationText":"#'); @@ -55,7 +55,7 @@ bodyLength += parts[4].length; assert.strictEqual(bodyLength, 336); -for (var i = 0; i < parts.length; i++) { +for (let i = 0; i < parts.length; i++) { p.execute(parts[i]); } assert.strictEqual(resCount, 2); @@ -63,24 +63,24 @@ assert.strictEqual(resCount, 2); // Make sure that if we get backed up, we still manage to get all the // messages -var d = 'Content-Length: 466\r\n\r\n' + - '{"seq":10,"type":"event","event":"afterCompile","success":true,' + - '"body":{"script":{"handle":1,"type":"script","name":"dns.js",' + - '"id":34,"lineOffset":0,"columnOffset":0,"lineCount":241,' + - '"sourceStart":"(function(module, exports, require) {' + - 'var dns = process.binding(\'cares\')' + - ';\\nvar ne","sourceLength":6137,"scriptType":2,"compilationType":0,' + - '"context":{"ref":0},"text":"dns.js (lines: 241)"}},"refs":' + - '[{"handle":0' + - ',"type":"context","text":"#"}],"running":true}' + - '\r\n\r\nContent-Length: 119\r\n\r\n' + - '{"seq":11,"type":"event","event":"scriptCollected","success":true,' + - '"body":{"script":{"id":26}},"refs":[],"running":true}'; +const d = 'Content-Length: 466\r\n\r\n' + + '{"seq":10,"type":"event","event":"afterCompile","success":true,' + + '"body":{"script":{"handle":1,"type":"script","name":"dns.js",' + + '"id":34,"lineOffset":0,"columnOffset":0,"lineCount":241,' + + '"sourceStart":"(function(module, exports, require) {' + + 'var dns = process.binding(\'cares\')' + + ';\\nvar ne","sourceLength":6137,"scriptType":2,"compilationType"' + + ':0,"context":{"ref":0},"text":"dns.js (lines: 241)"}},"refs":' + + '[{"handle":0' + + ',"type":"context","text":"#"}],"running":true}' + + '\r\n\r\nContent-Length: 119\r\n\r\n' + + '{"seq":11,"type":"event","event":"scriptCollected","success":true' + + ',"body":{"script":{"id":26}},"refs":[],"running":true}'; p.execute(d); assert.strictEqual(resCount, 4); -var expectedConnections = 0; -var tests = []; +let expectedConnections = 0; +const tests = []; function addTest(cb) { expectedConnections++; tests.push(cb); @@ -102,9 +102,9 @@ addTest(function(client, done) { assert.ok(!err); console.error('got %d scripts', Object.keys(client.scripts).length); - var foundMainScript = false; - for (var k in client.scripts) { - var script = client.scripts[k]; + let foundMainScript = false; + for (const k in client.scripts) { + const script = client.scripts[k]; if (script && script.name === 'node.js') { foundMainScript = true; break; @@ -127,19 +127,19 @@ addTest(function(client, done) { }); -var connectCount = 0; -var script = 'setTimeout(function() { console.log("blah"); });' + - 'setInterval(function() {}, 1000000);'; +let connectCount = 0; +const script = 'setTimeout(function() { console.log("blah"); });' + + 'setInterval(function() {}, 1000000);'; -var nodeProcess; +let nodeProcess; function doTest(cb, done) { - var args = ['--debug=' + debugPort, '-e', script]; + const args = ['--debug=' + debugPort, '-e', script]; nodeProcess = spawn(process.execPath, args); nodeProcess.stdout.once('data', function(c) { console.log('>>> new node process: %d', nodeProcess.pid); - var failed = true; + let failed = true; try { process._debugProcess(nodeProcess.pid); failed = false; @@ -151,9 +151,9 @@ function doTest(cb, done) { console.log('>>> starting debugger session'); }); - var didTryConnect = false; + let didTryConnect = false; nodeProcess.stderr.setEncoding('utf8'); - var b = ''; + let b = ''; nodeProcess.stderr.on('data', function(data) { console.error('got stderr data %j', data); nodeProcess.stderr.resume(); diff --git a/test/fixtures/module-require-symlink/symlinked.js b/test/fixtures/module-require-symlink/symlinked.js index fea1cedb0aa4f8..657ef2662644c0 100644 --- a/test/fixtures/module-require-symlink/symlinked.js +++ b/test/fixtures/module-require-symlink/symlinked.js @@ -1,13 +1,13 @@ 'use strict'; -const assert = require('assert'); const common = require('../../common'); +const assert = require('assert'); +const foo = require('./foo'); const path = require('path'); const linkScriptTarget = path.join(common.fixturesDir, - '/module-require-symlink/symlinked.js'); + 'module-require-symlink', 'symlinked.js'); -var foo = require('./foo'); -assert.equal(foo.dep1.bar.version, 'CORRECT_VERSION'); -assert.equal(foo.dep2.bar.version, 'CORRECT_VERSION'); -assert.equal(__filename, linkScriptTarget); +assert.strictEqual(foo.dep1.bar.version, 'CORRECT_VERSION'); +assert.strictEqual(foo.dep2.bar.version, 'CORRECT_VERSION'); +assert.strictEqual(__filename, linkScriptTarget); assert(__filename in require.cache); diff --git a/test/fixtures/packages/invalid/index.js b/test/fixtures/packages/invalid/index.js new file mode 100644 index 00000000000000..014fa39dc365d1 --- /dev/null +++ b/test/fixtures/packages/invalid/index.js @@ -0,0 +1 @@ +exports.ok = 'ok'; diff --git a/test/fixtures/packages/invalid/package.json b/test/fixtures/packages/invalid/package.json new file mode 100644 index 00000000000000..004e1e20324524 --- /dev/null +++ b/test/fixtures/packages/invalid/package.json @@ -0,0 +1 @@ +{,} diff --git a/test/fixtures/raw-key.pem b/test/fixtures/raw-key.pem new file mode 100644 index 00000000000000..3e27f9f8870ad0 --- /dev/null +++ b/test/fixtures/raw-key.pem @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQChmQeFwsaomtQbw9Nm55Dn6KSR9bkY8PDroQUeTNa90BlIbhGs +KYm4l7bERaasFgOrkcQpk45fdDVYPjKxraZiGXXKjSIDYeDAIC/+CkwQKrejgCPm +Js4gV4g+npvwi1gVr2NAg7fkJOyEW2TDp4dsAD8qtG8Aml0C1hJXwFYmBwIDAQAB +AoGAVgZpAsQVjVwe3kj5GSbc9Rfbw/fTeXuKRWWKm/67soA9dVli/wt9zU62dPW/ +LIzrl0IZ8ygh+p6aZ0d1JTEUCPx7e0KocCmNg77i5AG0eK5i/KKjTWB4UGRDylfD +dnBXQc814bK+VB0mrcp46U/7tLGYkV2Kz/LiNpmxKwITS4ECQQDPoA6WIU87Eulq +OuVmJnFIQ2IR3SycVisO7TUq2MItq2U4BwsA3aQ4ehpP/uJdAfJEfwi2omRV5pGb +806pWkfPAkEAxz+igHS8tR11aLck71dD4BRBY7XZCUg6G4zmYYWsqj0yvM6c4Yn0 +HRcrZqFvV/xuMFphWEmMBhrqLvgy66yUSQJBALkei4LeRid0sDswMhMHGaAFvG4T +FtB5n8CaTPpb854GoKP42521ANP+QnGq36dvsdPStDEqz20rvA4hPLSQs08CQCV8 +eWxFikNg+XfsDQzilCiSZwMFcYHnjtckGSv75FJbFTKkhKuCMuVOOKIkeThKi8iZ +GHttyuRTKAASPjJM09ECQBrhlKJwYKuUDMp3qkLBgrXYqbFxZtkS2GeFMUfLcRlx +oMrTFEczz9lZ0huTuQYPeAAOY0Gd84mL0kQqTRTzNLs= +-----END RSA PRIVATE KEY----- diff --git a/test/inspector/test-inspector-stops-no-file.js b/test/inspector/test-inspector-stops-no-file.js new file mode 100644 index 00000000000000..d0f3a753464096 --- /dev/null +++ b/test/inspector/test-inspector-stops-no-file.js @@ -0,0 +1,15 @@ +'use strict'; +require('../common'); +const spawn = require('child_process').spawn; + +const child = spawn(process.execPath, + [ '--inspect', 'no-such-script.js' ], + { 'stdio': 'inherit' }); + +function signalHandler(value) { + child.kill(); + process.exit(1); +} + +process.on('SIGINT', signalHandler); +process.on('SIGTERM', signalHandler); diff --git a/test/internet/test-dns-ipv6.js b/test/internet/test-dns-ipv6.js index c1ccc4996eb24d..b2cdd14c53a60c 100644 --- a/test/internet/test-dns-ipv6.js +++ b/test/internet/test-dns-ipv6.js @@ -5,8 +5,6 @@ const dns = require('dns'); const net = require('net'); const isIPv6 = net.isIPv6; -let expected = 0; -let completed = 0; let running = false; const queue = []; @@ -17,7 +15,7 @@ if (!common.hasIPv6) { function TEST(f) { function next() { - var f = queue.shift(); + const f = queue.shift(); if (f) { running = true; console.log(f.name); @@ -27,11 +25,9 @@ function TEST(f) { function done() { running = false; - completed++; process.nextTick(next); } - expected++; queue.push(f); if (!running) { @@ -44,46 +40,46 @@ function checkWrap(req) { } TEST(function test_resolve6(done) { - var req = dns.resolve6('ipv6.google.com', function(err, ips) { - if (err) throw err; + const req = dns.resolve6('ipv6.google.com', + common.mustCall((err, ips) => { + assert.ifError(err); - assert.ok(ips.length > 0); + assert.ok(ips.length > 0); - for (var i = 0; i < ips.length; i++) { - assert.ok(isIPv6(ips[i])); - } + for (let i = 0; i < ips.length; i++) + assert.ok(isIPv6(ips[i])); - done(); - }); + done(); + })); checkWrap(req); }); TEST(function test_reverse_ipv6(done) { - var req = dns.reverse('2001:4860:4860::8888', function(err, domains) { - if (err) throw err; + const req = dns.reverse('2001:4860:4860::8888', + common.mustCall((err, domains) => { + assert.ifError(err); - assert.ok(domains.length > 0); + assert.ok(domains.length > 0); - for (var i = 0; i < domains.length; i++) { - assert.ok(domains[i]); - assert.ok(typeof domains[i] === 'string'); - } + for (let i = 0; i < domains.length; i++) + assert.ok(typeof domains[i] === 'string'); - done(); - }); + done(); + })); checkWrap(req); }); TEST(function test_lookup_ipv6_explicit(done) { - var req = dns.lookup('ipv6.google.com', 6, function(err, ip, family) { - if (err) throw err; - assert.ok(net.isIPv6(ip)); - assert.strictEqual(family, 6); + const req = dns.lookup('ipv6.google.com', 6, + common.mustCall((err, ip, family) => { + assert.ifError(err); + assert.ok(isIPv6(ip)); + assert.strictEqual(family, 6); - done(); - }); + done(); + })); checkWrap(req); }); @@ -103,24 +99,24 @@ TEST(function test_lookup_ipv6_implicit(done) { */ TEST(function test_lookup_ipv6_explicit_object(done) { - var req = dns.lookup('ipv6.google.com', { + const req = dns.lookup('ipv6.google.com', { family: 6 - }, function(err, ip, family) { - if (err) throw err; - assert.ok(net.isIPv6(ip)); + }, common.mustCall((err, ip, family) => { + assert.ifError(err); + assert.ok(isIPv6(ip)); assert.strictEqual(family, 6); done(); - }); + })); checkWrap(req); }); TEST(function test_lookup_ipv6_hint(done) { - var req = dns.lookup('www.google.com', { + const req = dns.lookup('www.google.com', { family: 6, hints: dns.V4MAPPED - }, function(err, ip, family) { + }, common.mustCall((err, ip, family) => { if (err) { // FreeBSD does not support V4MAPPED if (common.isFreeBSD) { @@ -130,41 +126,43 @@ TEST(function test_lookup_ipv6_hint(done) { assert.ok(/getaddrinfo EAI_BADFLAGS/.test(err.message)); done(); return; - } else { - throw err; } + + assert.ifError(err); } - assert.ok(net.isIPv6(ip)); + + assert.ok(isIPv6(ip)); assert.strictEqual(family, 6); done(); - }); + })); checkWrap(req); }); TEST(function test_lookup_ip_ipv6(done) { - var req = dns.lookup('::1', function(err, ip, family) { - if (err) throw err; - assert.ok(net.isIPv6(ip)); - assert.strictEqual(family, 6); + const req = dns.lookup('::1', + common.mustCall((err, ip, family) => { + assert.ifError(err); + assert.ok(isIPv6(ip)); + assert.strictEqual(family, 6); - done(); - }); + done(); + })); checkWrap(req); }); TEST(function test_lookup_all_ipv6(done) { - var req = dns.lookup( + const req = dns.lookup( 'www.google.com', {all: true, family: 6}, - function(err, ips) { - if (err) throw err; + common.mustCall((err, ips) => { + assert.ifError(err); assert.ok(Array.isArray(ips)); assert.ok(ips.length > 0); - ips.forEach(function(ip) { + ips.forEach((ip) => { assert.ok(isIPv6(ip.address), 'Invalid IPv6: ' + ip.address.toString()); assert.strictEqual(ip.family, 6); @@ -172,24 +170,25 @@ TEST(function test_lookup_all_ipv6(done) { done(); } - ); + )); checkWrap(req); }); TEST(function test_lookupservice_ip_ipv6(done) { - var req = dns.lookupService('::1', 80, function(err, host, service) { - if (err) { - // Not skipping the test, rather checking an alternative result, - // i.e. that ::1 may not be configured (e.g. in /etc/hosts) - assert.strictEqual(err.code, 'ENOTFOUND'); - return done(); - } - assert.equal(typeof host, 'string'); - assert(host); - assert(['http', 'www', '80'].includes(service)); - done(); - }); + const req = dns.lookupService('::1', 80, + common.mustCall((err, host, service) => { + if (err) { + // Not skipping the test, rather checking an alternative result, + // i.e. that ::1 may not be configured (e.g. in /etc/hosts) + assert.strictEqual(err.code, 'ENOTFOUND'); + return done(); + } + assert.strictEqual(typeof host, 'string'); + assert(host); + assert(['http', 'www', '80'].includes(service)); + done(); + })); checkWrap(req); }); @@ -206,9 +205,3 @@ TEST(function test_lookupservice_ip_ipv6(done) { checkWrap(req); }); */ - -process.on('exit', function() { - console.log(completed + ' tests completed'); - assert.equal(running, false); - assert.strictEqual(expected, completed); -}); diff --git a/test/internet/test-http-dns-fail.js b/test/internet/test-http-dns-fail.js index c83b89f8ccd37e..37abe6ed14b70b 100644 --- a/test/internet/test-http-dns-fail.js +++ b/test/internet/test-http-dns-fail.js @@ -5,34 +5,25 @@ */ const common = require('../common'); -var assert = require('assert'); -var http = require('http'); - -var hadError = 0; +const assert = require('assert'); +const http = require('http'); function httpreq(count) { - if (1 < count) return; + if (count > 1) return; - var req = http.request({ + const req = http.request({ host: 'not-a-real-domain-name.nobody-would-register-this-as-a-tld', port: 80, path: '/', method: 'GET' }, common.fail); - req.on('error', function(e) { - console.log(e.message); + req.on('error', common.mustCall((e) => { assert.strictEqual(e.code, 'ENOTFOUND'); - hadError++; httpreq(count + 1); - }); + })); req.end(); } httpreq(0); - - -process.on('exit', function() { - assert.equal(2, hadError); -}); diff --git a/test/known_issues/test-vm-deleting-property.js b/test/known_issues/test-vm-deleting-property.js new file mode 100644 index 00000000000000..cda3371a33bf16 --- /dev/null +++ b/test/known_issues/test-vm-deleting-property.js @@ -0,0 +1,15 @@ +'use strict'; +// Refs: https://github.com/nodejs/node/issues/6287 + +require('../common'); +const assert = require('assert'); +const vm = require('vm'); + +const context = vm.createContext(); +const res = vm.runInContext(` + this.x = 'prop'; + delete this.x; + Object.getOwnPropertyDescriptor(this, 'x'); +`, context); + +assert.strictEqual(res.value, undefined); diff --git a/test/message/testcfg.py b/test/message/testcfg.py index 7183ab333d8274..3c668459079f0a 100644 --- a/test/message/testcfg.py +++ b/test/message/testcfg.py @@ -127,8 +127,7 @@ def ListTests(self, current_path, path, arch, mode): file_path = file_prefix + ".js" output_path = file_prefix + ".out" if not exists(output_path): - print "Could not find %s" % output_path - continue + raise Exception("Could not find %s" % output_path) result.append(MessageTestCase(test, file_path, output_path, arch, mode, self.context, self)) return result diff --git a/test/parallel/test-beforeexit-event.js b/test/parallel/test-beforeexit-event.js index 4decbcf9f921f3..ef94da76af3883 100644 --- a/test/parallel/test-beforeexit-event.js +++ b/test/parallel/test-beforeexit-event.js @@ -1,42 +1,26 @@ 'use strict'; -require('../common'); -var assert = require('assert'); -var net = require('net'); -var revivals = 0; -var deaths = 0; +const common = require('../common'); +const net = require('net'); -process.on('beforeExit', function() { deaths++; }); - -process.once('beforeExit', tryImmediate); +process.once('beforeExit', common.mustCall(tryImmediate)); function tryImmediate() { - console.log('set immediate'); - setImmediate(function() { - revivals++; - process.once('beforeExit', tryTimer); - }); + setImmediate(common.mustCall(() => { + process.once('beforeExit', common.mustCall(tryTimer)); + })); } function tryTimer() { - console.log('set a timeout'); - setTimeout(function() { - console.log('timeout cb, do another once beforeExit'); - revivals++; - process.once('beforeExit', tryListen); - }, 1); + setTimeout(common.mustCall(() => { + process.once('beforeExit', common.mustCall(tryListen)); + }), 1); } function tryListen() { - console.log('create a server'); net.createServer() .listen(0) - .on('listening', function() { - revivals++; + .on('listening', common.mustCall(function() { this.close(); - }); + process.on('beforeExit', common.mustCall(() => {})); + })); } - -process.on('exit', function() { - assert.strictEqual(4, deaths); - assert.strictEqual(3, revivals); -}); diff --git a/test/parallel/test-buffer-arraybuffer.js b/test/parallel/test-buffer-arraybuffer.js index f40c43939f975e..4353af17ef1d3a 100644 --- a/test/parallel/test-buffer-arraybuffer.js +++ b/test/parallel/test-buffer-arraybuffer.js @@ -13,9 +13,9 @@ const buf = Buffer.from(ab); assert.ok(buf instanceof Buffer); -assert.equal(buf.parent, buf.buffer); -assert.equal(buf.buffer, ab); -assert.equal(buf.length, ab.byteLength); +assert.strictEqual(buf.parent, buf.buffer); +assert.strictEqual(buf.buffer, ab); +assert.strictEqual(buf.length, ab.byteLength); buf.fill(0xC); @@ -44,7 +44,7 @@ assert.throws(function() { }, TypeError); // write{Double,Float}{LE,BE} with noAssert should not crash, cf. #3766 -var b = Buffer.allocUnsafe(1); +const b = Buffer.allocUnsafe(1); b.writeFloatLE(11.11, 0, true); b.writeFloatBE(11.11, 0, true); b.writeDoubleLE(11.11, 0, true); diff --git a/test/parallel/test-buffer-creation-regression.js b/test/parallel/test-buffer-creation-regression.js deleted file mode 100644 index 650fbf48f12ae6..00000000000000 --- a/test/parallel/test-buffer-creation-regression.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -const common = require('../common'); -const assert = require('assert'); - -function test(arrayBuffer, offset, length) { - const uint8Array = new Uint8Array(arrayBuffer, offset, length); - for (let i = 0; i < length; i += 1) { - uint8Array[i] = 1; - } - - const buffer = Buffer.from(arrayBuffer, offset, length); - for (let i = 0; i < length; i += 1) { - assert.strictEqual(buffer[i], 1); - } -} - -const acceptableOOMErrors = [ - 'Array buffer allocation failed', - 'Invalid array buffer length' -]; - -const testCases = [ - [200, 50, 100], - [4294967296 /* 1 << 32 */, 2147483648 /* 1 << 31 */, 1000], - [8589934592 /* 1 << 33 */, 4294967296 /* 1 << 32 */, 1000] -]; - -for (let index = 0, arrayBuffer; index < testCases.length; index += 1) { - const [size, offset, length] = testCases[index]; - - try { - arrayBuffer = new ArrayBuffer(size); - } catch (e) { - if (e instanceof RangeError && acceptableOOMErrors.includes(e.message)) - return common.skip(`Unable to allocate ${size} bytes for ArrayBuffer`); - throw e; - } - - test(arrayBuffer, offset, length); -} diff --git a/test/parallel/test-buffer-fill.js b/test/parallel/test-buffer-fill.js index 4272d686940cc7..eecb14abb06001 100644 --- a/test/parallel/test-buffer-fill.js +++ b/test/parallel/test-buffer-fill.js @@ -2,13 +2,11 @@ require('../common'); const assert = require('assert'); -const os = require('os'); const SIZE = 28; const buf1 = Buffer.allocUnsafe(SIZE); const buf2 = Buffer.allocUnsafe(SIZE); - // Default encoding testBufs('abc'); testBufs('\u0222aa'); @@ -112,8 +110,7 @@ testBufs('\u0222aa', 8, 1, 'ucs2'); testBufs('a\u0234b\u0235c\u0236', 4, -1, 'ucs2'); testBufs('a\u0234b\u0235c\u0236', 4, 1, 'ucs2'); testBufs('a\u0234b\u0235c\u0236', 12, 1, 'ucs2'); -assert.strictEqual(Buffer.allocUnsafe(1).fill('\u0222', 'ucs2')[0], - os.endianness() === 'LE' ? 0x22 : 0x02); +assert.strictEqual(Buffer.allocUnsafe(1).fill('\u0222', 'ucs2')[0], 0x22); // HEX @@ -259,15 +256,6 @@ function writeToFill(string, offset, end, encoding) { } } while (offset < buf2.length); - // Correction for UCS2 operations. - if (os.endianness() === 'BE' && encoding === 'ucs2') { - for (var i = 0; i < buf2.length; i += 2) { - var tmp = buf2[i]; - buf2[i] = buf2[i + 1]; - buf2[i + 1] = tmp; - } - } - return buf2; } @@ -406,3 +394,38 @@ assert.throws(() => { }); buf.fill(''); }, /^RangeError: out of range index$/); + +assert.deepStrictEqual( + Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'), + Buffer.from('61006200610062006100620061006200', 'hex')); + +assert.deepStrictEqual( + Buffer.allocUnsafeSlow(15).fill('ab', 'utf16le'), + Buffer.from('610062006100620061006200610062', 'hex')); + +assert.deepStrictEqual( + Buffer.allocUnsafeSlow(16).fill('ab', 'utf16le'), + Buffer.from('61006200610062006100620061006200', 'hex')); +assert.deepStrictEqual( + Buffer.allocUnsafeSlow(16).fill('a', 'utf16le'), + Buffer.from('61006100610061006100610061006100', 'hex')); + +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('a', 'utf16le').toString('utf16le'), + 'a'.repeat(8)); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('a', 'latin1').toString('latin1'), + 'a'.repeat(16)); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('a', 'utf8').toString('utf8'), + 'a'.repeat(16)); + +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('Љ', 'utf16le').toString('utf16le'), + 'Љ'.repeat(8)); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('Љ', 'latin1').toString('latin1'), + '\t'.repeat(16)); +assert.strictEqual( + Buffer.allocUnsafeSlow(16).fill('Љ', 'utf8').toString('utf8'), + 'Љ'.repeat(8)); diff --git a/test/parallel/test-buffer-regression-649.js b/test/parallel/test-buffer-regression-649.js index b11e4a50e5d447..ab7228e84c1c13 100644 --- a/test/parallel/test-buffer-regression-649.js +++ b/test/parallel/test-buffer-regression-649.js @@ -6,8 +6,13 @@ const SlowBuffer = require('buffer').SlowBuffer; // Regression test for https://github.com/nodejs/node/issues/649. const len = 1422561062959; -assert.throws(() => Buffer(len).toString('utf8')); -assert.throws(() => SlowBuffer(len).toString('utf8')); -assert.throws(() => Buffer.alloc(len).toString('utf8')); -assert.throws(() => Buffer.allocUnsafe(len).toString('utf8')); -assert.throws(() => Buffer.allocUnsafeSlow(len).toString('utf8')); +const lenLimitMsg = new RegExp('^RangeError: (Invalid typed array length' + + '|Array buffer allocation failed' + + '|Invalid array buffer length)$'); + +assert.throws(() => Buffer(len).toString('utf8'), lenLimitMsg); +assert.throws(() => SlowBuffer(len).toString('utf8'), lenLimitMsg); +assert.throws(() => Buffer.alloc(len).toString('utf8'), lenLimitMsg); +assert.throws(() => Buffer.allocUnsafe(len).toString('utf8'), lenLimitMsg); +assert.throws(() => Buffer.allocUnsafeSlow(len).toString('utf8'), + lenLimitMsg); diff --git a/test/parallel/test-child-process-detached.js b/test/parallel/test-child-process-detached.js index d550401fae79e1..43cae6eeb02a88 100644 --- a/test/parallel/test-child-process-detached.js +++ b/test/parallel/test-child-process-detached.js @@ -18,7 +18,7 @@ process.on('exit', function() { assert.notStrictEqual(persistentPid, -1); assert.throws(function() { process.kill(child.pid); - }); + }, /^Error: kill ESRCH$/); assert.doesNotThrow(function() { process.kill(persistentPid); }); diff --git a/test/parallel/test-child-process-exec-buffer.js b/test/parallel/test-child-process-exec-buffer.js index 47879c05b2ce97..092304879ec48c 100644 --- a/test/parallel/test-child-process-exec-buffer.js +++ b/test/parallel/test-child-process-exec-buffer.js @@ -1,22 +1,24 @@ 'use strict'; const common = require('../common'); -var assert = require('assert'); -var exec = require('child_process').exec; -var os = require('os'); -var str = 'hello'; +const assert = require('assert'); +const exec = require('child_process').exec; +const os = require('os'); +const str = 'hello'; // default encoding exec('echo ' + str, common.mustCall(function(err, stdout, stderr) { - assert.ok('string', typeof stdout, 'Expected stdout to be a string'); - assert.ok('string', typeof stderr, 'Expected stderr to be a string'); - assert.equal(str + os.EOL, stdout); + assert.strictEqual(typeof stdout, 'string', 'Expected stdout to be a string'); + assert.strictEqual(typeof stderr, 'string', 'Expected stderr to be a string'); + assert.strictEqual(str + os.EOL, stdout); })); // no encoding (Buffers expected) exec('echo ' + str, { encoding: null }, common.mustCall(function(err, stdout, stderr) { - assert.ok(stdout instanceof Buffer, 'Expected stdout to be a Buffer'); - assert.ok(stderr instanceof Buffer, 'Expected stderr to be a Buffer'); - assert.equal(str + os.EOL, stdout.toString()); + assert.strictEqual(stdout instanceof Buffer, true, + 'Expected stdout to be a Buffer'); + assert.strictEqual(stderr instanceof Buffer, true, + 'Expected stderr to be a Buffer'); + assert.strictEqual(str + os.EOL, stdout.toString()); })); diff --git a/test/parallel/test-child-process-fork-and-spawn.js b/test/parallel/test-child-process-fork-and-spawn.js index 50615ecb79d0c6..5807147a1c947d 100644 --- a/test/parallel/test-child-process-fork-and-spawn.js +++ b/test/parallel/test-child-process-fork-and-spawn.js @@ -1,8 +1,8 @@ 'use strict'; const common = require('../common'); -var assert = require('assert'); -var spawn = require('child_process').spawn; -var fork = require('child_process').fork; +const assert = require('assert'); +const spawn = require('child_process').spawn; +const fork = require('child_process').fork; // Fork, then spawn. The spawned process should not hang. switch (process.argv[2] || '') { @@ -16,10 +16,9 @@ switch (process.argv[2] || '') { case 'spawn': break; default: - assert(0); + common.fail(); } function checkExit(statusCode) { - assert.equal(statusCode, 0); - process.nextTick(process.exit); + assert.strictEqual(statusCode, 0); } diff --git a/test/parallel/test-child-process-stdio-big-write-end.js b/test/parallel/test-child-process-stdio-big-write-end.js index 4b0f9d2cf3216f..4c9f4159d0d8bc 100644 --- a/test/parallel/test-child-process-stdio-big-write-end.js +++ b/test/parallel/test-child-process-stdio-big-write-end.js @@ -23,7 +23,7 @@ function parent() { n += c; }); child.stdout.on('end', function() { - assert.equal(+n, sent); + assert.strictEqual(+n, sent); console.log('ok'); }); diff --git a/test/parallel/test-child-process-stdout-flush-exit.js b/test/parallel/test-child-process-stdout-flush-exit.js index b76a7cb5e5a8e2..9db74b51ce5864 100644 --- a/test/parallel/test-child-process-stdout-flush-exit.js +++ b/test/parallel/test-child-process-stdout-flush-exit.js @@ -1,23 +1,23 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); +const assert = require('assert'); // if child process output to console and exit if (process.argv[2] === 'child') { console.log('hello'); - for (var i = 0; i < 200; i++) { + for (let i = 0; i < 200; i++) { console.log('filler'); } console.log('goodbye'); process.exit(0); } else { // parent process - var spawn = require('child_process').spawn; + const spawn = require('child_process').spawn; // spawn self as child - var child = spawn(process.argv[0], [process.argv[1], 'child']); + const child = spawn(process.argv[0], [process.argv[1], 'child']); - var stdout = ''; + let stdout = ''; child.stderr.setEncoding('utf8'); child.stderr.on('data', function(data) { @@ -32,7 +32,7 @@ if (process.argv[2] === 'child') { }); child.on('close', common.mustCall(function() { - assert.equal(stdout.slice(0, 6), 'hello\n'); - assert.equal(stdout.slice(stdout.length - 8), 'goodbye\n'); + assert.strictEqual(stdout.slice(0, 6), 'hello\n'); + assert.strictEqual(stdout.slice(stdout.length - 8), 'goodbye\n'); })); } diff --git a/test/parallel/test-cluster-send-handle-twice.js b/test/parallel/test-cluster-send-handle-twice.js index f1552d79265a0c..172a5563f306f5 100644 --- a/test/parallel/test-cluster-send-handle-twice.js +++ b/test/parallel/test-cluster-send-handle-twice.js @@ -14,7 +14,7 @@ if (cluster.isMaster) { for (var i = 0; i < workers.toStart; ++i) { var worker = cluster.fork(); worker.on('exit', function(code, signal) { - assert.equal(code, 0, 'Worker exited with an error code'); + assert.strictEqual(code, 0, 'Worker exited with an error code'); assert(!signal, 'Worker exited by a signal'); }); } diff --git a/test/parallel/test-cluster-worker-death.js b/test/parallel/test-cluster-worker-death.js index 8bbf46de568eb0..ac32705106e03c 100644 --- a/test/parallel/test-cluster-worker-death.js +++ b/test/parallel/test-cluster-worker-death.js @@ -8,10 +8,10 @@ if (!cluster.isMaster) { } else { var worker = cluster.fork(); worker.on('exit', common.mustCall(function(exitCode, signalCode) { - assert.equal(exitCode, 42); - assert.equal(signalCode, null); + assert.strictEqual(exitCode, 42); + assert.strictEqual(signalCode, null); })); cluster.on('exit', common.mustCall(function(worker_) { - assert.equal(worker_, worker); + assert.strictEqual(worker_, worker); })); } diff --git a/test/parallel/test-cluster-worker-destroy.js b/test/parallel/test-cluster-worker-destroy.js index c802177530e4af..ca3ac77e7b25cc 100644 --- a/test/parallel/test-cluster-worker-destroy.js +++ b/test/parallel/test-cluster-worker-destroy.js @@ -8,6 +8,7 @@ */ const common = require('../common'); +const assert = require('assert'); var cluster = require('cluster'); var worker1, worker2; @@ -26,7 +27,8 @@ if (cluster.isMaster) { cluster.worker.destroy(); }); - cluster.worker.disconnect(); + const w = cluster.worker.disconnect(); + assert.strictEqual(w, cluster.worker, 'did not return a reference'); } else { // Call destroy when worker is not disconnected yet cluster.worker.destroy(); diff --git a/test/parallel/test-cluster-worker-disconnect.js b/test/parallel/test-cluster-worker-disconnect.js index 4e17a7d475e3d0..684fd5541eac55 100644 --- a/test/parallel/test-cluster-worker-disconnect.js +++ b/test/parallel/test-cluster-worker-disconnect.js @@ -40,7 +40,8 @@ if (cluster.isWorker) { // Disconnect worker when it is ready worker.once('listening', common.mustCall(() => { - worker.disconnect(); + const w = worker.disconnect(); + assert.strictEqual(worker, w, 'did not return a reference'); })); // Check cluster events diff --git a/test/parallel/test-cluster-worker-init.js b/test/parallel/test-cluster-worker-init.js index 3b82866d1b14eb..eaa9746c5f99a3 100644 --- a/test/parallel/test-cluster-worker-init.js +++ b/test/parallel/test-cluster-worker-init.js @@ -13,7 +13,8 @@ if (cluster.isMaster) { worker.on('message', common.mustCall((message) => { assert.strictEqual(message, true, 'did not receive expected message'); - worker.disconnect(); + const w = worker.disconnect(); + assert.strictEqual(worker, w, 'did not return a reference'); })); worker.on('online', () => { diff --git a/test/parallel/test-crypto-authenticated.js b/test/parallel/test-crypto-authenticated.js index 8eab91e549dfa7..4bed5aa665b64d 100644 --- a/test/parallel/test-crypto-authenticated.js +++ b/test/parallel/test-crypto-authenticated.js @@ -352,7 +352,7 @@ for (const i in TEST_CASES) { let msg = decrypt.update(test.ct, 'hex', outputEncoding); if (!test.tampered) { msg += decrypt.final(outputEncoding); - assert.equal(msg, test.plain); + assert.strictEqual(msg, test.plain); } else { // assert that final throws if input data could not be verified! assert.throws(function() { decrypt.final('ascii'); }, / auth/); diff --git a/test/parallel/test-crypto-cipher-decipher.js b/test/parallel/test-crypto-cipher-decipher.js index c63bcd6f9e2695..e53f02edfa0c86 100644 --- a/test/parallel/test-crypto-cipher-decipher.js +++ b/test/parallel/test-crypto-cipher-decipher.js @@ -1,6 +1,5 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); if (!common.hasCrypto) { common.skip('missing crypto'); @@ -10,21 +9,22 @@ if (common.hasFipsCrypto) { common.skip('not supported in FIPS mode'); return; } -var crypto = require('crypto'); +const crypto = require('crypto'); +const assert = require('assert'); function testCipher1(key) { // Test encryption and decryption - var plaintext = 'Keep this a secret? No! Tell everyone about node.js!'; - var cipher = crypto.createCipher('aes192', key); + const plaintext = 'Keep this a secret? No! Tell everyone about node.js!'; + const cipher = crypto.createCipher('aes192', key); // encrypt plaintext which is in utf8 format // to a ciphertext which will be in hex - var ciph = cipher.update(plaintext, 'utf8', 'hex'); + let ciph = cipher.update(plaintext, 'utf8', 'hex'); // Only use binary or hex, not base64. ciph += cipher.final('hex'); - var decipher = crypto.createDecipher('aes192', key); - var txt = decipher.update(ciph, 'hex', 'utf8'); + const decipher = crypto.createDecipher('aes192', key); + let txt = decipher.update(ciph, 'hex', 'utf8'); txt += decipher.final('utf8'); assert.strictEqual(txt, plaintext, 'encryption and decryption'); @@ -33,11 +33,11 @@ function testCipher1(key) { // NB: In real life, it's not guaranteed that you can get all of it // in a single read() like this. But in this case, we know it's // quite small, so there's no harm. - var cStream = crypto.createCipher('aes192', key); + const cStream = crypto.createCipher('aes192', key); cStream.end(plaintext); ciph = cStream.read(); - var dStream = crypto.createDecipher('aes192', key); + const dStream = crypto.createDecipher('aes192', key); dStream.end(ciph); txt = dStream.read().toString('utf8'); @@ -48,19 +48,19 @@ function testCipher1(key) { function testCipher2(key) { // encryption and decryption with Base64 // reported in https://github.com/joyent/node/issues/738 - var plaintext = + const plaintext = '32|RmVZZkFUVmpRRkp0TmJaUm56ZU9qcnJkaXNNWVNpTTU*|iXmckfRWZBGWWELw' + 'eCBsThSsfUHLeRe0KCsK8ooHgxie0zOINpXxfZi/oNG7uq9JWFVCk70gfzQH8ZUJ' + 'jAfaFg**'; - var cipher = crypto.createCipher('aes256', key); + const cipher = crypto.createCipher('aes256', key); // encrypt plaintext which is in utf8 format // to a ciphertext which will be in Base64 - var ciph = cipher.update(plaintext, 'utf8', 'base64'); + let ciph = cipher.update(plaintext, 'utf8', 'base64'); ciph += cipher.final('base64'); - var decipher = crypto.createDecipher('aes256', key); - var txt = decipher.update(ciph, 'base64', 'utf8'); + const decipher = crypto.createDecipher('aes256', key); + let txt = decipher.update(ciph, 'base64', 'utf8'); txt += decipher.final('utf8'); assert.strictEqual(txt, plaintext, 'encryption and decryption with Base64'); @@ -119,12 +119,12 @@ testCipher2(Buffer.from('0123456789abcdef')); const key = '0123456789abcdef'; const plaintext = 'Top secret!!!'; const c = crypto.createCipher('aes192', key); - var ciph = c.update(plaintext, 'utf16le', 'base64'); + let ciph = c.update(plaintext, 'utf16le', 'base64'); ciph += c.final('base64'); - var decipher = crypto.createDecipher('aes192', key); + let decipher = crypto.createDecipher('aes192', key); - var txt; + let txt; assert.doesNotThrow(() => txt = decipher.update(ciph, 'base64', 'ucs2')); assert.doesNotThrow(() => txt += decipher.final('ucs2')); assert.strictEqual(txt, plaintext, 'decrypted result in ucs2'); diff --git a/test/parallel/test-crypto-fips.js b/test/parallel/test-crypto-fips.js index 55b542ca9ead83..24b1af70b70329 100644 --- a/test/parallel/test-crypto-fips.js +++ b/test/parallel/test-crypto-fips.js @@ -53,7 +53,7 @@ function testHelper(stream, args, expectedOutput, cmd, env) { assert.notEqual(-1, response.indexOf(expectedOutput)); } else { // Normal path where we expect either FIPS enabled or disabled. - assert.equal(expectedOutput, response); + assert.strictEqual(expectedOutput, Number(response)); } childOk(child); } diff --git a/test/parallel/test-crypto-hmac.js b/test/parallel/test-crypto-hmac.js index 7c550be4c2ebf3..5307ea4f6f9e05 100644 --- a/test/parallel/test-crypto-hmac.js +++ b/test/parallel/test-crypto-hmac.js @@ -13,7 +13,7 @@ var h1 = crypto.createHmac('sha1', 'Node') .update('some data') .update('to hmac') .digest('hex'); -assert.equal(h1, '19fd6e1ba73d9ed2224dd5094a71babe85d9a892', 'test HMAC'); +assert.strictEqual(h1, '19fd6e1ba73d9ed2224dd5094a71babe85d9a892', 'test HMAC'); // Test HMAC (Wikipedia Test Cases) var wikipedia = [ @@ -67,9 +67,9 @@ for (let i = 0, l = wikipedia.length; i < l; i++) { const result = crypto.createHmac(hash, wikipedia[i]['key']) .update(wikipedia[i]['data']) .digest('hex'); - assert.equal(wikipedia[i]['hmac'][hash], - result, - 'Test HMAC-' + hash + ': Test case ' + (i + 1) + ' wikipedia'); + assert.strictEqual(wikipedia[i]['hmac'][hash], + result, + `Test HMAC-${hash}: Test case ${i + 1} wikipedia`); } } @@ -233,10 +233,10 @@ for (let i = 0, l = rfc4231.length; i < l; i++) { result = result.substr(0, 32); // first 128 bits == 32 hex chars strRes = strRes.substr(0, 32); } - assert.equal(rfc4231[i]['hmac'][hash], - result, - 'Test HMAC-' + hash + ': Test case ' + (i + 1) + ' rfc 4231'); - assert.equal(strRes, result, 'Should get same result from stream'); + assert.strictEqual(rfc4231[i]['hmac'][hash], + result, + `Test HMAC-${hash}: Test case ${i + 1} rfc 4231`); + assert.strictEqual(strRes, result, 'Should get same result from stream'); } } @@ -356,7 +356,7 @@ if (!common.hasFipsCrypto) { crypto.createHmac('md5', rfc2202_md5[i]['key']) .update(rfc2202_md5[i]['data']) .digest('hex'), - 'Test HMAC-MD5 : Test case ' + (i + 1) + ' rfc 2202' + `Test HMAC-MD5 : Test case ${i + 1} rfc 2202` ); } } @@ -366,6 +366,6 @@ for (let i = 0, l = rfc2202_sha1.length; i < l; i++) { crypto.createHmac('sha1', rfc2202_sha1[i]['key']) .update(rfc2202_sha1[i]['data']) .digest('hex'), - 'Test HMAC-SHA1 : Test case ' + (i + 1) + ' rfc 2202' + `Test HMAC-SHA1 : Test case ${i + 1} rfc 2202` ); } diff --git a/test/parallel/test-crypto-random.js b/test/parallel/test-crypto-random.js index 6866c8c08186ee..a3e9ab26687f09 100644 --- a/test/parallel/test-crypto-random.js +++ b/test/parallel/test-crypto-random.js @@ -1,11 +1,11 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); if (!common.hasCrypto) { common.skip('missing crypto'); return; } +const assert = require('assert'); const crypto = require('crypto'); crypto.DEFAULT_ENCODING = 'buffer'; @@ -13,25 +13,16 @@ crypto.DEFAULT_ENCODING = 'buffer'; // bump, we register a lot of exit listeners process.setMaxListeners(256); -[crypto.randomBytes, - crypto.pseudoRandomBytes -].forEach(function(f) { - [-1, - undefined, - null, - false, - true, - {}, - [] - ].forEach(function(value) { - assert.throws(function() { f(value); }); - assert.throws(function() { f(value, function() {}); }); +[crypto.randomBytes, crypto.pseudoRandomBytes].forEach(function(f) { + [-1, undefined, null, false, true, {}, []].forEach(function(value) { + assert.throws(function() { f(value); }, TypeError); + assert.throws(function() { f(value, function() {}); }, TypeError); }); [0, 1, 2, 4, 16, 256, 1024].forEach(function(len) { f(len, common.mustCall(function(ex, buf) { - assert.strictEqual(null, ex); - assert.strictEqual(len, buf.length); + assert.strictEqual(ex, null); + assert.strictEqual(buf.length, len); assert.ok(Buffer.isBuffer(buf)); })); }); diff --git a/test/parallel/test-debug-port-from-cmdline.js b/test/parallel/test-debug-port-from-cmdline.js index e1125507c208ee..abec53cbd3c83a 100644 --- a/test/parallel/test-debug-port-from-cmdline.js +++ b/test/parallel/test-debug-port-from-cmdline.js @@ -42,7 +42,7 @@ function assertOutputLines() { 'Debugger listening on 127.0.0.1:' + debugPort, ]; - assert.equal(outputLines.length, expectedLines.length); + assert.strictEqual(outputLines.length, expectedLines.length); for (var i = 0; i < expectedLines.length; i++) assert(expectedLines[i].includes(outputLines[i])); } diff --git a/test/parallel/test-debug-prompt.js b/test/parallel/test-debug-prompt.js index fdc3b4c27f4d45..82120859c7ca8a 100644 --- a/test/parallel/test-debug-prompt.js +++ b/test/parallel/test-debug-prompt.js @@ -1,13 +1,14 @@ 'use strict'; -const assert = require('assert'); -const common = require('../common'); +require('../common'); const spawn = require('child_process').spawn; const proc = spawn(process.execPath, ['debug', 'foo']); proc.stdout.setEncoding('utf8'); -proc.stdout.once('data', common.mustCall((data) => { - assert.strictEqual(data, 'debug> '); - proc.kill(); -})); +let output = ''; +proc.stdout.on('data', (data) => { + output += data; + if (output.includes('debug> ')) + proc.kill(); +}); diff --git a/test/parallel/test-dgram-bind-default-address.js b/test/parallel/test-dgram-bind-default-address.js old mode 100644 new mode 100755 index b2bd72f6db6a7c..142a5134c013c3 --- a/test/parallel/test-dgram-bind-default-address.js +++ b/test/parallel/test-dgram-bind-default-address.js @@ -1,7 +1,7 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var dgram = require('dgram'); +const common = require('../common'); +const assert = require('assert'); +const dgram = require('dgram'); // skip test in FreeBSD jails since 0.0.0.0 will resolve to default interface if (common.inFreeBSDJail) { @@ -13,7 +13,7 @@ dgram.createSocket('udp4').bind(0, common.mustCall(function() { assert.strictEqual(typeof this.address().port, 'number'); assert.ok(isFinite(this.address().port)); assert.ok(this.address().port > 0); - assert.equal(this.address().address, '0.0.0.0'); + assert.strictEqual(this.address().address, '0.0.0.0'); this.close(); })); @@ -26,9 +26,9 @@ dgram.createSocket('udp6').bind(0, common.mustCall(function() { assert.strictEqual(typeof this.address().port, 'number'); assert.ok(isFinite(this.address().port)); assert.ok(this.address().port > 0); - var address = this.address().address; + let address = this.address().address; if (address === '::ffff:0.0.0.0') address = '::'; - assert.equal(address, '::'); + assert.strictEqual(address, '::'); this.close(); })); diff --git a/test/parallel/test-dgram-exclusive-implicit-bind.js b/test/parallel/test-dgram-exclusive-implicit-bind.js index c8799cf058b99e..97fd6bed5d6e33 100644 --- a/test/parallel/test-dgram-exclusive-implicit-bind.js +++ b/test/parallel/test-dgram-exclusive-implicit-bind.js @@ -20,10 +20,10 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -var common = require('../common'); -var assert = require('assert'); -var cluster = require('cluster'); -var dgram = require('dgram'); +const common = require('../common'); +const assert = require('assert'); +const cluster = require('cluster'); +const dgram = require('dgram'); // Without an explicit bind, send() causes an implicit bind, which always // generate a unique per-socket ephemeral port. An explicit bind to a port @@ -40,17 +40,21 @@ var dgram = require('dgram'); // with ENOTSUP. if (cluster.isMaster) { - var pass; var messages = 0; - var ports = {}; - - process.on('exit', function() { - assert.strictEqual(pass, true); - }); + const ports = {}; + const pids = []; var target = dgram.createSocket('udp4'); + const done = common.mustCall(function() { + cluster.disconnect(); + target.close(); + }); + target.on('message', function(buf, rinfo) { + if (pids.includes(buf.toString())) + return; + pids.push(buf.toString()); messages++; ports[rinfo.port] = true; @@ -63,12 +67,6 @@ if (cluster.isMaster) { assert.strictEqual(Object.keys(ports).length, 3); done(); } - - function done() { - pass = true; - cluster.disconnect(); - target.close(); - } }); target.on('listening', function() { @@ -85,7 +83,12 @@ if (cluster.isMaster) { return; } -var source = dgram.createSocket('udp4'); +const source = dgram.createSocket('udp4'); +var interval; + +source.on('close', function() { + clearInterval(interval); +}); if (process.env.BOUND === 'y') { source.bind(0); @@ -96,4 +99,7 @@ if (process.env.BOUND === 'y') { source.unref(); } -source.send(Buffer.from('abc'), 0, 3, common.PORT, '127.0.0.1'); +const buf = Buffer.from(process.pid.toString()); +interval = setInterval(() => { + source.send(buf, common.PORT, '127.0.0.1'); +}, 1).unref(); diff --git a/test/parallel/test-dgram-send-callback-multi-buffer.js b/test/parallel/test-dgram-send-callback-multi-buffer.js index a60d42cc45d49e..f77b5618450095 100644 --- a/test/parallel/test-dgram-send-callback-multi-buffer.js +++ b/test/parallel/test-dgram-send-callback-multi-buffer.js @@ -7,7 +7,7 @@ const dgram = require('dgram'); const client = dgram.createSocket('udp4'); const messageSent = common.mustCall(function messageSent(err, bytes) { - assert.equal(bytes, buf1.length + buf2.length); + assert.strictEqual(bytes, buf1.length + buf2.length); }); const buf1 = Buffer.alloc(256, 'x'); diff --git a/test/parallel/test-domain-exit-dispose-again.js b/test/parallel/test-domain-exit-dispose-again.js index 0928addd9ace55..b1911bb40e0c93 100644 --- a/test/parallel/test-domain-exit-dispose-again.js +++ b/test/parallel/test-domain-exit-dispose-again.js @@ -51,7 +51,7 @@ setTimeout(function firstTimer() { 'a domain that should be disposed.'); disposalFailed = true; process.exit(1); - }); + }, 1); // Make V8 throw an unreferenced error. As a result, the domain's error // handler is called, which disposes the domain "d" and should prevent the @@ -69,8 +69,8 @@ setTimeout(function secondTimer() { }, TIMEOUT_DURATION); process.on('exit', function() { - assert.equal(a, 10); - assert.equal(disposalFailed, false); + assert.strictEqual(a, 10); + assert.strictEqual(disposalFailed, false); assert(secondTimerRan); console.log('ok'); }); diff --git a/test/parallel/test-domain-exit-dispose.js b/test/parallel/test-domain-exit-dispose.js index 94b3dbd4ca5a37..508cec18dccb7d 100644 --- a/test/parallel/test-domain-exit-dispose.js +++ b/test/parallel/test-domain-exit-dispose.js @@ -1,8 +1,8 @@ 'use strict'; require('../common'); +var common = require('../common'); var assert = require('assert'); var domain = require('domain'); -var disposalFailed = false; // no matter what happens, we should increment a 10 times. var a = 0; @@ -22,11 +22,7 @@ function err() { function err2() { // this timeout should never be called, since the domain gets // disposed when the error happens. - setTimeout(function() { - console.error('This should not happen.'); - disposalFailed = true; - process.exit(1); - }); + setTimeout(common.mustCall(() => {}, 0), 1); // this function doesn't exist, and throws an error as a result. err3(); // eslint-disable-line no-undef @@ -41,7 +37,6 @@ function err() { } process.on('exit', function() { - assert.equal(a, 10); - assert.equal(disposalFailed, false); + assert.strictEqual(a, 10); console.log('ok'); }); diff --git a/test/parallel/test-domain-from-timer.js b/test/parallel/test-domain-from-timer.js index f0115018ec1879..2ffae758ef6490 100644 --- a/test/parallel/test-domain-from-timer.js +++ b/test/parallel/test-domain-from-timer.js @@ -2,17 +2,17 @@ // Simple tests of most basic domain functionality. require('../common'); -var assert = require('assert'); +const assert = require('assert'); // timeouts call the callback directly from cc, so need to make sure the // domain will be used regardless setTimeout(function() { - var domain = require('domain'); - var d = domain.create(); + const domain = require('domain'); + const d = domain.create(); d.run(function() { process.nextTick(function() { console.trace('in nexttick', process.domain === d); - assert.equal(process.domain, d); + assert.strictEqual(process.domain, d); }); }); -}); +}, 1); diff --git a/test/parallel/test-domain-no-error-handler-abort-on-uncaught.js b/test/parallel/test-domain-no-error-handler-abort-on-uncaught.js index 76ca3faad702b6..833e7374d7f2ab 100644 --- a/test/parallel/test-domain-no-error-handler-abort-on-uncaught.js +++ b/test/parallel/test-domain-no-error-handler-abort-on-uncaught.js @@ -36,7 +36,7 @@ const tests = [ d.run(function() { setTimeout(function() { throw new Error('boom!'); - }); + }, 1); }); }, @@ -65,7 +65,7 @@ const tests = [ d.run(function() { var fs = require('fs'); - fs.exists('/non/existing/file', function onExists(exists) { + fs.exists('/non/existing/file', function onExists() { throw new Error('boom!'); }); }); @@ -82,7 +82,7 @@ const tests = [ d2.run(function() { setTimeout(function() { throw new Error('boom!'); - }); + }, 1); }); }); }, @@ -129,7 +129,7 @@ const tests = [ d.run(function() { d2.run(function() { var fs = require('fs'); - fs.exists('/non/existing/file', function onExists(exists) { + fs.exists('/non/existing/file', function onExists() { throw new Error('boom!'); }); }); diff --git a/test/parallel/test-domain-stack-empty-in-process-uncaughtexception.js b/test/parallel/test-domain-stack-empty-in-process-uncaughtexception.js index 8b345741ec95e3..a1699d106d9c7c 100644 --- a/test/parallel/test-domain-stack-empty-in-process-uncaughtexception.js +++ b/test/parallel/test-domain-stack-empty-in-process-uncaughtexception.js @@ -7,13 +7,14 @@ const assert = require('assert'); const d = domain.create(); process.on('uncaughtException', common.mustCall(function onUncaught() { - assert.equal(process.domain, null, - 'domains stack should be empty in uncaughtException handler'); + assert.strictEqual(process.domain, null, + 'domains stack should be empty in uncaughtException' + + ' handler'); })); process.on('beforeExit', common.mustCall(function onBeforeExit() { - assert.equal(process.domain, null, - 'domains stack should be empty in beforeExit handler'); + assert.strictEqual(process.domain, null, + 'domains stack should be empty in beforeExit handler'); })); d.run(function() { diff --git a/test/parallel/test-domain-uncaught-exception.js b/test/parallel/test-domain-uncaught-exception.js index 35632dbf537202..58df4ac59a7818 100644 --- a/test/parallel/test-domain-uncaught-exception.js +++ b/test/parallel/test-domain-uncaught-exception.js @@ -25,7 +25,7 @@ function test1() { d.run(function() { setTimeout(function onTimeout() { throw new Error('boom!'); - }); + }, 1); }); } @@ -59,7 +59,7 @@ function test3() { const d3 = domain.create(); const d4 = domain.create(); - d3.on('error', function onErrorInD3Domain(err) { + d3.on('error', function onErrorInD3Domain() { process.send('errorHandledByDomain'); }); @@ -88,7 +88,7 @@ function test4() { const d5 = domain.create(); const d6 = domain.create(); - d5.on('error', function onErrorInD2Domain(err) { + d5.on('error', function onErrorInD2Domain() { process.send('errorHandledByDomain'); }); @@ -96,7 +96,7 @@ function test4() { d6.run(function() { setTimeout(function onTimeout() { throw new Error('boom!'); - }); + }, 1); }); }); } @@ -115,7 +115,7 @@ function test5() { const d7 = domain.create(); const d8 = domain.create(); - d8.on('error', function onErrorInD3Domain(err) { + d8.on('error', function onErrorInD3Domain() { process.send('errorHandledByDomain'); }); @@ -139,7 +139,7 @@ function test6() { const d9 = domain.create(); const d10 = domain.create(); - d10.on('error', function onErrorInD2Domain(err) { + d10.on('error', function onErrorInD2Domain() { process.send('errorHandledByDomain'); }); @@ -147,7 +147,7 @@ function test6() { d10.run(function() { setTimeout(function onTimeout() { throw new Error('boom!'); - }); + }, 1); }); }); } diff --git a/test/parallel/test-domain.js b/test/parallel/test-domain.js index 69521108f6e47b..73ab3b96168930 100644 --- a/test/parallel/test-domain.js +++ b/test/parallel/test-domain.js @@ -2,10 +2,10 @@ // Simple tests of most basic domain functionality. require('../common'); -var assert = require('assert'); -var domain = require('domain'); -var events = require('events'); -var fs = require('fs'); +const assert = require('assert'); +const domain = require('domain'); +const events = require('events'); +const fs = require('fs'); var caught = 0; var expectCaught = 0; @@ -137,8 +137,8 @@ d.run(function() { // pretty common error. console.log(stat.isDirectory()); }); - }); - }); + }, 1); + }, 1); }); }); expectCaught++; @@ -148,7 +148,7 @@ expectCaught++; d.run(function() { setTimeout(function() { throw new Error('implicit timer'); - }); + }, 1); }); expectCaught++; @@ -162,7 +162,7 @@ expectCaught++; // get rid of the `if (er) return cb(er)` malarky, by intercepting // the cb functions to the domain, and using the intercepted function // as a callback instead. -function fn(er) { +function fn() { throw new Error('This function should never be called!'); } diff --git a/test/parallel/test-event-emitter-method-names.js b/test/parallel/test-event-emitter-method-names.js index c1e6540f0184af..e268e229b06b5b 100644 --- a/test/parallel/test-event-emitter-method-names.js +++ b/test/parallel/test-event-emitter-method-names.js @@ -4,10 +4,10 @@ var assert = require('assert'); var events = require('events'); var E = events.EventEmitter.prototype; -assert.equal(E.constructor.name, 'EventEmitter'); -assert.equal(E.on, E.addListener); // Same method. +assert.strictEqual(E.constructor.name, 'EventEmitter'); +assert.strictEqual(E.on, E.addListener); // Same method. Object.getOwnPropertyNames(E).forEach(function(name) { if (name === 'constructor' || name === 'on') return; if (typeof E[name] !== 'function') return; - assert.equal(E[name].name, name); + assert.strictEqual(E[name].name, name); }); diff --git a/test/parallel/test-fs-fsync.js b/test/parallel/test-fs-fsync.js index 89d104c00246bc..f69a3c5e7f13c6 100644 --- a/test/parallel/test-fs-fsync.js +++ b/test/parallel/test-fs-fsync.js @@ -1,32 +1,23 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); +const assert = require('assert'); -var path = require('path'); -var fs = require('fs'); -var successes = 0; +const path = require('path'); +const fs = require('fs'); -var file = path.join(common.fixturesDir, 'a.js'); +const file = path.join(common.fixturesDir, 'a.js'); -fs.open(file, 'a', 0o777, function(err, fd) { - if (err) throw err; +fs.open(file, 'a', 0o777, common.mustCall(function(err, fd) { + assert.ifError(err); fs.fdatasyncSync(fd); - successes++; fs.fsyncSync(fd); - successes++; - fs.fdatasync(fd, function(err) { - if (err) throw err; - successes++; - fs.fsync(fd, function(err) { - if (err) throw err; - successes++; - }); - }); -}); - -process.on('exit', function() { - assert.equal(4, successes); -}); + fs.fdatasync(fd, common.mustCall(function(err) { + assert.ifError(err); + fs.fsync(fd, common.mustCall(function(err) { + assert.ifError(err); + })); + })); +})); diff --git a/test/parallel/test-fs-open.js b/test/parallel/test-fs-open.js index a5a9bbf2577fca..d2d24b1e07ab75 100644 --- a/test/parallel/test-fs-open.js +++ b/test/parallel/test-fs-open.js @@ -1,27 +1,24 @@ 'use strict'; const common = require('../common'); -var assert = require('assert'); -var fs = require('fs'); +const assert = require('assert'); +const fs = require('fs'); + +let caughtException = false; -var caughtException = false; try { // should throw ENOENT, not EBADF // see https://github.com/joyent/node/pull/1228 fs.openSync('/path/to/file/that/does/not/exist', 'r'); } catch (e) { - assert.equal(e.code, 'ENOENT'); + assert.strictEqual(e.code, 'ENOENT'); caughtException = true; } -assert.ok(caughtException); +assert.strictEqual(caughtException, true); -fs.open(__filename, 'r', common.mustCall(function(err, fd) { - if (err) { - throw err; - } +fs.open(__filename, 'r', common.mustCall((err) => { + assert.ifError(err); })); -fs.open(__filename, 'rs', common.mustCall(function(err, fd) { - if (err) { - throw err; - } +fs.open(__filename, 'rs', common.mustCall((err) => { + assert.ifError(err); })); diff --git a/test/parallel/test-fs-read-stream-inherit.js b/test/parallel/test-fs-read-stream-inherit.js index 40ec5ed883829b..d71dc3d4381272 100644 --- a/test/parallel/test-fs-read-stream-inherit.js +++ b/test/parallel/test-fs-read-stream-inherit.js @@ -7,174 +7,185 @@ const fs = require('fs'); const fn = path.join(common.fixturesDir, 'elipses.txt'); const rangeFile = path.join(common.fixturesDir, 'x.txt'); -const callbacks = { open: 0, end: 0, close: 0 }; - let paused = false; -const file = fs.ReadStream(fn); - -file.on('open', function(fd) { - file.length = 0; - callbacks.open++; - assert.strictEqual(typeof fd, 'number'); - assert.ok(file.readable); +{ + const file = fs.ReadStream(fn); - // GH-535 - file.pause(); - file.resume(); - file.pause(); - file.resume(); -}); + file.on('open', common.mustCall(function(fd) { + file.length = 0; + assert.strictEqual(typeof fd, 'number'); + assert.ok(file.readable); -file.on('data', function(data) { - assert.ok(data instanceof Buffer); - assert.ok(!paused); - file.length += data.length; + // GH-535 + file.pause(); + file.resume(); + file.pause(); + file.resume(); + })); - paused = true; - file.pause(); + file.on('data', function(data) { + assert.ok(data instanceof Buffer); + assert.ok(!paused); + file.length += data.length; - setTimeout(function() { - paused = false; - file.resume(); - }, 10); -}); + paused = true; + file.pause(); + setTimeout(function() { + paused = false; + file.resume(); + }, 10); + }); -file.on('end', function(chunk) { - callbacks.end++; -}); + file.on('end', common.mustCall(function() {})); -file.on('close', function() { - callbacks.close++; -}); -const file3 = fs.createReadStream(fn, Object.create({encoding: 'utf8'})); -file3.length = 0; -file3.on('data', function(data) { - assert.strictEqual(typeof data, 'string'); - file3.length += data.length; + file.on('close', common.mustCall(function() { + assert.strictEqual(file.length, 30000); + })); +} - for (let i = 0; i < data.length; i++) { - // http://www.fileformat.info/info/unicode/char/2026/index.htm - assert.strictEqual(data[i], '\u2026'); - } -}); - -file3.on('close', function() { - callbacks.close++; -}); - -process.on('exit', function() { - assert.strictEqual(callbacks.open, 1); - assert.strictEqual(callbacks.end, 1); - assert.strictEqual(callbacks.close, 2); - assert.strictEqual(file.length, 30000); - assert.strictEqual(file3.length, 10000); - console.error('ok'); -}); - -const file4 = fs.createReadStream(rangeFile, Object.create({bufferSize: 1, - start: 1, end: 2})); -assert.strictEqual(file4.start, 1); -assert.strictEqual(file4.end, 2); -let contentRead = ''; -file4.on('data', function(data) { - contentRead += data.toString('utf-8'); -}); -file4.on('end', function(data) { - assert.strictEqual(contentRead, 'yz'); -}); - -const file5 = fs.createReadStream(rangeFile, Object.create({bufferSize: 1, - start: 1})); -assert.strictEqual(file5.start, 1); -file5.data = ''; -file5.on('data', function(data) { - file5.data += data.toString('utf-8'); -}); -file5.on('end', function() { - assert.strictEqual(file5.data, 'yz\n'); -}); +{ + const file3 = fs.createReadStream(fn, Object.create({encoding: 'utf8'})); + file3.length = 0; + file3.on('data', function(data) { + assert.strictEqual(typeof data, 'string'); + file3.length += data.length; + + for (let i = 0; i < data.length; i++) { + // http://www.fileformat.info/info/unicode/char/2026/index.htm + assert.strictEqual(data[i], '\u2026'); + } + }); -// https://github.com/joyent/node/issues/2320 -const file6 = fs.createReadStream(rangeFile, Object.create({bufferSize: 1.23, - start: 1})); -assert.strictEqual(file6.start, 1); -file6.data = ''; -file6.on('data', function(data) { - file6.data += data.toString('utf-8'); -}); -file6.on('end', function() { - assert.strictEqual(file6.data, 'yz\n'); -}); - -assert.throws(function() { - fs.createReadStream(rangeFile, Object.create({start: 10, end: 2})); -}, /"start" option must be <= "end" option/); - -const stream = fs.createReadStream(rangeFile, Object.create({ start: 0, - end: 0 })); -assert.strictEqual(stream.start, 0); -assert.strictEqual(stream.end, 0); -stream.data = ''; - -stream.on('data', function(chunk) { - stream.data += chunk; -}); - -stream.on('end', function() { - assert.strictEqual(stream.data, 'x'); -}); + file3.on('close', common.mustCall(function() { + assert.strictEqual(file3.length, 10000); + })); +} -// pause and then resume immediately. -const pauseRes = fs.createReadStream(rangeFile); -pauseRes.pause(); -pauseRes.resume(); - -let file7 = fs.createReadStream(rangeFile, Object.create({autoClose: false })); -assert.strictEqual(file7.autoClose, false); -file7.on('data', function() {}); -file7.on('end', function() { - process.nextTick(function() { - assert(!file7.closed); - assert(!file7.destroyed); - file7Next(); +{ + const options = Object.create({bufferSize: 1, start: 1, end: 2}); + const file4 = fs.createReadStream(rangeFile, options); + assert.strictEqual(file4.start, 1); + assert.strictEqual(file4.end, 2); + let contentRead = ''; + file4.on('data', function(data) { + contentRead += data.toString('utf-8'); }); -}); - -function file7Next() { - // This will tell us if the fd is usable again or not. - file7 = fs.createReadStream(null, Object.create({fd: file7.fd, start: 0 })); - file7.data = ''; - file7.on('data', function(data) { - file7.data += data; + file4.on('end', common.mustCall(function() { + assert.strictEqual(contentRead, 'yz'); + })); +} + +{ + const options = Object.create({bufferSize: 1, start: 1}); + const file5 = fs.createReadStream(rangeFile, options); + assert.strictEqual(file5.start, 1); + file5.data = ''; + file5.on('data', function(data) { + file5.data += data.toString('utf-8'); }); - file7.on('end', function(err) { - assert.strictEqual(file7.data, 'xyz\n'); + file5.on('end', common.mustCall(function() { + assert.strictEqual(file5.data, 'yz\n'); + })); +} + +// https://github.com/joyent/node/issues/2320 +{ + const options = Object.create({bufferSize: 1.23, start: 1}); + const file6 = fs.createReadStream(rangeFile, options); + assert.strictEqual(file6.start, 1); + file6.data = ''; + file6.on('data', function(data) { + file6.data += data.toString('utf-8'); }); + file6.on('end', common.mustCall(function() { + assert.strictEqual(file6.data, 'yz\n'); + })); } -// Just to make sure autoClose won't close the stream because of error. -const file8 = fs.createReadStream(null, Object.create({fd: 13337, - autoClose: false })); -file8.on('data', function() {}); -file8.on('error', common.mustCall(function() {})); +{ + assert.throws(function() { + fs.createReadStream(rangeFile, Object.create({start: 10, end: 2})); + }, /"start" option must be <= "end" option/); +} -// Make sure stream is destroyed when file does not exist. -const file9 = fs.createReadStream('/path/to/file/that/does/not/exist'); -file9.on('data', function() {}); -file9.on('error', common.mustCall(function() {})); +{ + const options = Object.create({start: 0, end: 0}); + const stream = fs.createReadStream(rangeFile, options); + assert.strictEqual(stream.start, 0); + assert.strictEqual(stream.end, 0); + stream.data = ''; + + stream.on('data', function(chunk) { + stream.data += chunk; + }); + + stream.on('end', common.mustCall(function() { + assert.strictEqual(stream.data, 'x'); + })); +} + +// pause and then resume immediately. +{ + const pauseRes = fs.createReadStream(rangeFile); + pauseRes.pause(); + pauseRes.resume(); +} -process.on('exit', function() { - assert(file7.closed); - assert(file7.destroyed); +{ + let file7 = + fs.createReadStream(rangeFile, Object.create({autoClose: false })); + assert.strictEqual(file7.autoClose, false); + file7.on('data', function() {}); + file7.on('end', common.mustCall(function() { + process.nextTick(common.mustCall(function() { + assert(!file7.closed); + assert(!file7.destroyed); + file7Next(); + })); + })); + + function file7Next() { + // This will tell us if the fd is usable again or not. + file7 = fs.createReadStream(null, Object.create({fd: file7.fd, start: 0 })); + file7.data = ''; + file7.on('data', function(data) { + file7.data += data; + }); + file7.on('end', common.mustCall(function() { + assert.strictEqual(file7.data, 'xyz\n'); + })); + } + process.on('exit', function() { + assert(file7.closed); + assert(file7.destroyed); + }); +} - assert(!file8.closed); - assert(!file8.destroyed); - assert(file8.fd); +// Just to make sure autoClose won't close the stream because of error. +{ + const options = Object.create({fd: 13337, autoClose: false}); + const file8 = fs.createReadStream(null, options); + file8.on('data', function() {}); + file8.on('error', common.mustCall(function() {})); + process.on('exit', function() { + assert(!file8.closed); + assert(!file8.destroyed); + assert(file8.fd); + }); +} - assert(!file9.closed); - assert(file9.destroyed); -}); +// Make sure stream is destroyed when file does not exist. +{ + const file9 = fs.createReadStream('/path/to/file/that/does/not/exist'); + file9.on('data', function() {}); + file9.on('error', common.mustCall(function() {})); + + process.on('exit', function() { + assert(!file9.closed); + assert(file9.destroyed); + }); +} diff --git a/test/parallel/test-fs-read-stream.js b/test/parallel/test-fs-read-stream.js index 7b133022511910..c8da0275c53c9b 100644 --- a/test/parallel/test-fs-read-stream.js +++ b/test/parallel/test-fs-read-stream.js @@ -1,11 +1,11 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); +const assert = require('assert'); -var path = require('path'); -var fs = require('fs'); -var fn = path.join(common.fixturesDir, 'elipses.txt'); -var rangeFile = path.join(common.fixturesDir, 'x.txt'); +const path = require('path'); +const fs = require('fs'); +const fn = path.join(common.fixturesDir, 'elipses.txt'); +const rangeFile = path.join(common.fixturesDir, 'x.txt'); var callbacks = { open: 0, end: 0, close: 0 }; @@ -20,7 +20,7 @@ assert.strictEqual(file.bytesRead, 0); file.on('open', function(fd) { file.length = 0; callbacks.open++; - assert.equal('number', typeof fd); + assert.strictEqual('number', typeof fd); assert.strictEqual(file.bytesRead, 0); assert.ok(file.readable); @@ -67,12 +67,12 @@ file.on('close', function() { var file3 = fs.createReadStream(fn, {encoding: 'utf8'}); file3.length = 0; file3.on('data', function(data) { - assert.equal('string', typeof data); + assert.strictEqual('string', typeof data); file3.length += data.length; for (var i = 0; i < data.length; i++) { // http://www.fileformat.info/info/unicode/char/2026/index.htm - assert.equal('\u2026', data[i]); + assert.strictEqual('\u2026', data[i]); } }); @@ -81,11 +81,11 @@ file3.on('close', function() { }); process.on('exit', function() { - assert.equal(1, callbacks.open); - assert.equal(1, callbacks.end); - assert.equal(2, callbacks.close); - assert.equal(30000, file.length); - assert.equal(10000, file3.length); + assert.strictEqual(1, callbacks.open); + assert.strictEqual(1, callbacks.end); + assert.strictEqual(2, callbacks.close); + assert.strictEqual(30000, file.length); + assert.strictEqual(10000, file3.length); console.error('ok'); }); @@ -95,7 +95,7 @@ file4.on('data', function(data) { contentRead += data.toString('utf-8'); }); file4.on('end', function(data) { - assert.equal(contentRead, 'yz'); + assert.strictEqual(contentRead, 'yz'); }); var file5 = fs.createReadStream(rangeFile, {bufferSize: 1, start: 1}); @@ -104,7 +104,7 @@ file5.on('data', function(data) { file5.data += data.toString('utf-8'); }); file5.on('end', function() { - assert.equal(file5.data, 'yz\n'); + assert.strictEqual(file5.data, 'yz\n'); }); // https://github.com/joyent/node/issues/2320 @@ -114,7 +114,7 @@ file6.on('data', function(data) { file6.data += data.toString('utf-8'); }); file6.on('end', function() { - assert.equal(file6.data, 'yz\n'); + assert.strictEqual(file6.data, 'yz\n'); }); assert.throws(function() { @@ -129,7 +129,7 @@ stream.on('data', function(chunk) { }); stream.on('end', function() { - assert.equal('x', stream.data); + assert.strictEqual('x', stream.data); }); // pause and then resume immediately. @@ -155,7 +155,7 @@ function file7Next() { file7.data += data; }); file7.on('end', function(err) { - assert.equal(file7.data, 'xyz\n'); + assert.strictEqual(file7.data, 'xyz\n'); }); } diff --git a/test/parallel/test-fs-truncate.js b/test/parallel/test-fs-truncate.js index 442038eeb50a51..1ba0db7f012fe4 100644 --- a/test/parallel/test-fs-truncate.js +++ b/test/parallel/test-fs-truncate.js @@ -1,43 +1,43 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var path = require('path'); -var fs = require('fs'); -var tmp = common.tmpDir; -var filename = path.resolve(tmp, 'truncate-file.txt'); -var data = Buffer.alloc(1024 * 16, 'x'); +const common = require('../common'); +const assert = require('assert'); +const path = require('path'); +const fs = require('fs'); +const tmp = common.tmpDir; +const filename = path.resolve(tmp, 'truncate-file.txt'); +const data = Buffer.alloc(1024 * 16, 'x'); common.refreshTmpDir(); -var stat; +let stat; // truncateSync fs.writeFileSync(filename, data); stat = fs.statSync(filename); -assert.equal(stat.size, 1024 * 16); +assert.strictEqual(stat.size, 1024 * 16); fs.truncateSync(filename, 1024); stat = fs.statSync(filename); -assert.equal(stat.size, 1024); +assert.strictEqual(stat.size, 1024); fs.truncateSync(filename); stat = fs.statSync(filename); -assert.equal(stat.size, 0); +assert.strictEqual(stat.size, 0); // ftruncateSync fs.writeFileSync(filename, data); -var fd = fs.openSync(filename, 'r+'); +const fd = fs.openSync(filename, 'r+'); stat = fs.statSync(filename); -assert.equal(stat.size, 1024 * 16); +assert.strictEqual(stat.size, 1024 * 16); fs.ftruncateSync(fd, 1024); stat = fs.statSync(filename); -assert.equal(stat.size, 1024); +assert.strictEqual(stat.size, 1024); fs.ftruncateSync(fd); stat = fs.statSync(filename); -assert.equal(stat.size, 0); +assert.strictEqual(stat.size, 0); fs.closeSync(fd); @@ -54,19 +54,19 @@ function testTruncate(cb) { if (er) return cb(er); fs.stat(filename, function(er, stat) { if (er) return cb(er); - assert.equal(stat.size, 1024 * 16); + assert.strictEqual(stat.size, 1024 * 16); fs.truncate(filename, 1024, function(er) { if (er) return cb(er); fs.stat(filename, function(er, stat) { if (er) return cb(er); - assert.equal(stat.size, 1024); + assert.strictEqual(stat.size, 1024); fs.truncate(filename, function(er) { if (er) return cb(er); fs.stat(filename, function(er, stat) { if (er) return cb(er); - assert.equal(stat.size, 0); + assert.strictEqual(stat.size, 0); cb(); }); }); @@ -82,7 +82,7 @@ function testFtruncate(cb) { if (er) return cb(er); fs.stat(filename, function(er, stat) { if (er) return cb(er); - assert.equal(stat.size, 1024 * 16); + assert.strictEqual(stat.size, 1024 * 16); fs.open(filename, 'w', function(er, fd) { if (er) return cb(er); @@ -90,13 +90,13 @@ function testFtruncate(cb) { if (er) return cb(er); fs.stat(filename, function(er, stat) { if (er) return cb(er); - assert.equal(stat.size, 1024); + assert.strictEqual(stat.size, 1024); fs.ftruncate(fd, function(er) { if (er) return cb(er); fs.stat(filename, function(er, stat) { if (er) return cb(er); - assert.equal(stat.size, 0); + assert.strictEqual(stat.size, 0); fs.close(fd, cb); }); }); diff --git a/test/parallel/test-handle-wrap-close-abort.js b/test/parallel/test-handle-wrap-close-abort.js index 8572668f666864..5355e65df60821 100644 --- a/test/parallel/test-handle-wrap-close-abort.js +++ b/test/parallel/test-handle-wrap-close-abort.js @@ -1,16 +1,16 @@ 'use strict'; -require('../common'); +const common = require('../common'); -process.on('uncaughtException', function() { }); +process.on('uncaughtException', common.mustCall(function() {}, 2)); setTimeout(function() { process.nextTick(function() { - var c = setInterval(function() { + const c = setInterval(function() { clearInterval(c); throw new Error('setInterval'); - }); + }, 1); }); setTimeout(function() { throw new Error('setTimeout'); - }); + }, 1); }); diff --git a/test/parallel/test-http-after-connect.js b/test/parallel/test-http-after-connect.js index 0bae99b1d34cf1..0580f428ed70f5 100644 --- a/test/parallel/test-http-after-connect.js +++ b/test/parallel/test-http-after-connect.js @@ -1,38 +1,34 @@ 'use strict'; -require('../common'); -var assert = require('assert'); -var http = require('http'); +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); -var serverConnected = false; -var serverRequests = 0; var clientResponses = 0; -var server = http.createServer(function(req, res) { +const server = http.createServer(common.mustCall(function(req, res) { console.error('Server got GET request'); req.resume(); - ++serverRequests; res.writeHead(200); res.write(''); setTimeout(function() { res.end(req.url); }, 50); -}); -server.on('connect', function(req, socket, firstBodyChunk) { +}, 2)); +server.on('connect', common.mustCall(function(req, socket) { console.error('Server got CONNECT request'); - serverConnected = true; socket.write('HTTP/1.1 200 Connection established\r\n\r\n'); socket.resume(); socket.on('end', function() { socket.end(); }); -}); +})); server.listen(0, function() { - var req = http.request({ + const req = http.request({ port: this.address().port, method: 'CONNECT', path: 'google.com:80' }); - req.on('connect', function(res, socket, firstBodyChunk) { + req.on('connect', common.mustCall(function(res, socket) { console.error('Client got CONNECT response'); socket.end(); socket.on('end', function() { @@ -40,7 +36,7 @@ server.listen(0, function() { doRequest(1); }); socket.resume(); - }); + })); req.end(); }); @@ -48,7 +44,7 @@ function doRequest(i) { http.get({ port: server.address().port, path: '/request' + i - }, function(res) { + }, common.mustCall(function(res) { console.error('Client got GET response'); var data = ''; res.setEncoding('utf8'); @@ -56,17 +52,11 @@ function doRequest(i) { data += chunk; }); res.on('end', function() { - assert.equal(data, '/request' + i); + assert.strictEqual(data, '/request' + i); ++clientResponses; if (clientResponses === 2) { server.close(); } }); - }); + })); } - -process.on('exit', function() { - assert(serverConnected); - assert.equal(serverRequests, 2); - assert.equal(clientResponses, 2); -}); diff --git a/test/parallel/test-http-client-timeout-event.js b/test/parallel/test-http-client-timeout-event.js index 8e3d034c31d857..623b253a20e667 100644 --- a/test/parallel/test-http-client-timeout-event.js +++ b/test/parallel/test-http-client-timeout-event.js @@ -1,33 +1,30 @@ 'use strict'; const common = require('../common'); -const assert = require('assert'); const http = require('http'); -var options = { +const options = { method: 'GET', port: undefined, host: '127.0.0.1', path: '/' }; -var server = http.createServer(); +const server = http.createServer(); server.listen(0, options.host, function() { options.port = this.address().port; - var req = http.request(options); + const req = http.request(options); req.on('error', function() { // this space is intentionally left blank }); req.on('close', common.mustCall(() => server.close())); - var timeout_events = 0; req.setTimeout(1); - req.on('timeout', common.mustCall(() => timeout_events += 1)); - setTimeout(function() { - req.destroy(); - assert.strictEqual(timeout_events, 1); - }, common.platformTimeout(100)); - setTimeout(function() { - req.end(); - }, common.platformTimeout(50)); + req.on('timeout', common.mustCall(() => { + req.end(() => { + setTimeout(() => { + req.destroy(); + }, 100); + }); + })); }); diff --git a/test/parallel/test-http-client-timeout-option-listeners.js b/test/parallel/test-http-client-timeout-option-listeners.js new file mode 100644 index 00000000000000..727b5fddf09624 --- /dev/null +++ b/test/parallel/test-http-client-timeout-option-listeners.js @@ -0,0 +1,47 @@ +'use strict'; +const common = require('../common'); +const http = require('http'); +const assert = require('assert'); + +const agent = new http.Agent({ keepAlive: true }); + +const server = http.createServer((req, res) => { + res.end(''); +}); + +// Maximum allowed value for timeouts +const timeout = 2 ** 31 - 1; + +const options = { + agent, + method: 'GET', + port: undefined, + host: common.localhostIPv4, + path: '/', + timeout: timeout +}; + +server.listen(0, options.host, common.mustCall(() => { + options.port = server.address().port; + doRequest(common.mustCall((numListeners) => { + assert.strictEqual(numListeners, 1); + doRequest(common.mustCall((numListeners) => { + assert.strictEqual(numListeners, 1); + server.close(); + agent.destroy(); + })); + })); +})); + +function doRequest(cb) { + http.request(options, common.mustCall((response) => { + const sockets = agent.sockets[`${options.host}:${options.port}:`]; + assert.strictEqual(sockets.length, 1); + const socket = sockets[0]; + const numListeners = socket.listeners('timeout').length; + response.resume(); + response.once('end', common.mustCall(() => { + process.nextTick(cb, numListeners); + })); + })).end(); +} diff --git a/test/parallel/test-http-incoming-pipelined-socket-destroy.js b/test/parallel/test-http-incoming-pipelined-socket-destroy.js index 9789e9976cb7a7..1465f189dd2045 100644 --- a/test/parallel/test-http-incoming-pipelined-socket-destroy.js +++ b/test/parallel/test-http-incoming-pipelined-socket-destroy.js @@ -1,16 +1,17 @@ 'use strict'; -require('../common'); +const common = require('../common'); -var http = require('http'); -var net = require('net'); +const http = require('http'); +const net = require('net'); +const seeds = [ 3, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 ]; // Set up some timing issues where sockets can be destroyed // via either the req or res. -var server = http.createServer(function(req, res) { +const server = http.createServer(common.mustCall(function(req, res) { switch (req.url) { case '/1': - return setTimeout(function() { + return setImmediate(function() { req.socket.destroy(); server.emit('requestDone'); }); @@ -24,7 +25,7 @@ var server = http.createServer(function(req, res) { // in one case, actually send a response in 2 chunks case '/3': res.write('hello '); - return setTimeout(function() { + return setImmediate(function() { res.end('world!'); server.emit('requestDone'); }); @@ -33,7 +34,7 @@ var server = http.createServer(function(req, res) { res.destroy(); server.emit('requestDone'); } -}); +}, seeds.length)); // Make a bunch of requests pipelined on the same socket @@ -47,10 +48,9 @@ function generator(seeds) { } -server.listen(0, function() { - var seeds = [ 3, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4 ]; - var client = net.connect({ port: this.address().port }); - var done = 0; +server.listen(0, common.mustCall(function() { + const client = net.connect({ port: this.address().port }); + let done = 0; server.on('requestDone', function() { if (++done === seeds.length) { server.close(); @@ -60,9 +60,4 @@ server.listen(0, function() { // immediately write the pipelined requests. // Some of these will not have a socket to destroy! client.write(generator(seeds)); -}); - -process.on('exit', function(c) { - if (!c) - console.log('ok'); -}); +})); diff --git a/test/parallel/test-http-pause-resume-one-end.js b/test/parallel/test-http-pause-resume-one-end.js index 2ebd3cbe619ac7..6b98246cc271ac 100644 --- a/test/parallel/test-http-pause-resume-one-end.js +++ b/test/parallel/test-http-pause-resume-one-end.js @@ -1,23 +1,23 @@ 'use strict'; const common = require('../common'); -var http = require('http'); +const http = require('http'); -var server = http.Server(function(req, res) { +const server = http.Server(function(req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); server.close(); }); server.listen(0, common.mustCall(function() { - var opts = { + const opts = { port: this.address().port, headers: { connection: 'close' } }; http.get(opts, common.mustCall(function(res) { - res.on('data', common.mustCall(function(chunk) { + res.on('data', common.mustCall(function() { res.pause(); - setTimeout(function() { + setImmediate(function() { res.resume(); }); })); diff --git a/test/parallel/test-http-unix-socket.js b/test/parallel/test-http-unix-socket.js index 69c887b53bdbb1..d2b99bde95a234 100644 --- a/test/parallel/test-http-unix-socket.js +++ b/test/parallel/test-http-unix-socket.js @@ -1,9 +1,9 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var http = require('http'); +const common = require('../common'); +const assert = require('assert'); +const http = require('http'); -var server = http.createServer(function(req, res) { +const server = http.createServer(function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain', 'Connection': 'close' @@ -23,8 +23,8 @@ server.listen(common.PIPE, common.mustCall(function() { }; var req = http.get(options, common.mustCall(function(res) { - assert.equal(res.statusCode, 200); - assert.equal(res.headers['content-type'], 'text/plain'); + assert.strictEqual(res.statusCode, 200); + assert.strictEqual(res.headers['content-type'], 'text/plain'); res.body = ''; res.setEncoding('utf8'); @@ -34,19 +34,18 @@ server.listen(common.PIPE, common.mustCall(function() { }); res.on('end', common.mustCall(function() { - assert.equal(res.body, 'hello world\n'); - server.close(function(error) { - assert.equal(error, undefined); - server.close(function(error) { - assert.equal(error && error.message, 'Not running'); - }); - }); + assert.strictEqual(res.body, 'hello world\n'); + server.close(common.mustCall(function(error) { + assert.strictEqual(error, undefined); + server.close(common.mustCall(function(error) { + assert.strictEqual(error && error.message, 'Not running'); + })); + })); })); })); req.on('error', function(e) { - console.log(e.stack); - process.exit(1); + common.fail(e.stack); }); req.end(); diff --git a/test/parallel/test-https-agent-session-reuse.js b/test/parallel/test-https-agent-session-reuse.js index 01f161574b29db..73465aa5a98fb9 100644 --- a/test/parallel/test-https-agent-session-reuse.js +++ b/test/parallel/test-https-agent-session-reuse.js @@ -1,39 +1,39 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); +const assert = require('assert'); if (!common.hasCrypto) { common.skip('missing crypto'); return; } -var https = require('https'); -var crypto = require('crypto'); +const https = require('https'); +const crypto = require('crypto'); -var fs = require('fs'); +const fs = require('fs'); -var options = { +const options = { key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem') }; -var ca = fs.readFileSync(common.fixturesDir + '/keys/ca1-cert.pem'); +const ca = fs.readFileSync(common.fixturesDir + '/keys/ca1-cert.pem'); -var clientSessions = {}; -var serverRequests = 0; +const clientSessions = {}; +let serverRequests = 0; -var agent = new https.Agent({ +const agent = new https.Agent({ maxCachedSessions: 1 }); -var server = https.createServer(options, function(req, res) { +const server = https.createServer(options, function(req, res) { if (req.url === '/drop-key') server.setTicketKeys(crypto.randomBytes(48)); serverRequests++; res.end('ok'); }).listen(0, function() { - var queue = [ + const queue = [ { name: 'first', @@ -97,7 +97,7 @@ var server = https.createServer(options, function(req, res) { ]; function request() { - var options = queue.shift(); + const options = queue.shift(); options.agent = agent; https.request(options, function(res) { clientSessions[options.name] = res.socket.getSession(); @@ -114,9 +114,9 @@ var server = https.createServer(options, function(req, res) { }); process.on('exit', function() { - assert.equal(serverRequests, 6); - assert.equal(clientSessions['first'].toString('hex'), - clientSessions['first-reuse'].toString('hex')); + assert.strictEqual(serverRequests, 6); + assert.strictEqual(clientSessions['first'].toString('hex'), + clientSessions['first-reuse'].toString('hex')); assert.notEqual(clientSessions['first'].toString('hex'), clientSessions['cipher-change'].toString('hex')); assert.notEqual(clientSessions['first'].toString('hex'), @@ -125,6 +125,6 @@ process.on('exit', function() { clientSessions['before-drop'].toString('hex')); assert.notEqual(clientSessions['before-drop'].toString('hex'), clientSessions['after-drop'].toString('hex')); - assert.equal(clientSessions['after-drop'].toString('hex'), - clientSessions['after-drop-reuse'].toString('hex')); + assert.strictEqual(clientSessions['after-drop'].toString('hex'), + clientSessions['after-drop-reuse'].toString('hex')); }); diff --git a/test/parallel/test-https-timeout-server.js b/test/parallel/test-https-timeout-server.js index 92b06f1495ddbf..04ccf0a64d2d7c 100644 --- a/test/parallel/test-https-timeout-server.js +++ b/test/parallel/test-https-timeout-server.js @@ -1,29 +1,29 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); if (!common.hasCrypto) { common.skip('missing crypto'); return; } -var https = require('https'); +const assert = require('assert'); +const https = require('https'); -var net = require('net'); -var fs = require('fs'); +const net = require('net'); +const fs = require('fs'); -var options = { +const options = { key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem'), handshakeTimeout: 50 }; -var server = https.createServer(options, common.fail); +const server = https.createServer(options, common.fail); server.on('clientError', common.mustCall(function(err, conn) { // Don't hesitate to update the asserts if the internal structure of // the cleartext object ever changes. We're checking that the https.Server // has closed the client connection. - assert.equal(conn._secureEstablished, false); + assert.strictEqual(conn._secureEstablished, false); server.close(); conn.destroy(); })); diff --git a/test/parallel/test-icu-transcode.js b/test/parallel/test-icu-transcode.js index 2cdd4078a2cceb..c099e754ca55d6 100644 --- a/test/parallel/test-icu-transcode.js +++ b/test/parallel/test-icu-transcode.js @@ -38,13 +38,19 @@ for (const test in tests) { utf8_to_ucs2.toString('ucs2')); } +assert.throws( + () => buffer.transcode(null, 'utf8', 'ascii'), + /^TypeError: "source" argument must be a Buffer$/ +); + assert.throws( () => buffer.transcode(Buffer.from('a'), 'b', 'utf8'), - /Unable to transcode Buffer \[U_ILLEGAL_ARGUMENT_ERROR\]/ + /^Error: Unable to transcode Buffer \[U_ILLEGAL_ARGUMENT_ERROR\]/ ); + assert.throws( () => buffer.transcode(Buffer.from('a'), 'uf8', 'b'), - /Unable to transcode Buffer \[U_ILLEGAL_ARGUMENT_ERROR\]/ + /^Error: Unable to transcode Buffer \[U_ILLEGAL_ARGUMENT_ERROR\]$/ ); assert.deepStrictEqual( diff --git a/test/parallel/test-listen-fd-ebadf.js b/test/parallel/test-listen-fd-ebadf.js index 09beda067b5e71..86004e6af00437 100644 --- a/test/parallel/test-listen-fd-ebadf.js +++ b/test/parallel/test-listen-fd-ebadf.js @@ -1,7 +1,7 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var net = require('net'); +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); net.createServer(common.fail).listen({fd: 2}) .on('error', common.mustCall(onError)); @@ -9,5 +9,5 @@ net.createServer(common.fail).listen({fd: 42}) .on('error', common.mustCall(onError)); function onError(ex) { - assert.equal(ex.code, 'EINVAL'); + assert.strictEqual(ex.code, 'EINVAL'); } diff --git a/test/parallel/test-net-keepalive.js b/test/parallel/test-net-keepalive.js index d414393a9346cd..e466f0ff580d06 100644 --- a/test/parallel/test-net-keepalive.js +++ b/test/parallel/test-net-keepalive.js @@ -1,20 +1,20 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var net = require('net'); +const common = require('../common'); +const assert = require('assert'); +const net = require('net'); var serverConnection; var clientConnection; var echoServer = net.createServer(function(connection) { serverConnection = connection; - setTimeout(function() { + setTimeout(common.mustCall(function() { // make sure both connections are still open - assert.equal(serverConnection.readyState, 'open'); - assert.equal(clientConnection.readyState, 'open'); + assert.strictEqual(serverConnection.readyState, 'open'); + assert.strictEqual(clientConnection.readyState, 'open'); serverConnection.end(); clientConnection.end(); echoServer.close(); - }, common.platformTimeout(100)); + }, 1), common.platformTimeout(100)); connection.setTimeout(0); assert.notEqual(connection.setKeepAlive, undefined); // send a keepalive packet after 50 ms diff --git a/test/parallel/test-net-socket-timeout.js b/test/parallel/test-net-socket-timeout.js index 54f5ce301cc52e..61ea54debeaa61 100644 --- a/test/parallel/test-net-socket-timeout.js +++ b/test/parallel/test-net-socket-timeout.js @@ -1,14 +1,17 @@ 'use strict'; -var common = require('../common'); -var net = require('net'); -var assert = require('assert'); +const common = require('../common'); +const net = require('net'); +const assert = require('assert'); // Verify that invalid delays throw -var noop = function() {}; -var s = new net.Socket(); -var nonNumericDelays = ['100', true, false, undefined, null, '', {}, noop, []]; -var badRangeDelays = [-0.001, -1, -Infinity, Infinity, NaN]; -var validDelays = [0, 0.001, 1, 1e6]; +const noop = function() {}; +const s = new net.Socket(); +const nonNumericDelays = [ + '100', true, false, undefined, null, '', {}, noop, [] +]; +const badRangeDelays = [-0.001, -1, -Infinity, Infinity, NaN]; +const validDelays = [0, 0.001, 1, 1e6]; + for (let i = 0; i < nonNumericDelays.length; i++) { assert.throws(function() { @@ -28,15 +31,11 @@ for (let i = 0; i < validDelays.length; i++) { }); } -var server = net.Server(); +const server = net.Server(); server.listen(0, common.mustCall(function() { - var socket = net.createConnection(this.address().port); - socket.setTimeout(100, common.mustCall(function() { + const socket = net.createConnection(this.address().port); + socket.setTimeout(1, common.mustCall(function() { socket.destroy(); server.close(); - clearTimeout(timer); })); - var timer = setTimeout(function() { - process.exit(1); - }, common.platformTimeout(200)); })); diff --git a/test/parallel/test-os-homedir-no-envvar.js b/test/parallel/test-os-homedir-no-envvar.js index cb4be4e6efcd4e..94d8ab5a08fa14 100644 --- a/test/parallel/test-os-homedir-no-envvar.js +++ b/test/parallel/test-os-homedir-no-envvar.js @@ -1,28 +1,28 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var cp = require('child_process'); -var os = require('os'); -var path = require('path'); +const common = require('../common'); +const assert = require('assert'); +const cp = require('child_process'); +const os = require('os'); +const path = require('path'); if (process.argv[2] === 'child') { if (common.isWindows) - assert.equal(process.env.USERPROFILE, undefined); + assert.strictEqual(process.env.USERPROFILE, undefined); else - assert.equal(process.env.HOME, undefined); + assert.strictEqual(process.env.HOME, undefined); - var home = os.homedir(); + const home = os.homedir(); - assert.ok(typeof home === 'string'); - assert.ok(home.indexOf(path.sep) !== -1); + assert.strictEqual(typeof home, 'string'); + assert(home.includes(path.sep)); } else { if (common.isWindows) delete process.env.USERPROFILE; else delete process.env.HOME; - var child = cp.spawnSync(process.execPath, [__filename, 'child'], { + const child = cp.spawnSync(process.execPath, [__filename, 'child'], { env: process.env }); diff --git a/test/parallel/test-preload.js b/test/parallel/test-preload.js index f849bc3dda3243..4ee564f0520cc5 100644 --- a/test/parallel/test-preload.js +++ b/test/parallel/test-preload.js @@ -32,27 +32,27 @@ const fixtureD = fixture('define-global.js'); const fixtureThrows = fixture('throws_error4.js'); // test preloading a single module works -childProcess.exec(nodeBinary + ' ' - + preloadOption([fixtureA]) + ' ' - + fixtureB, +childProcess.exec(nodeBinary + ' ' + + preloadOption([fixtureA]) + ' ' + + fixtureB, function(err, stdout, stderr) { if (err) throw err; assert.strictEqual(stdout, 'A\nB\n'); }); // test preloading multiple modules works -childProcess.exec(nodeBinary + ' ' - + preloadOption([fixtureA, fixtureB]) + ' ' - + fixtureC, +childProcess.exec(nodeBinary + ' ' + + preloadOption([fixtureA, fixtureB]) + ' ' + + fixtureC, function(err, stdout, stderr) { if (err) throw err; assert.strictEqual(stdout, 'A\nB\nC\n'); }); // test that preloading a throwing module aborts -childProcess.exec(nodeBinary + ' ' - + preloadOption([fixtureA, fixtureThrows]) + ' ' - + fixtureB, +childProcess.exec(nodeBinary + ' ' + + preloadOption([fixtureA, fixtureThrows]) + ' ' + + fixtureB, function(err, stdout, stderr) { if (err) { assert.strictEqual(stdout, 'A\n'); @@ -62,9 +62,9 @@ childProcess.exec(nodeBinary + ' ' }); // test that preload can be used with --eval -childProcess.exec(nodeBinary + ' ' - + preloadOption([fixtureA]) - + '-e "console.log(\'hello\');"', +childProcess.exec(nodeBinary + ' ' + + preloadOption([fixtureA]) + + '-e "console.log(\'hello\');"', function(err, stdout, stderr) { if (err) throw err; assert.strictEqual(stdout, 'A\nhello\n'); @@ -108,19 +108,19 @@ replProc.on('close', function(code) { // test that preload placement at other points in the cmdline // also test that duplicated preload only gets loaded once -childProcess.exec(nodeBinary + ' ' - + preloadOption([fixtureA]) - + '-e "console.log(\'hello\');" ' - + preloadOption([fixtureA, fixtureB]), +childProcess.exec(nodeBinary + ' ' + + preloadOption([fixtureA]) + + '-e "console.log(\'hello\');" ' + + preloadOption([fixtureA, fixtureB]), function(err, stdout, stderr) { if (err) throw err; assert.strictEqual(stdout, 'A\nB\nhello\n'); }); // test that preload works with -i -const interactive = childProcess.exec(nodeBinary + ' ' - + preloadOption([fixtureD]) - + '-i', +const interactive = childProcess.exec(nodeBinary + ' ' + + preloadOption([fixtureD]) + + '-i', common.mustCall(function(err, stdout, stderr) { assert.ifError(err); assert.strictEqual(stdout, "> 'test'\n> "); @@ -129,9 +129,9 @@ const interactive = childProcess.exec(nodeBinary + ' ' interactive.stdin.write('a\n'); interactive.stdin.write('process.exit()\n'); -childProcess.exec(nodeBinary + ' ' - + '--require ' + fixture('cluster-preload.js') + ' ' - + fixture('cluster-preload-test.js'), +childProcess.exec(nodeBinary + ' ' + + '--require ' + fixture('cluster-preload.js') + ' ' + + fixture('cluster-preload-test.js'), function(err, stdout, stderr) { if (err) throw err; assert.ok(/worker terminated with code 43/.test(stdout)); @@ -139,10 +139,10 @@ childProcess.exec(nodeBinary + ' ' // https://github.com/nodejs/node/issues/1691 process.chdir(common.fixturesDir); -childProcess.exec(nodeBinary + ' ' - + '--expose_debug_as=v8debug ' - + '--require ' + fixture('cluster-preload.js') + ' ' - + 'cluster-preload-test.js', +childProcess.exec(nodeBinary + ' ' + + '--expose_debug_as=v8debug ' + + '--require ' + fixture('cluster-preload.js') + ' ' + + 'cluster-preload-test.js', function(err, stdout, stderr) { if (err) throw err; assert.ok(/worker terminated with code 43/.test(stdout)); diff --git a/test/parallel/test-process-kill-pid.js b/test/parallel/test-process-kill-pid.js index 5c11be2903c4a7..ee0554c32083f6 100644 --- a/test/parallel/test-process-kill-pid.js +++ b/test/parallel/test-process-kill-pid.js @@ -24,6 +24,10 @@ assert.throws(function() { process.kill(+'not a number'); }, TypeError); assert.throws(function() { process.kill(1 / 0); }, TypeError); assert.throws(function() { process.kill(-1 / 0); }, TypeError); +// Test that kill throws an error for invalid signal + +assert.throws(function() { process.kill(1, 'test'); }, Error); + // Test kill argument processing in valid cases. // // Monkey patch _kill so that we don't actually send any signals, particularly diff --git a/test/parallel/test-repl-domain.js b/test/parallel/test-repl-domain.js index 9f66f306395d29..3cc88b75f72428 100644 --- a/test/parallel/test-repl-domain.js +++ b/test/parallel/test-repl-domain.js @@ -18,6 +18,6 @@ putIn.write = function(data) { }; putIn.run([ - 'require("domain").create().on("error", function() { console.log("OK") })' - + '.run(function() { throw new Error("threw") })' + 'require("domain").create().on("error", function() { console.log("OK") })' + + '.run(function() { throw new Error("threw") })' ]); diff --git a/test/parallel/test-require-dot.js b/test/parallel/test-require-dot.js index 2fb161486a9241..26733c7fc438a1 100644 --- a/test/parallel/test-require-dot.js +++ b/test/parallel/test-require-dot.js @@ -1,17 +1,17 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var module = require('module'); +const common = require('../common'); +const assert = require('assert'); +const m = require('module'); -var a = require(common.fixturesDir + '/module-require/relative/dot.js'); -var b = require(common.fixturesDir + '/module-require/relative/dot-slash.js'); +const a = require(common.fixturesDir + '/module-require/relative/dot.js'); +const b = require(common.fixturesDir + '/module-require/relative/dot-slash.js'); -assert.equal(a.value, 42); -assert.equal(a, b, 'require(".") should resolve like require("./")'); +assert.strictEqual(a.value, 42); +assert.strictEqual(a, b, 'require(".") should resolve like require("./")'); process.env.NODE_PATH = common.fixturesDir + '/module-require/relative'; -module._initPaths(); +m._initPaths(); -var c = require('.'); +const c = require('.'); -assert.equal(c.value, 42, 'require(".") should honor NODE_PATH'); +assert.strictEqual(c.value, 42, 'require(".") should honor NODE_PATH'); diff --git a/test/parallel/test-stdin-from-file.js b/test/parallel/test-stdin-from-file.js index d6e3afeae6fdee..f3a78192e5e5aa 100644 --- a/test/parallel/test-stdin-from-file.js +++ b/test/parallel/test-stdin-from-file.js @@ -1,44 +1,40 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var join = require('path').join; -var childProcess = require('child_process'); -var fs = require('fs'); - -var stdoutScript = join(common.fixturesDir, 'echo-close-check.js'); -var tmpFile = join(common.tmpDir, 'stdin.txt'); - -var cmd = '"' + process.argv[0] + '" "' + stdoutScript + '" < "' + - tmpFile + '"'; - -var string = 'abc\nümlaut.\nsomething else\n' + - '南越国是前203年至前111年存在于岭南地区的一个国家,国都位于番禺,' + - '疆域包括今天中国的广东、广西两省区的大部份地区,福建省、湖南、贵州、' + - '云南的一小部份地区和越南的北部。南越国是秦朝灭亡后,' + - '由南海郡尉赵佗于前203年起兵兼并桂林郡和象郡后建立。前196年和前179年,' + - '南越国曾先后两次名义上臣属于西汉,成为西汉的“外臣”。前112年,' + - '南越国末代君主赵建德与西汉发生战争,被汉武帝于前111年所灭。南越国共存在93年,' + - '历经五代君主。南越国是岭南地区的第一个有记载的政权国家,' + - '采用封建制和郡县制并存的制度,' + - '它的建立保证了秦末乱世岭南地区社会秩序的稳定,' + - '有效的改善了岭南地区落后的政治、##济现状。\n'; +const common = require('../common'); +const assert = require('assert'); +const join = require('path').join; +const childProcess = require('child_process'); +const fs = require('fs'); + +const stdoutScript = join(common.fixturesDir, 'echo-close-check.js'); +const tmpFile = join(common.tmpDir, 'stdin.txt'); + +const cmd = '"' + process.argv[0] + '" "' + stdoutScript + '" < "' + + tmpFile + '"'; + +const string = 'abc\nümlaut.\nsomething else\n' + + '南越国是前203年至前111年存在于岭南地区的一个国家,国都位于番禺,' + + '疆域包括今天中国的广东、广西两省区的大部份地区,福建省、湖南、贵州、' + + '云南的一小部份地区和越南的北部。南越国是秦朝灭亡后,' + + '由南海郡尉赵佗于前203年起兵兼并桂林郡和象郡后建立。前196年和前179年,' + + '南越国曾先后两次名义上臣属于西汉,成为西汉的“外臣”。前112年,' + + '南越国末代君主赵建德与西汉发生战争,被汉武帝于前111年所灭。南越国共存在93年,' + + '历经五代君主。南越国是岭南地区的第一个有记载的政权国家,' + + '采用封建制和郡县制并存的制度,' + + '它的建立保证了秦末乱世岭南地区社会秩序的稳定,' + + '有效的改善了岭南地区落后的政治、##济现状。\n'; common.refreshTmpDir(); console.log(cmd + '\n\n'); -try { - fs.unlinkSync(tmpFile); -} catch (e) {} - fs.writeFileSync(tmpFile, string); -childProcess.exec(cmd, function(err, stdout, stderr) { +childProcess.exec(cmd, common.mustCall(function(err, stdout, stderr) { fs.unlinkSync(tmpFile); if (err) throw err; console.log(stdout); - assert.equal(stdout, 'hello world\r\n' + string); - assert.equal('', stderr); -}); + assert.strictEqual(stdout, 'hello world\r\n' + string); + assert.strictEqual('', stderr); +})); diff --git a/test/parallel/test-stdout-close-catch.js b/test/parallel/test-stdout-close-catch.js index d84d8e93b0c0b0..322ed76aee8fc0 100644 --- a/test/parallel/test-stdout-close-catch.js +++ b/test/parallel/test-stdout-close-catch.js @@ -1,27 +1,30 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); -var path = require('path'); -var child_process = require('child_process'); +const common = require('../common'); +const assert = require('assert'); +const path = require('path'); +const child_process = require('child_process'); -var testScript = path.join(common.fixturesDir, 'catch-stdout-error.js'); +const testScript = path.join(common.fixturesDir, 'catch-stdout-error.js'); -var cmd = JSON.stringify(process.execPath) + ' ' + - JSON.stringify(testScript) + ' | ' + - JSON.stringify(process.execPath) + ' ' + - '-pe "process.stdin.on(\'data\' , () => process.exit(1))"'; +const cmd = JSON.stringify(process.execPath) + ' ' + + JSON.stringify(testScript) + ' | ' + + JSON.stringify(process.execPath) + ' ' + + '-pe "process.stdin.on(\'data\' , () => process.exit(1))"'; -var child = child_process.exec(cmd); -var output = ''; -var outputExpect = { 'code': 'EPIPE', - 'errno': 'EPIPE', - 'syscall': 'write' }; +const child = child_process.exec(cmd); +let output = ''; +const outputExpect = { + code: 'EPIPE', + errno: 'EPIPE', + syscall: 'write' +}; child.stderr.on('data', function(c) { output += c; }); -child.on('close', function(code) { + +child.on('close', common.mustCall(function(code) { try { output = JSON.parse(output); } catch (er) { @@ -31,4 +34,4 @@ child.on('close', function(code) { assert.deepStrictEqual(output, outputExpect); console.log('ok'); -}); +})); diff --git a/test/parallel/test-stream-big-push.js b/test/parallel/test-stream-big-push.js index d9b79ebafc1d08..27feef35ef536d 100644 --- a/test/parallel/test-stream-big-push.js +++ b/test/parallel/test-stream-big-push.js @@ -1,5 +1,5 @@ 'use strict'; -require('../common'); +const common = require('../common'); const assert = require('assert'); const stream = require('stream'); const str = 'asdfasdfasdfasdfasdf'; @@ -10,29 +10,25 @@ const r = new stream.Readable({ }); let reads = 0; -let eofed = false; -let ended = false; -r._read = function(n) { +function _read() { if (reads === 0) { setTimeout(function() { r.push(str); - }); + }, 1); reads++; } else if (reads === 1) { var ret = r.push(str); assert.strictEqual(ret, false); reads++; } else { - assert(!eofed); - eofed = true; r.push(null); } -}; +} -r.on('end', function() { - ended = true; -}); +r._read = common.mustCall(_read, 3); + +r.on('end', common.mustCall(function() {})); // push some data in to start. // we've never gotten any read event at this point. @@ -55,10 +51,3 @@ r.once('readable', function() { chunk = r.read(); assert.strictEqual(chunk, null); }); - -process.on('exit', function() { - assert(eofed); - assert(ended); - assert.strictEqual(reads, 2); - console.log('ok'); -}); diff --git a/test/parallel/test-stream-buffer-list.js b/test/parallel/test-stream-buffer-list.js new file mode 100644 index 00000000000000..ddbff452de4be9 --- /dev/null +++ b/test/parallel/test-stream-buffer-list.js @@ -0,0 +1,27 @@ +// Flags: --expose_internals +'use strict'; +require('../common'); +const assert = require('assert'); +const BufferList = require('internal/streams/BufferList'); + +// Test empty buffer list. +const emptyList = new BufferList(); + +emptyList.shift(); +assert.deepStrictEqual(emptyList, new BufferList()); + +assert.strictEqual(emptyList.join(','), ''); + +assert.deepStrictEqual(emptyList.concat(0), Buffer.alloc(0)); + +// Test buffer list with one element. +const list = new BufferList(); +list.push('foo'); + +assert.strictEqual(list.concat(1), 'foo'); + +assert.strictEqual(list.join(','), 'foo'); + +const shifted = list.shift(); +assert.strictEqual(shifted, 'foo'); +assert.deepStrictEqual(list, new BufferList()); diff --git a/test/parallel/test-stream-readable-emittedReadable.js b/test/parallel/test-stream-readable-emittedReadable.js new file mode 100644 index 00000000000000..65b6b5b15a5895 --- /dev/null +++ b/test/parallel/test-stream-readable-emittedReadable.js @@ -0,0 +1,70 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const Readable = require('stream').Readable; + +const readable = new Readable({ + read: () => {} +}); + +// Initialized to false. +assert.strictEqual(readable._readableState.emittedReadable, false); + +readable.on('readable', common.mustCall(() => { + // emittedReadable should be true when the readable event is emitted + assert.strictEqual(readable._readableState.emittedReadable, true); + readable.read(); + // emittedReadable is reset to false during read() + assert.strictEqual(readable._readableState.emittedReadable, false); +}, 4)); + +// When the first readable listener is just attached, +// emittedReadable should be false +assert.strictEqual(readable._readableState.emittedReadable, false); + +// Each one of these should trigger a readable event. +process.nextTick(common.mustCall(() => { + readable.push('foo'); +})); +process.nextTick(common.mustCall(() => { + readable.push('bar'); +})); +process.nextTick(common.mustCall(() => { + readable.push('quo'); +})); +process.nextTick(common.mustCall(() => { + readable.push(null); +})); + +const noRead = new Readable({ + read: () => {} +}); + +noRead.on('readable', common.mustCall(() => { + // emittedReadable should be true when the readable event is emitted + assert.strictEqual(noRead._readableState.emittedReadable, true); + noRead.read(0); + // emittedReadable is not reset during read(0) + assert.strictEqual(noRead._readableState.emittedReadable, true); +})); + +noRead.push('foo'); +noRead.push(null); + +const flowing = new Readable({ + read: () => {} +}); + +flowing.on('data', common.mustCall(() => { + // When in flowing mode, emittedReadable is always false. + assert.strictEqual(flowing._readableState.emittedReadable, false); + flowing.read(); + assert.strictEqual(flowing._readableState.emittedReadable, false); +}, 3)); + +flowing.push('foooo'); +flowing.push('bar'); +flowing.push('quo'); +process.nextTick(common.mustCall(() => { + flowing.push(null); +})); diff --git a/test/parallel/test-stream-readable-needReadable.js b/test/parallel/test-stream-readable-needReadable.js new file mode 100644 index 00000000000000..48229edd202333 --- /dev/null +++ b/test/parallel/test-stream-readable-needReadable.js @@ -0,0 +1,96 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const Readable = require('stream').Readable; + +const readable = new Readable({ + read: () => {} +}); + +// Initialized to false. +assert.strictEqual(readable._readableState.needReadable, false); + +readable.on('readable', common.mustCall(() => { + // When the readable event fires, needReadable is reset. + assert.strictEqual(readable._readableState.needReadable, false); + readable.read(); +})); + +// If a readable listener is attached, then a readable event is needed. +assert.strictEqual(readable._readableState.needReadable, true); + +readable.push('foo'); +readable.push(null); + +readable.on('end', common.mustCall(() => { + // No need to emit readable anymore when the stream ends. + assert.strictEqual(readable._readableState.needReadable, false); +})); + +const asyncReadable = new Readable({ + read: () => {} +}); + +asyncReadable.on('readable', common.mustCall(() => { + if (asyncReadable.read() !== null) { + // After each read(), the buffer is empty. + // If the stream doesn't end now, + // then we need to notify the reader on future changes. + assert.strictEqual(asyncReadable._readableState.needReadable, true); + } +}, 3)); + +process.nextTick(common.mustCall(() => { + asyncReadable.push('foooo'); +})); +process.nextTick(common.mustCall(() => { + asyncReadable.push('bar'); +})); +process.nextTick(common.mustCall(() => { + asyncReadable.push(null); +})); + +const flowing = new Readable({ + read: () => {} +}); + +// Notice this must be above the on('data') call. +flowing.push('foooo'); +flowing.push('bar'); +flowing.push('quo'); +process.nextTick(common.mustCall(() => { + flowing.push(null); +})); + +// When the buffer already has enough data, and the stream is +// in flowing mode, there is no need for the readable event. +flowing.on('data', common.mustCall(function(data) { + assert.strictEqual(flowing._readableState.needReadable, false); +}, 3)); + +const slowProducer = new Readable({ + read: () => {} +}); + +slowProducer.on('readable', common.mustCall(() => { + if (slowProducer.read(8) === null) { + // The buffer doesn't have enough data, and the stream is not ened, + // we need to notify the reader when data arrives. + assert.strictEqual(slowProducer._readableState.needReadable, true); + } else { + assert.strictEqual(slowProducer._readableState.needReadable, false); + } +}, 4)); + +process.nextTick(common.mustCall(() => { + slowProducer.push('foo'); +})); +process.nextTick(common.mustCall(() => { + slowProducer.push('foo'); +})); +process.nextTick(common.mustCall(() => { + slowProducer.push('foo'); +})); +process.nextTick(common.mustCall(() => { + slowProducer.push(null); +})); diff --git a/test/parallel/test-stream-readable-reading-readingMore.js b/test/parallel/test-stream-readable-reading-readingMore.js new file mode 100644 index 00000000000000..bee3a1c82a8678 --- /dev/null +++ b/test/parallel/test-stream-readable-reading-readingMore.js @@ -0,0 +1,65 @@ +'use strict'; +const common = require('../common'); +const assert = require('assert'); +const Readable = require('stream').Readable; + +const readable = new Readable({ + read(size) {} +}); + +const state = readable._readableState; + +// Starting off with false initially. +assert.strictEqual(state.reading, false); +assert.strictEqual(state.readingMore, false); + +readable.on('data', common.mustCall((data) => { + // while in a flowing state, should try to read more. + if (state.flowing) + assert.strictEqual(state.readingMore, true); + + // reading as long as we've not ended + assert.strictEqual(state.reading, !state.ended); +}, 2)); + +function onStreamEnd() { + // End of stream; state.reading is false + // And so should be readingMore. + assert.strictEqual(state.readingMore, false); + assert.strictEqual(state.reading, false); +} + +readable.on('readable', common.mustCall(() => { + // 'readable' always gets called before 'end' + // since 'end' hasn't been emitted, more data could be incoming + assert.strictEqual(state.readingMore, true); + + // if the stream has ended, we shouldn't be reading + assert.strictEqual(state.ended, !state.reading); + + if (readable.read() === null) // reached end of stream + process.nextTick(common.mustCall(onStreamEnd, 1)); +}, 2)); + +readable.on('end', common.mustCall(onStreamEnd)); + +readable.push('pushed'); + +// stop emitting 'data' events +readable.pause(); + +// read() should only be called while operating in paused mode +readable.read(6); + +// reading +assert.strictEqual(state.reading, true); +assert.strictEqual(state.readingMore, true); + +// resume emitting 'data' events +readable.resume(); + +// add chunk to front +readable.unshift('unshifted'); + +// end +readable.push(null); diff --git a/test/parallel/test-stream-readable-resumeScheduled.js b/test/parallel/test-stream-readable-resumeScheduled.js new file mode 100644 index 00000000000000..6d1bc913388f46 --- /dev/null +++ b/test/parallel/test-stream-readable-resumeScheduled.js @@ -0,0 +1,65 @@ +'use strict'; +const common = require('../common'); + +// Testing Readable Stream resumeScheduled state + +const assert = require('assert'); +const { Readable, Writable } = require('stream'); + +{ + // pipe() test case + const r = new Readable({ read() {} }); + const w = new Writable(); + + // resumeScheduled should start = `false`. + assert.strictEqual(r._readableState.resumeScheduled, false); + + // calling pipe() should change the state value = true. + r.pipe(w); + assert.strictEqual(r._readableState.resumeScheduled, true); + + process.nextTick(common.mustCall(() => { + assert.strictEqual(r._readableState.resumeScheduled, false); + })); +} + +{ + // 'data' listener test case + const r = new Readable({ read() {} }); + + // resumeScheduled should start = `false`. + assert.strictEqual(r._readableState.resumeScheduled, false); + + r.push(Buffer.from([1, 2, 3])); + + // adding 'data' listener should change the state value + r.on('data', common.mustCall(() => { + assert.strictEqual(r._readableState.resumeScheduled, false); + })); + assert.strictEqual(r._readableState.resumeScheduled, true); + + process.nextTick(common.mustCall(() => { + assert.strictEqual(r._readableState.resumeScheduled, false); + })); +} + +{ + // resume() test case + const r = new Readable({ read() {} }); + + // resumeScheduled should start = `false`. + assert.strictEqual(r._readableState.resumeScheduled, false); + + // Calling resume() should change the state value. + r.resume(); + assert.strictEqual(r._readableState.resumeScheduled, true); + + r.on('resume', common.mustCall(() => { + // The state value should be `false` again + assert.strictEqual(r._readableState.resumeScheduled, false); + })); + + process.nextTick(common.mustCall(() => { + assert.strictEqual(r._readableState.resumeScheduled, false); + })); +} diff --git a/test/parallel/test-stream-readableListening-state.js b/test/parallel/test-stream-readableListening-state.js new file mode 100644 index 00000000000000..5e3071faf370e5 --- /dev/null +++ b/test/parallel/test-stream-readableListening-state.js @@ -0,0 +1,34 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const stream = require('stream'); + +const r = new stream.Readable({ + read: () => {} +}); + +// readableListening state should start in `false`. +assert.strictEqual(r._readableState.readableListening, false); + +r.on('readable', common.mustCall(() => { + // Inside the readable event this state should be true. + assert.strictEqual(r._readableState.readableListening, true); +})); + +r.push(Buffer.from('Testing readableListening state')); + +const r2 = new stream.Readable({ + read: () => {} +}); + +// readableListening state should start in `false`. +assert.strictEqual(r2._readableState.readableListening, false); + +r2.on('data', common.mustCall((chunk) => { + // readableListening should be false because we don't have + // a `readable` listener + assert.strictEqual(r2._readableState.readableListening, false); +})); + +r2.push(Buffer.from('Testing readableListening state')); diff --git a/test/parallel/test-timers-regress-GH-9765.js b/test/parallel/test-timers-regress-GH-9765.js new file mode 100644 index 00000000000000..71169fa0d1704c --- /dev/null +++ b/test/parallel/test-timers-regress-GH-9765.js @@ -0,0 +1,23 @@ +'use strict'; +const common = require('../common'); + +// This test ensures that if an Immediate callback clears subsequent +// immediates we don't get stuck in an infinite loop. +// +// If the process does get stuck, it will be timed out by the test +// runner. +// +// Ref: https://github.com/nodejs/node/issues/9756 + +setImmediate(common.mustCall(function() { + clearImmediate(i2); + clearImmediate(i3); +})); + +const i2 = setImmediate(function() { + common.fail('immediate callback should not have fired'); +}); + +const i3 = setImmediate(function() { + common.fail('immediate callback should not have fired'); +}); diff --git a/test/parallel/test-tls-client-mindhsize.js b/test/parallel/test-tls-client-mindhsize.js index 9956c971ffbbf3..1d812a72093ba9 100644 --- a/test/parallel/test-tls-client-mindhsize.js +++ b/test/parallel/test-tls-client-mindhsize.js @@ -53,8 +53,8 @@ function test(size, err, next) { if (err) { client.on('error', function(e) { nerror++; - assert.strictEqual(e.message, 'DH parameter size 1024 is less' - + ' than 2048'); + assert.strictEqual(e.message, 'DH parameter size 1024 is less' + + ' than 2048'); server.close(); }); } diff --git a/test/parallel/test-tls-client-verify.js b/test/parallel/test-tls-client-verify.js index 7844253db9c15f..983d88296eb26f 100644 --- a/test/parallel/test-tls-client-verify.js +++ b/test/parallel/test-tls-client-verify.js @@ -1,17 +1,17 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); +const assert = require('assert'); if (!common.hasCrypto) { common.skip('missing crypto'); return; } -var tls = require('tls'); +const tls = require('tls'); -var fs = require('fs'); +const fs = require('fs'); -var hosterr = /Hostname\/IP doesn't match certificate's altnames/g; -var testCases = +const hosterr = /Hostname\/IP doesn't match certificate's altnames/g; +const testCases = [{ ca: ['ca1-cert'], key: 'agent2-key', cert: 'agent2-cert', @@ -52,16 +52,16 @@ function loadPEM(n) { return fs.readFileSync(filenamePEM(n)); } -var successfulTests = 0; +let successfulTests = 0; function testServers(index, servers, clientOptions, cb) { - var serverOptions = servers[index]; + const serverOptions = servers[index]; if (!serverOptions) { cb(); return; } - var ok = serverOptions.ok; + const ok = serverOptions.ok; if (serverOptions.key) { serverOptions.key = loadPEM(serverOptions.key); @@ -71,37 +71,37 @@ function testServers(index, servers, clientOptions, cb) { serverOptions.cert = loadPEM(serverOptions.cert); } - var server = tls.createServer(serverOptions, function(s) { + const server = tls.createServer(serverOptions, common.mustCall(function(s) { s.end('hello world\n'); - }); + })); - server.listen(0, function() { - var b = ''; + server.listen(0, common.mustCall(function() { + let b = ''; console.error('connecting...'); clientOptions.port = this.address().port; - var client = tls.connect(clientOptions, function() { - var authorized = client.authorized || - hosterr.test(client.authorizationError); + const client = tls.connect(clientOptions, common.mustCall(function() { + const authorized = client.authorized || + hosterr.test(client.authorizationError); console.error('expected: ' + ok + ' authed: ' + authorized); - assert.equal(ok, authorized); + assert.strictEqual(ok, authorized); server.close(); - }); + })); client.on('data', function(d) { b += d.toString(); }); - client.on('end', function() { - assert.equal('hello world\n', b); - }); + client.on('end', common.mustCall(function() { + assert.strictEqual('hello world\n', b); + })); - client.on('close', function() { + client.on('close', common.mustCall(function() { testServers(index + 1, servers, clientOptions, cb); - }); - }); + })); + })); } @@ -109,7 +109,7 @@ function runTest(testIndex) { var tcase = testCases[testIndex]; if (!tcase) return; - var clientOptions = { + const clientOptions = { port: undefined, ca: tcase.ca.map(loadPEM), key: loadPEM(tcase.key), @@ -118,10 +118,10 @@ function runTest(testIndex) { }; - testServers(0, tcase.servers, clientOptions, function() { + testServers(0, tcase.servers, clientOptions, common.mustCall(function() { successfulTests++; runTest(testIndex + 1); - }); + })); } diff --git a/test/parallel/test-tls-cnnic-whitelist.js b/test/parallel/test-tls-cnnic-whitelist.js index f16698c736be39..c2b9c0849296bc 100644 --- a/test/parallel/test-tls-cnnic-whitelist.js +++ b/test/parallel/test-tls-cnnic-whitelist.js @@ -1,16 +1,15 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); if (!common.hasCrypto) { common.skip('missing crypto'); return; } -var tls = require('tls'); -var fs = require('fs'); -var path = require('path'); -var finished = 0; +const assert = require('assert'); +const tls = require('tls'); +const fs = require('fs'); +const path = require('path'); function filenamePEM(n) { return path.join(common.fixturesDir, 'keys', n + '.pem'); @@ -20,7 +19,7 @@ function loadPEM(n) { return fs.readFileSync(filenamePEM(n)); } -var testCases = [ +const testCases = [ { // Test 0: for the check of a cert not existed in the whitelist. // agent7-cert.pem is issued by the fake CNNIC root CA so that its // hash is not listed in the whitelist. @@ -58,27 +57,22 @@ var testCases = [ ]; function runTest(tindex) { - var tcase = testCases[tindex]; + const tcase = testCases[tindex]; if (!tcase) return; - var server = tls.createServer(tcase.serverOpts, function(s) { + const server = tls.createServer(tcase.serverOpts, (s) => { s.resume(); - }).listen(0, function() { + }).listen(0, common.mustCall(function() { tcase.clientOpts = this.address().port; - var client = tls.connect(tcase.clientOpts); - client.on('error', function(e) { + const client = tls.connect(tcase.clientOpts); + client.on('error', common.mustCall((e) => { assert.strictEqual(e.code, tcase.errorCode); - server.close(function() { - finished++; + server.close(common.mustCall(() => { runTest(tindex + 1); - }); - }); - }); + })); + })); + })); } runTest(0); - -process.on('exit', function() { - assert.equal(finished, testCases.length); -}); diff --git a/test/parallel/test-tls-ecdh-disable.js b/test/parallel/test-tls-ecdh-disable.js index a6ddb15cc1478e..c2a7440a686a10 100644 --- a/test/parallel/test-tls-ecdh-disable.js +++ b/test/parallel/test-tls-ecdh-disable.js @@ -20,7 +20,7 @@ var options = { var server = tls.createServer(options, common.fail); -server.listen(0, '127.0.0.1', function() { +server.listen(0, '127.0.0.1', common.mustCall(function() { var cmd = '"' + common.opensslCli + '" s_client -cipher ' + options.ciphers + ` -connect 127.0.0.1:${this.address().port}`; @@ -28,10 +28,10 @@ server.listen(0, '127.0.0.1', function() { if (common.isWindows) cmd += ' -no_rand_screen'; - exec(cmd, function(err, stdout, stderr) { + exec(cmd, common.mustCall(function(err, stdout, stderr) { // Old versions of openssl will still exit with 0 so we // can't just check if err is not null. - assert.notEqual(stderr.indexOf('handshake failure'), -1); + assert(stderr.includes('handshake failure')); server.close(); - }); -}); + })); +})); diff --git a/test/parallel/test-tls-env-bad-extra-ca.js b/test/parallel/test-tls-env-bad-extra-ca.js new file mode 100644 index 00000000000000..1862366e013af0 --- /dev/null +++ b/test/parallel/test-tls-env-bad-extra-ca.js @@ -0,0 +1,43 @@ +// Setting NODE_EXTRA_CA_CERTS to non-existent file emits a warning + +'use strict'; +const common = require('../common'); + +if (!common.hasCrypto) { + common.skip('missing crypto'); + return; +} + +const assert = require('assert'); +const tls = require('tls'); +const fork = require('child_process').fork; + +if (process.env.CHILD) { + // This will try to load the extra CA certs, and emit a warning when it fails. + return tls.createServer({}); +} + +const env = { + CHILD: 'yes', + NODE_EXTRA_CA_CERTS: common.fixturesDir + '/no-such-file-exists', +}; + +var opts = { + env: env, + silent: true, +}; +var stderr = ''; + +fork(__filename, opts) + .on('exit', common.mustCall(function(status) { + assert.equal(status, 0, 'client did not succeed in connecting'); + })) + .on('close', common.mustCall(function() { + assert(stderr.match(new RegExp( + 'Warning: Ignoring extra certs from.*no-such-file-exists' + + '.* load failed:.*No such file or directory' + )), stderr); + })) + .stderr.setEncoding('utf8').on('data', function(str) { + stderr += str; + }); diff --git a/test/parallel/test-tls-env-extra-ca.js b/test/parallel/test-tls-env-extra-ca.js new file mode 100644 index 00000000000000..12e3272bd401a2 --- /dev/null +++ b/test/parallel/test-tls-env-extra-ca.js @@ -0,0 +1,45 @@ +// Certs in NODE_EXTRA_CA_CERTS are used for TLS peer validation + +'use strict'; +const common = require('../common'); + +if (!common.hasCrypto) { + common.skip('missing crypto'); + return; +} + +const assert = require('assert'); +const tls = require('tls'); +const fork = require('child_process').fork; +const fs = require('fs'); + +if (process.env.CHILD) { + const copts = { + port: process.env.PORT, + checkServerIdentity: function() {}, + }; + const client = tls.connect(copts, function() { + client.end('hi'); + }); + return; +} + +const options = { + key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), + cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem'), +}; + +const server = tls.createServer(options, function(s) { + s.end('bye'); + server.close(); +}).listen(0, common.mustCall(function() { + const env = { + CHILD: 'yes', + PORT: this.address().port, + NODE_EXTRA_CA_CERTS: common.fixturesDir + '/keys/ca1-cert.pem', + }; + + fork(__filename, {env: env}).on('exit', common.mustCall(function(status) { + assert.equal(status, 0, 'client did not succeed in connecting'); + })); +})); diff --git a/test/parallel/test-tls-multi-key.js b/test/parallel/test-tls-multi-key.js index e73ee2e25e6931..e29f5ee522829e 100644 --- a/test/parallel/test-tls-multi-key.js +++ b/test/parallel/test-tls-multi-key.js @@ -11,8 +11,8 @@ var fs = require('fs'); var options = { key: [ + fs.readFileSync(common.fixturesDir + '/keys/ec-key.pem'), fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), - fs.readFileSync(common.fixturesDir + '/keys/ec-key.pem') ], cert: [ fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem'), diff --git a/test/parallel/test-tls-no-cert-required.js b/test/parallel/test-tls-no-cert-required.js index de723e73e8a335..3c7cf4462fcd07 100644 --- a/test/parallel/test-tls-no-cert-required.js +++ b/test/parallel/test-tls-no-cert-required.js @@ -1,15 +1,30 @@ 'use strict'; -var common = require('../common'); +const assert = require('assert'); +const common = require('../common'); if (!common.hasCrypto) { common.skip('missing crypto'); return; } -var tls = require('tls'); +const tls = require('tls'); // Omitting the cert or pfx option to tls.createServer() should not throw. // AECDH-NULL-SHA is a no-authentication/no-encryption cipher and hence // doesn't need a certificate. -tls.createServer({ ciphers: 'AECDH-NULL-SHA' }).listen(0, function() { +tls.createServer({ ciphers: 'AECDH-NULL-SHA' }) + .listen(0, common.mustCall(close)); + +tls.createServer(assert.fail) + .listen(0, common.mustCall(close)); + +tls.createServer({}) + .listen(0, common.mustCall(close)); + +assert.throws(() => tls.createServer('this is not valid'), TypeError); + +tls.createServer() + .listen(0, common.mustCall(close)); + +function close() { this.close(); -}); +} diff --git a/test/parallel/test-tls-on-empty-socket.js b/test/parallel/test-tls-on-empty-socket.js index 58bc101333a583..84e27c5dd3067e 100644 --- a/test/parallel/test-tls-on-empty-socket.js +++ b/test/parallel/test-tls-on-empty-socket.js @@ -1,27 +1,27 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); if (!common.hasCrypto) { common.skip('missing crypto'); return; } -var tls = require('tls'); +const assert = require('assert'); +const tls = require('tls'); -var fs = require('fs'); -var net = require('net'); +const fs = require('fs'); +const net = require('net'); -var out = ''; +let out = ''; -var server = tls.createServer({ +const server = tls.createServer({ key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem') }, function(c) { c.end('hello'); }).listen(0, function() { - var socket = new net.Socket(); + const socket = new net.Socket(); - var s = tls.connect({ + const s = tls.connect({ socket: socket, rejectUnauthorized: false }, function() { @@ -38,5 +38,5 @@ var server = tls.createServer({ }); process.on('exit', function() { - assert.equal(out, 'hello'); + assert.strictEqual(out, 'hello'); }); diff --git a/test/parallel/test-tls-passphrase.js b/test/parallel/test-tls-passphrase.js index 8999f470187f78..4630fe236d16c7 100644 --- a/test/parallel/test-tls-passphrase.js +++ b/test/parallel/test-tls-passphrase.js @@ -1,21 +1,27 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); +const assert = require('assert'); if (!common.hasCrypto) { common.skip('missing crypto'); return; } -var tls = require('tls'); +const tls = require('tls'); -var fs = require('fs'); -var path = require('path'); +const fs = require('fs'); +const path = require('path'); -var key = fs.readFileSync(path.join(common.fixturesDir, 'pass-key.pem')); -var cert = fs.readFileSync(path.join(common.fixturesDir, 'pass-cert.pem')); +const passKey = fs.readFileSync(path.join(common.fixturesDir, 'pass-key.pem')); +const rawKey = fs.readFileSync(path.join(common.fixturesDir, 'raw-key.pem')); +const cert = fs.readFileSync(path.join(common.fixturesDir, 'pass-cert.pem')); -var server = tls.Server({ - key: key, +assert(Buffer.isBuffer(passKey)); +assert(Buffer.isBuffer(cert)); +assert.strictEqual(typeof passKey.toString(), 'string'); +assert.strictEqual(typeof cert.toString(), 'string'); + +const server = tls.Server({ + key: passKey, passphrase: 'passphrase', cert: cert, ca: [cert], @@ -26,24 +32,243 @@ var server = tls.Server({ }); server.listen(0, common.mustCall(function() { - var c = tls.connect({ + // Buffer + tls.connect({ + port: this.address().port, + key: passKey, + passphrase: 'passphrase', + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: rawKey, + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: rawKey, + passphrase: 'ignored', + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); + + // Buffer[] + tls.connect({ + port: this.address().port, + key: [passKey], + passphrase: 'passphrase', + cert: [cert], + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [rawKey], + cert: [cert], + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [rawKey], + passphrase: 'ignored', + cert: [cert], + rejectUnauthorized: false + }, common.mustCall(function() {})); + + // string + tls.connect({ + port: this.address().port, + key: passKey.toString(), + passphrase: 'passphrase', + cert: cert.toString(), + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: rawKey.toString(), + cert: cert.toString(), + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: rawKey.toString(), + passphrase: 'ignored', + cert: cert.toString(), + rejectUnauthorized: false + }, common.mustCall(function() {})); + + // String[] + tls.connect({ + port: this.address().port, + key: [passKey.toString()], + passphrase: 'passphrase', + cert: [cert.toString()], + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [rawKey.toString()], + cert: [cert.toString()], + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [rawKey.toString()], + passphrase: 'ignored', + cert: [cert.toString()], + rejectUnauthorized: false + }, common.mustCall(function() {})); + + // Object[] + tls.connect({ port: this.address().port, - key: key, + key: [{pem: passKey, passphrase: 'passphrase'}], + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [{pem: passKey, passphrase: 'passphrase'}], + passphrase: 'ignored', + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [{pem: passKey}], passphrase: 'passphrase', cert: cert, rejectUnauthorized: false }, common.mustCall(function() {})); - c.on('end', function() { - server.close(); + + tls.connect({ + port: this.address().port, + key: [{pem: passKey.toString(), passphrase: 'passphrase'}], + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [{pem: rawKey, passphrase: 'ignored'}], + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [{pem: rawKey.toString(), passphrase: 'ignored'}], + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [{pem: rawKey}], + passphrase: 'ignored', + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [{pem: rawKey.toString()}], + passphrase: 'ignored', + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [{pem: rawKey}], + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); + + tls.connect({ + port: this.address().port, + key: [{pem: rawKey.toString()}], + cert: cert, + rejectUnauthorized: false + }, common.mustCall(function() {})); +})).unref(); + +// Missing passphrase +assert.throws(function() { + tls.connect({ + port: server.address().port, + key: passKey, + cert: cert, + rejectUnauthorized: false }); -})); +}, /bad password read/); assert.throws(function() { tls.connect({ port: server.address().port, - key: key, + key: [passKey], + cert: cert, + rejectUnauthorized: false + }); +}, /bad password read/); + +assert.throws(function() { + tls.connect({ + port: server.address().port, + key: [{pem: passKey}], + cert: cert, + rejectUnauthorized: false + }); +}, /bad password read/); + +// Invalid passphrase +assert.throws(function() { + tls.connect({ + port: server.address().port, + key: passKey, passphrase: 'invalid', cert: cert, rejectUnauthorized: false }); -}); +}, /bad decrypt/); + +assert.throws(function() { + tls.connect({ + port: server.address().port, + key: [passKey], + passphrase: 'invalid', + cert: cert, + rejectUnauthorized: false + }); +}, /bad decrypt/); + +assert.throws(function() { + tls.connect({ + port: server.address().port, + key: [{pem: passKey}], + passphrase: 'invalid', + cert: cert, + rejectUnauthorized: false + }); +}, /bad decrypt/); + +assert.throws(function() { + tls.connect({ + port: server.address().port, + key: [{pem: passKey, passphrase: 'invalid'}], + passphrase: 'passphrase', // Valid but unused + cert: cert, + rejectUnauthorized: false + }); +}, /bad decrypt/); diff --git a/test/parallel/test-tls-ticket-cluster.js b/test/parallel/test-tls-ticket-cluster.js index 4d1667a7adcab2..fa630f4ec251bd 100644 --- a/test/parallel/test-tls-ticket-cluster.js +++ b/test/parallel/test-tls-ticket-cluster.js @@ -1,29 +1,29 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); +const assert = require('assert'); if (!common.hasCrypto) { common.skip('missing crypto'); return; } -var tls = require('tls'); +const tls = require('tls'); -var cluster = require('cluster'); -var fs = require('fs'); -var join = require('path').join; +const cluster = require('cluster'); +const fs = require('fs'); +const join = require('path').join; -var workerCount = 4; -var expectedReqCount = 16; +const workerCount = 4; +const expectedReqCount = 16; if (cluster.isMaster) { - var reusedCount = 0; - var reqCount = 0; - var lastSession = null; - var shootOnce = false; + let reusedCount = 0; + let reqCount = 0; + let lastSession = null; + let shootOnce = false; function shoot() { console.error('[master] connecting'); - var c = tls.connect(common.PORT, { + const c = tls.connect(common.PORT, { session: lastSession, rejectUnauthorized: false }, function() { @@ -41,7 +41,7 @@ if (cluster.isMaster) { } function fork() { - var worker = cluster.fork(); + const worker = cluster.fork(); worker.on('message', function(msg) { console.error('[master] got %j', msg); if (msg === 'reused') { @@ -56,27 +56,27 @@ if (cluster.isMaster) { console.error('[master] worker died'); }); } - for (var i = 0; i < workerCount; i++) { + for (let i = 0; i < workerCount; i++) { fork(); } process.on('exit', function() { - assert.equal(reqCount, expectedReqCount); - assert.equal(reusedCount + 1, reqCount); + assert.strictEqual(reqCount, expectedReqCount); + assert.strictEqual(reusedCount + 1, reqCount); }); return; } -var keyFile = join(common.fixturesDir, 'agent.key'); -var certFile = join(common.fixturesDir, 'agent.crt'); -var key = fs.readFileSync(keyFile); -var cert = fs.readFileSync(certFile); -var options = { +const keyFile = join(common.fixturesDir, 'agent.key'); +const certFile = join(common.fixturesDir, 'agent.crt'); +const key = fs.readFileSync(keyFile); +const cert = fs.readFileSync(certFile); +const options = { key: key, cert: cert }; -var server = tls.createServer(options, function(c) { +const server = tls.createServer(options, function(c) { if (c.isSessionReused()) { process.send('reused'); } else { diff --git a/test/parallel/test-tls-ticket.js b/test/parallel/test-tls-ticket.js index 8457b15e0cd325..0fa0c057f3e573 100644 --- a/test/parallel/test-tls-ticket.js +++ b/test/parallel/test-tls-ticket.js @@ -1,29 +1,29 @@ 'use strict'; -var common = require('../common'); -var assert = require('assert'); +const common = require('../common'); +const assert = require('assert'); if (!common.hasCrypto) { common.skip('missing crypto'); return; } -var tls = require('tls'); +const tls = require('tls'); -var fs = require('fs'); -var net = require('net'); -var crypto = require('crypto'); +const fs = require('fs'); +const net = require('net'); +const crypto = require('crypto'); -var keys = crypto.randomBytes(48); -var serverLog = []; -var ticketLog = []; +const keys = crypto.randomBytes(48); +const serverLog = []; +const ticketLog = []; -var serverCount = 0; +let serverCount = 0; function createServer() { - var id = serverCount++; + const id = serverCount++; - var counter = 0; - var previousKey = null; + let counter = 0; + let previousKey = null; - var server = tls.createServer({ + const server = tls.createServer({ key: fs.readFileSync(common.fixturesDir + '/keys/agent1-key.pem'), cert: fs.readFileSync(common.fixturesDir + '/keys/agent1-cert.pem'), ticketKeys: keys @@ -49,13 +49,13 @@ function createServer() { return server; } -var naturalServers = [ createServer(), createServer(), createServer() ]; +const naturalServers = [ createServer(), createServer(), createServer() ]; // 3x servers -var servers = naturalServers.concat(naturalServers).concat(naturalServers); +const servers = naturalServers.concat(naturalServers).concat(naturalServers); // Create one TCP server and balance sockets to multiple TLS server instances -var shared = net.createServer(function(c) { +const shared = net.createServer(function(c) { servers.shift().emit('connection', c); }).listen(0, function() { start(function() { @@ -64,11 +64,11 @@ var shared = net.createServer(function(c) { }); function start(callback) { - var sess = null; - var left = servers.length; + let sess = null; + let left = servers.length; function connect() { - var s = tls.connect(shared.address().port, { + const s = tls.connect(shared.address().port, { session: sess, rejectUnauthorized: false }, function() { @@ -87,15 +87,15 @@ function start(callback) { } process.on('exit', function() { - assert.equal(ticketLog.length, serverLog.length); - for (var i = 0; i < naturalServers.length - 1; i++) { - assert.notEqual(serverLog[i], serverLog[i + 1]); - assert.equal(ticketLog[i], ticketLog[i + 1]); + assert.strictEqual(ticketLog.length, serverLog.length); + for (let i = 0; i < naturalServers.length - 1; i++) { + assert.notStrictEqual(serverLog[i], serverLog[i + 1]); + assert.strictEqual(ticketLog[i], ticketLog[i + 1]); // 2nd connection should have different ticket - assert.notEqual(ticketLog[i], ticketLog[i + naturalServers.length]); + assert.notStrictEqual(ticketLog[i], ticketLog[i + naturalServers.length]); // 3rd connection should have the same ticket - assert.equal(ticketLog[i], ticketLog[i + naturalServers.length * 2]); + assert.strictEqual(ticketLog[i], ticketLog[i + naturalServers.length * 2]); } }); diff --git a/test/parallel/test-util-inspect-tuple-origin.js b/test/parallel/test-util-inspect-tuple-origin.js new file mode 100644 index 00000000000000..7529273756afe9 --- /dev/null +++ b/test/parallel/test-util-inspect-tuple-origin.js @@ -0,0 +1,37 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const inspect = require('util').inspect; +const URL = require('url').URL; + +assert.strictEqual( + inspect(URL.originFor('http://test.com:8000')), + `TupleOrigin { + scheme: http, + host: test.com, + port: 8000, + domain: null + }` + ); + +assert.strictEqual( + inspect(URL.originFor('http://test.com')), + `TupleOrigin { + scheme: http, + host: test.com, + port: undefined, + domain: null + }` + ); + + +assert.strictEqual( + inspect(URL.originFor('https://test.com')), + `TupleOrigin { + scheme: https, + host: test.com, + port: undefined, + domain: null + }` + ); diff --git a/test/parallel/test-vm-context.js b/test/parallel/test-vm-context.js index 659a092eb3e6c0..d3269d9035d010 100644 --- a/test/parallel/test-vm-context.js +++ b/test/parallel/test-vm-context.js @@ -75,3 +75,14 @@ assert.throws(function() { // https://github.com/nodejs/node/issues/6158 ctx = new Proxy({}, {}); assert.strictEqual(typeof vm.runInNewContext('String', ctx), 'function'); + +// https://github.com/nodejs/node/issues/10223 +ctx = vm.createContext(); +vm.runInContext('Object.defineProperty(this, "x", { value: 42 })', ctx); +assert.strictEqual(ctx.x, undefined); // Not copied out by cloneProperty(). +assert.strictEqual(vm.runInContext('x', ctx), 42); +vm.runInContext('x = 0', ctx); // Does not throw but x... +assert.strictEqual(vm.runInContext('x', ctx), 42); // ...should be unaltered. +assert.throws(() => vm.runInContext('"use strict"; x = 0', ctx), + /Cannot assign to read only property 'x'/); +assert.strictEqual(vm.runInContext('x', ctx), 42); diff --git a/test/parallel/test-whatwg-url-origin-for.js b/test/parallel/test-whatwg-url-origin-for.js new file mode 100644 index 00000000000000..a82f624e4e3392 --- /dev/null +++ b/test/parallel/test-whatwg-url-origin-for.js @@ -0,0 +1,19 @@ +'use strict'; + +const common = require('../common'); + +const URL = require('url').URL; +const path = require('path'); +const assert = require('assert'); +const tests = require(path.join(common.fixturesDir, 'url-tests.json')); + +for (const test of tests) { + if (typeof test === 'string') + continue; + + if (test.origin) { + const origin = URL.originFor(test.input, test.base); + // Pass true to origin.toString() to enable unicode serialization. + assert.strictEqual(origin.toString(true), test.origin); + } +} diff --git a/test/parallel/test-whatwg-url-parsing.js b/test/parallel/test-whatwg-url-parsing.js index 40ada010c1dd36..99bc3ce1c63c94 100644 --- a/test/parallel/test-whatwg-url-parsing.js +++ b/test/parallel/test-whatwg-url-parsing.js @@ -127,3 +127,71 @@ additional_tests.forEach((test) => { if (test.search) assert.strictEqual(test.search, u.search); if (test.hash) assert.strictEqual(test.hash, u.hash); }); + +// 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 = url.inspect(null, { + showHidden: 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-searchparams-append.js b/test/parallel/test-whatwg-url-searchparams-append.js new file mode 100644 index 00000000000000..1f61cb0d11bb6b --- /dev/null +++ b/test/parallel/test-whatwg-url-searchparams-append.js @@ -0,0 +1,52 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const URL = require('url').URL; + +const m = new URL('http://example.org'); +let params = m.searchParams; + +// Until we export URLSearchParams +const URLSearchParams = params.constructor; + +// 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"'); diff --git a/test/parallel/test-whatwg-url-searchparams-constructor.js b/test/parallel/test-whatwg-url-searchparams-constructor.js new file mode 100644 index 00000000000000..98349021586f1a --- /dev/null +++ b/test/parallel/test-whatwg-url-searchparams-constructor.js @@ -0,0 +1,134 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const URL = require('url').URL; + +const m = new URL('http://example.org'); +let params = m.searchParams; + +// Until we export URLSearchParams +const URLSearchParams = params.constructor; + +// 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.notEqual(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.notEqual(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.notEqual(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.notEqual(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.notEqual(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'); diff --git a/test/parallel/test-whatwg-url-searchparams-delete.js b/test/parallel/test-whatwg-url-searchparams-delete.js new file mode 100644 index 00000000000000..bdccf49baf1cc4 --- /dev/null +++ b/test/parallel/test-whatwg-url-searchparams-delete.js @@ -0,0 +1,44 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const URL = require('url').URL; + +const m = new URL('http://example.org'); +let params = m.searchParams; + +// Until we export URLSearchParams +const URLSearchParams = params.constructor; + +// 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'); + +// 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'); diff --git a/test/parallel/test-whatwg-url-searchparams-foreach.js b/test/parallel/test-whatwg-url-searchparams-foreach.js new file mode 100644 index 00000000000000..b6d684b06743b0 --- /dev/null +++ b/test/parallel/test-whatwg-url-searchparams-foreach.js @@ -0,0 +1,43 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const URL = require('url').URL; + +const m = new URL('http://example.org'); +let params = m.searchParams; + +// Until we export URLSearchParams +const URLSearchParams = params.constructor; + +let a, b, i; + +// ForEach Check +params = new URLSearchParams('a=1&b=2&c=3'); +const keys = []; +const values = []; +params.forEach(function(value, key) { + keys.push(key); + values.push(value); +}); +assert.deepStrictEqual(keys, ['a', 'b', 'c']); +assert.deepStrictEqual(values, ['1', '2', '3']); + +// 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']); + +// empty +a = new URL('http://a.b/c'); +b = a.searchParams; +for (i of b) { + assert(false, 'should not be reached'); +} diff --git a/test/parallel/test-whatwg-url-searchparams-get.js b/test/parallel/test-whatwg-url-searchparams-get.js new file mode 100644 index 00000000000000..667738f817b707 --- /dev/null +++ b/test/parallel/test-whatwg-url-searchparams-get.js @@ -0,0 +1,35 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const URL = require('url').URL; + +const m = new URL('http://example.org'); +let params = m.searchParams; + +// Until we export URLSearchParams +const URLSearchParams = params.constructor; + +// 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'), ''); + +// More get() basics +params = new URLSearchParams('first=second&third&&'); +assert.notEqual(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.'); diff --git a/test/parallel/test-whatwg-url-searchparams-getall.js b/test/parallel/test-whatwg-url-searchparams-getall.js new file mode 100644 index 00000000000000..8333982d688c3b --- /dev/null +++ b/test/parallel/test-whatwg-url-searchparams-getall.js @@ -0,0 +1,43 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const URL = require('url').URL; + +const m = new URL('http://example.org'); +let params = m.searchParams; + +// Until we export URLSearchParams +const URLSearchParams = params.constructor; + +let matches; + +// 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']); + +// 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'); diff --git a/test/parallel/test-whatwg-url-searchparams-has.js b/test/parallel/test-whatwg-url-searchparams-has.js new file mode 100644 index 00000000000000..c884227e0b0f1d --- /dev/null +++ b/test/parallel/test-whatwg-url-searchparams-has.js @@ -0,0 +1,39 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const URL = require('url').URL; + +const m = new URL('http://example.org'); +let params = m.searchParams; + +// Until we export URLSearchParams +const URLSearchParams = params.constructor; + +// 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)); + +// 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"'); diff --git a/test/parallel/test-whatwg-url-searchparams-set.js b/test/parallel/test-whatwg-url-searchparams-set.js new file mode 100644 index 00000000000000..2d9ae8aaa8d021 --- /dev/null +++ b/test/parallel/test-whatwg-url-searchparams-set.js @@ -0,0 +1,38 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const URL = require('url').URL; + +const m = new URL('http://example.org'); +let params = m.searchParams; + +// Until we export URLSearchParams +const URLSearchParams = params.constructor; + +// 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'); + +// 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"'); diff --git a/test/parallel/test-whatwg-url-searchparams-stringifier.js b/test/parallel/test-whatwg-url-searchparams-stringifier.js new file mode 100644 index 00000000000000..0a53df634454b6 --- /dev/null +++ b/test/parallel/test-whatwg-url-searchparams-stringifier.js @@ -0,0 +1,116 @@ +'use strict'; + +require('../common'); +const assert = require('assert'); +const URL = require('url').URL; + +const m = new URL('http://example.org'); +let params = m.searchParams; + +// Until we export URLSearchParams +const URLSearchParams = params.constructor; + +// 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'); diff --git a/test/parallel/test-whatwg-url-searchparams.js b/test/parallel/test-whatwg-url-searchparams.js index 99e2e6a748c264..54743b97a31da9 100644 --- a/test/parallel/test-whatwg-url-searchparams.js +++ b/test/parallel/test-whatwg-url-searchparams.js @@ -29,8 +29,21 @@ assert.strictEqual(sp.toString(), serialized); assert.strictEqual(m.search, `?${serialized}`); +assert.strictEqual(sp[Symbol.iterator], sp.entries); + var key, val, n = 0; for ([key, val] of sp) { assert.strictEqual(key, 'a'); assert.strictEqual(val, String(values[n++])); } +n = 0; +for (key of sp.keys()) { + assert.strictEqual(key, 'a'); +} +n = 0; +for (val of sp.values()) { + assert.strictEqual(val, String(values[n++])); +} + +m.search = '?a=a&b=b'; +assert.strictEqual(sp.toString(), 'a=a&b=b'); diff --git a/test/pseudo-tty/stdin-setrawmode.out b/test/pseudo-tty/stdin-setrawmode.out new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/test/pseudo-tty/testcfg.py b/test/pseudo-tty/testcfg.py index 96b30253498857..40396db247e279 100644 --- a/test/pseudo-tty/testcfg.py +++ b/test/pseudo-tty/testcfg.py @@ -142,8 +142,7 @@ def ListTests(self, current_path, path, arch, mode): file_path = file_prefix + ".js" output_path = file_prefix + ".out" if not exists(output_path): - print "Could not find %s" % output_path - continue + raise Exception("Could not find %s" % output_path) result.append(TTYTestCase(test, file_path, output_path, arch, mode, self.context, self)) return result diff --git a/test/sequential/test-buffer-creation-regression.js b/test/sequential/test-buffer-creation-regression.js new file mode 100644 index 00000000000000..b5c8450e036cc8 --- /dev/null +++ b/test/sequential/test-buffer-creation-regression.js @@ -0,0 +1,36 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); + +function test(arrayBuffer, offset, length) { + const uint8Array = new Uint8Array(arrayBuffer, offset, length); + for (let i = 0; i < length; i += 1) { + uint8Array[i] = 1; + } + + const buffer = Buffer.from(arrayBuffer, offset, length); + for (let i = 0; i < length; i += 1) { + assert.strictEqual(buffer[i], 1); + } +} + +const acceptableOOMErrors = [ + 'Array buffer allocation failed', + 'Invalid array buffer length' +]; + +const size = 8589934592; /* 1 << 33 */ +const offset = 4294967296; /* 1 << 32 */ +const length = 1000; +let arrayBuffer; + +try { + arrayBuffer = new ArrayBuffer(size); +} catch (e) { + if (e instanceof RangeError && acceptableOOMErrors.includes(e.message)) + return common.skip(`Unable to allocate ${size} bytes for ArrayBuffer`); + throw e; +} + +test(arrayBuffer, offset, length); diff --git a/test/sequential/test-module-loading.js b/test/sequential/test-module-loading.js index f500700f9dbbb6..61746a282f5eaa 100644 --- a/test/sequential/test-module-loading.js +++ b/test/sequential/test-module-loading.js @@ -69,6 +69,13 @@ assert.strictEqual(threeFolder, threeIndex); assert.notStrictEqual(threeFolder, three); console.error('test package.json require() loading'); +assert.throws( + function() { + require('../fixtures/packages/invalid'); + }, + /^SyntaxError: Error parsing \S+: Unexpected token , in JSON at position 1$/ +); + assert.strictEqual(require('../fixtures/packages/index').ok, 'ok', 'Failed loading package'); assert.strictEqual(require('../fixtures/packages/main').ok, 'ok', diff --git a/tools/eslint-rules/assert-throws-arguments.js b/tools/eslint-rules/assert-throws-arguments.js index 434a0ca455b471..3b51188c0c89bc 100644 --- a/tools/eslint-rules/assert-throws-arguments.js +++ b/tools/eslint-rules/assert-throws-arguments.js @@ -21,7 +21,8 @@ function checkThrowsArguments(context, node) { }); } else if (args.length > 1) { const error = args[1]; - if (error.type === 'Literal' && typeof error.value === 'string') { + if (error.type === 'Literal' && typeof error.value === 'string' || + error.type === 'TemplateLiteral') { context.report({ message: 'Unexpected string as second argument', node: error diff --git a/tools/macosx-firewall.sh b/tools/macosx-firewall.sh new file mode 100755 index 00000000000000..c1de916e3c87ea --- /dev/null +++ b/tools/macosx-firewall.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Script that adds rules to Mac OS X Socket Firewall to avoid +# popups asking to accept incoming network connections when +# running tests. +SFW="/usr/libexec/ApplicationFirewall/socketfilterfw" +TOOLSDIR="`dirname \"$0\"`" +TOOLSDIR="`( cd \"$TOOLSDIR\" && pwd) `" +ROOTDIR="`( cd \"$TOOLSDIR/..\" && pwd) `" +OUTDIR="$TOOLSDIR/../out" +# Using cd and pwd here so that the path used for socketfilterfw does not +# contain a '..', which seems to cause the rules to be incorrectly added +# and they are not removed when this script is re-run. Instead the new +# rules are simply appended. By using pwd we can get the full path +# without '..' and things work as expected. +OUTDIR="`( cd \"$OUTDIR\" && pwd) `" +NODE_RELEASE="$OUTDIR/Release/node" +NODE_DEBUG="$OUTDIR/Debug/node" +NODE_LINK="$ROOTDIR/node" +CCTEST_RELEASE="$OUTDIR/Release/cctest" +CCTEST_DEBUG="$OUTDIR/Debug/cctest" + +if [ -f $SFW ]; +then + # Duplicating these commands on purpose as the symbolic link node might be + # linked to either out/Debug/node or out/Release/node depending on the + # BUILDTYPE. + $SFW --remove "$NODE_DEBUG" + $SFW --remove "$NODE_DEBUG" + $SFW --remove "$NODE_RELEASE" + $SFW --remove "$NODE_RELEASE" + $SFW --remove "$NODE_LINK" + $SFW --remove "$CCTEST_DEBUG" + $SFW --remove "$CCTEST_RELEASE" + + $SFW --add "$NODE_DEBUG" + $SFW --add "$NODE_RELEASE" + $SFW --add "$NODE_LINK" + $SFW --add "$CCTEST_DEBUG" + $SFW --add "$CCTEST_RELEASE" + + $SFW --unblock "$NODE_DEBUG" + $SFW --unblock "$NODE_RELEASE" + $SFW --unblock "$NODE_LINK" + $SFW --unblock "$CCTEST_DEBUG" + $SFW --unblock "$CCTEST_RELEASE" +else + echo "SocketFirewall not found in location: $SFW" +fi diff --git a/tools/msvs/msi/product.wxs b/tools/msvs/msi/product.wxs index db2a74a7054e44..a21a3bb3ef1659 100755 --- a/tools/msvs/msi/product.wxs +++ b/tools/msvs/msi/product.wxs @@ -357,6 +357,7 @@ + diff --git a/tools/test.py b/tools/test.py index 4a272475ccfffc..c8edca2b991ad2 100755 --- a/tools/test.py +++ b/tools/test.py @@ -683,11 +683,12 @@ def Execute(args, context, timeout=None, env={}, faketty=False): if faketty: import pty (out_master, fd_out) = pty.openpty() - fd_err = fd_out + fd_in = fd_err = fd_out pty_out = out_master else: (fd_out, outname) = tempfile.mkstemp() (fd_err, errname) = tempfile.mkstemp() + fd_in = 0 pty_out = None # Extend environment @@ -699,6 +700,7 @@ def Execute(args, context, timeout=None, env={}, faketty=False): context, timeout, args = args, + stdin = fd_in, stdout = fd_out, stderr = fd_err, env = env_copy,