From 5a78c6c0a60a7cb34bff8ee983712e7847010840 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 13 Nov 2017 16:44:30 -0200 Subject: [PATCH 001/134] doc: improve assert documentation 1) Separate all loose and strict functions. 2) Stronger outline the used comparison rules in (not)deepStrictEqual 3) Fix SameValue comparison info Backport-PR-URL: https://github.com/nodejs/node/pull/19230 PR-URL: https://github.com/nodejs/node/pull/17002 Reviewed-By: Refael Ackermann Reviewed-By: James M Snell Reviewed-By: Vse Mozhet Byt Reviewed-By: Anna Henningsen --- doc/api/assert.md | 91 +++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index 6935a9db4bda64..058aff858be8e5 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -101,7 +101,7 @@ assert.deepEqual(obj1, obj4); If the values are not equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the `message` -parameter is an instance of an `Error` then it will be thrown instead of the +parameter is an instance of an [`Error`][] then it will be thrown instead of the `AssertionError`. ## assert.deepStrictEqual(actual, expected[, message]) @@ -136,50 +136,50 @@ changes: * `expected` {any} * `message` {any} -Identical to [`assert.deepEqual()`][] with the following exceptions: +Tests for deep equality between the `actual` and `expected` parameters. +"Deep" equality means that the enumerable "own" properties of child objects +are recursively evaluated also by the following rules. -1. Primitive values besides `NaN` are compared using the [Strict Equality - Comparison][] ( `===` ). Set and Map values, Map keys and `NaN` are compared - using the [SameValueZero][] comparison (which means they are free of the - [caveats][]). -2. [`[[Prototype]]`][prototype-spec] of objects are compared using +### Comparison details + +* Primitive values are compared using the [SameValue Comparison][], used by + [`Object.is()`][]. +* [Type tags][Object.prototype.toString()] of objects should be the same. +* [`[[Prototype]]`][prototype-spec] of objects are compared using the [Strict Equality Comparison][] too. -3. [Type tags][Object.prototype.toString()] of objects should be the same. -4. [Object wrappers][] are compared both as objects and unwrapped values. -5. `0` and `-0` are not considered equal. -6. Enumerable own [`Symbol`][] properties are compared as well. +* Only [enumerable "own" properties][] are considered. +* [`Error`][] names and messages are always compared, even if these are not + enumerable properties. +* Enumerable own [`Symbol`][] properties are compared as well. +* [Object wrappers][] are compared both as objects and unwrapped values. +* Object properties are compared unordered. +* Map keys and Set items are compared unordered. +* Recursion stops when both sides differ or both sides encounter a circular + reference. ```js const assert = require('assert'); -assert.deepEqual({ a: 1 }, { a: '1' }); -// OK, because 1 == '1' - assert.deepStrictEqual({ a: 1 }, { a: '1' }); // AssertionError: { a: 1 } deepStrictEqual { a: '1' } -// because 1 !== '1' using strict equality +// because 1 !== '1' using SameValue comparison // The following objects don't have own properties const date = new Date(); const object = {}; const fakeDate = {}; - Object.setPrototypeOf(fakeDate, Date.prototype); -assert.deepEqual(object, fakeDate); -// OK, doesn't check [[Prototype]] assert.deepStrictEqual(object, fakeDate); // AssertionError: {} deepStrictEqual Date {} // Different [[Prototype]] -assert.deepEqual(date, fakeDate); -// OK, doesn't check type tags assert.deepStrictEqual(date, fakeDate); // AssertionError: 2017-03-11T14:25:31.849Z deepStrictEqual Date {} // Different type tags assert.deepStrictEqual(NaN, NaN); -// OK, because of the SameValueZero comparison +// OK, because of the SameValue comparison assert.deepStrictEqual(new Number(1), new Number(2)); // Fails because the wrapped number is unwrapped and compared as well. @@ -202,7 +202,7 @@ assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol2]: 1 }); If the values are not equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the `message` -parameter is an instance of an `Error` then it will be thrown instead of the +parameter is an instance of an [`Error`][] then it will be thrown instead of the `AssertionError`. ## assert.doesNotThrow(block[, error][, message]) @@ -298,7 +298,7 @@ assert.equal({ a: { b: 1 } }, { a: { b: 1 } }); If the values are not equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the `message` -parameter is an instance of an `Error` then it will be thrown instead of the +parameter is an instance of an [`Error`][] then it will be thrown instead of the `AssertionError`. ## assert.fail([message]) @@ -314,7 +314,7 @@ added: v0.1.21 Throws an `AssertionError`. If `message` is falsy, the error message is set as the values of `actual` and `expected` separated by the provided `operator`. If -the `message` parameter is an instance of an `Error` then it will be thrown +the `message` parameter is an instance of an [`Error`][] then it will be thrown instead of the `AssertionError`. If just the two `actual` and `expected` arguments are provided, `operator` will default to `'!='`. If `message` is provided only it will be used as the error message, the other arguments will be @@ -451,7 +451,7 @@ assert.notDeepEqual(obj1, obj4); If the values are deeply equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the `message` -parameter is an instance of an `Error` then it will be thrown instead of the +parameter is an instance of an [`Error`][] then it will be thrown instead of the `AssertionError`. ## assert.notDeepStrictEqual(actual, expected[, message]) @@ -491,9 +491,6 @@ Tests for deep strict inequality. Opposite of [`assert.deepStrictEqual()`][]. ```js const assert = require('assert'); -assert.notDeepEqual({ a: 1 }, { a: '1' }); -// AssertionError: { a: 1 } notDeepEqual { a: '1' } - assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); // OK ``` @@ -501,8 +498,8 @@ assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); If the values are deeply and strictly equal, an `AssertionError` is thrown with a `message` property set equal to the value of the `message` parameter. If the `message` parameter is undefined, a default error message is assigned. If the -`message` parameter is an instance of an `Error` then it will be thrown instead -of the `AssertionError`. +`message` parameter is an instance of an [`Error`][] then it will be thrown +instead of the `AssertionError`. ## assert.notEqual(actual, expected[, message]) + +When using the `strict mode`, any `assert` function will use the equality used in +the strict function mode. So [`assert.deepEqual()`][] will, for example, work the +same as [`assert.deepStrictEqual()`][]. + +It can be accessed using: + +```js +const assert = require('assert').strict; +``` + +## Legacy mode + +> Stability: 0 - Deprecated: Use strict mode instead. + +When accessing `assert` directly instead of using the `strict` property, the +[Abstract Equality Comparison][] will be used for any function without a +"strict" in its name (e.g. [`assert.deepEqual()`][]). + +It can be accessed using: + +```js +const assert = require('assert'); +``` + +It is recommended to use the [`strict mode`][] instead as the +[Abstract Equality Comparison][] can often have surprising results. Especially +in case of [`assert.deepEqual()`][] as the used comparison rules there are very +lax. + +E.g. + +```js +// WARNING: This does not throw an AssertionError! +assert.deepEqual(/a/gi, new Date()); +``` + ## assert(value[, message]) ```js -// THIS IS A MISTAKE! DO NOT DO THIS! -assert.throws(myFunction, 'missing foo', 'did not throw with expected message'); - -// Do this instead. -assert.throws(myFunction, /missing foo/, 'did not throw with expected message'); +function throwingFirst() { + throw new Error('First'); +} +function throwingSecond() { + throw new Error('Second'); +} +function notThrowing() {} + +// The second argument is a string and the input function threw an Error. +// In that case both cases do not throw as neither is going to try to +// match for the error message thrown by the input function! +assert.throws(throwingFirst, 'Second'); +assert.throws(throwingSecond, 'Second'); + +// The string is only used (as message) in case the function does not throw: +assert.throws(notThrowing, 'Second'); +// AssertionError [ERR_ASSERTION]: Missing expected exception: Second + +// If it was intended to match for the error message do this instead: +assert.throws(throwingSecond, /Second$/); +// Does not throw because the error messages match. +assert.throws(throwingFirst, /Second$/); +// Throws a error: +// Error: First +// at throwingFirst (repl:2:9) ``` +Due to the confusing notation, it is recommended not to use a string as the +second argument. This might lead to difficult-to-spot errors. + ## Caveats For the following cases, consider using ES2015 [`Object.is()`][], diff --git a/lib/assert.js b/lib/assert.js index cb590ca8af0c2b..6aae1a33a428be 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -211,7 +211,11 @@ function expectedException(actual, expected) { return expected.call({}, actual) === true; } -function tryBlock(block) { +function getActual(block) { + if (typeof block !== 'function') { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'block', 'Function', + block); + } try { block(); } catch (e) { @@ -219,60 +223,61 @@ function tryBlock(block) { } } -function innerThrows(shouldThrow, block, expected, message) { - var details = ''; +// Expected to throw an error. +assert.throws = function throws(block, error, message) { + const actual = getActual(block); - if (typeof block !== 'function') { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'block', 'Function', - block); - } + if (typeof error === 'string') { + if (arguments.length === 3) + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', + 'error', + ['Function', 'RegExp'], + error); - if (typeof expected === 'string') { - message = expected; - expected = null; + message = error; + error = null; } - const actual = tryBlock(block); - - if (shouldThrow === true) { - if (actual === undefined) { - if (expected && expected.name) { - details += ` (${expected.name})`; - } - details += message ? `: ${message}` : '.'; - innerFail({ - actual, - expected, - operator: 'throws', - message: `Missing expected exception${details}`, - stackStartFn: assert.throws - }); - } - if (expected && expectedException(actual, expected) === false) { - throw actual; - } - } else if (actual !== undefined) { - if (!expected || expectedException(actual, expected)) { - details = message ? `: ${message}` : '.'; - innerFail({ - actual, - expected, - operator: 'doesNotThrow', - message: `Got unwanted exception${details}\n${actual.message}`, - stackStartFn: assert.doesNotThrow - }); + if (actual === undefined) { + let details = ''; + if (error && error.name) { + details += ` (${error.name})`; } + details += message ? `: ${message}` : '.'; + innerFail({ + actual, + expected: error, + operator: 'throws', + message: `Missing expected exception${details}`, + stackStartFn: throws + }); + } + if (error && expectedException(actual, error) === false) { throw actual; } -} - -// Expected to throw an error. -assert.throws = function throws(block, error, message) { - innerThrows(true, block, error, message); }; assert.doesNotThrow = function doesNotThrow(block, error, message) { - innerThrows(false, block, error, message); + const actual = getActual(block); + if (actual === undefined) + return; + + if (typeof error === 'string') { + message = error; + error = null; + } + + if (!error || expectedException(actual, error)) { + const details = message ? `: ${message}` : '.'; + innerFail({ + actual, + expected: error, + operator: 'doesNotThrow', + message: `Got unwanted exception${details}\n${actual.message}`, + stackStartFn: doesNotThrow + }); + } + throw actual; }; assert.ifError = function ifError(err) { if (err) throw err; }; diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index dd9b0906097643..c260eabe2e3e8d 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -773,3 +773,14 @@ common.expectsError( message: 'null == true' } ); + +common.expectsError( + // eslint-disable-next-line no-restricted-syntax + () => assert.throws(() => {}, 'Error message', 'message'), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "error" argument must be one of type Function or RegExp. ' + + 'Received type string' + } +); From 745709396c04d1d12bfc1c2a1c3e7b21bab8911d Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 11 Dec 2017 05:04:17 -0200 Subject: [PATCH 007/134] doc: improve .throws RegExp info It was not clear why the error name is actually also tested for when using a regular expression. This is now clarified. Backport-PR-URL: https://github.com/nodejs/node/pull/19230 PR-URL: https://github.com/nodejs/node/pull/17585 Reviewed-By: Rich Trott Reviewed-By: Benjamin Gruenbaum Reviewed-By: Matteo Collina Reviewed-By: James M Snell Reviewed-By: Gireesh Punathil Reviewed-By: Evan Lucas --- doc/api/assert.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index 1bbb2c1f367027..5e4d0e75f53e60 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -738,12 +738,15 @@ assert.throws( Validate error message using [`RegExp`][]: +Using a regular expression runs `.toString` on the error object, and will +therefore also include the error name. + ```js assert.throws( () => { throw new Error('Wrong value'); }, - /value/ + /^Error: Wrong value$/ ); ``` From ebd60fa505c5c4b5606064fa25dd17c687095bc5 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 9 Dec 2017 22:54:44 -0200 Subject: [PATCH 008/134] assert: .throws accept objects From now on it is possible to use a validation object in throws instead of the other possibilites. Backport-PR-URL: https://github.com/nodejs/node/pull/19230 PR-URL: https://github.com/nodejs/node/pull/17584 Refs: https://github.com/nodejs/node/pull/17557 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Luigi Pinca Reviewed-By: James M Snell Reviewed-By: Matteo Collina Reviewed-By: Ron Korving Reviewed-By: Yuta Hiroto --- doc/api/assert.md | 26 +++++++++-- lib/assert.js | 43 ++++++++++++++++-- test/parallel/test-assert.js | 86 +++++++++++++++++++++++++++++++----- 3 files changed, 138 insertions(+), 17 deletions(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index 5e4d0e75f53e60..d53bccd21a998d 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -709,18 +709,21 @@ instead of the `AssertionError`. * `block` {Function} -* `error` {RegExp|Function} +* `error` {RegExp|Function|object} * `message` {any} Expects the function `block` to throw an error. -If specified, `error` can be a constructor, [`RegExp`][], or validation -function. +If specified, `error` can be a constructor, [`RegExp`][], a validation +function, or an object where each property will be tested for. If specified, `message` will be the message provided by the `AssertionError` if the block fails to throw. @@ -766,6 +769,23 @@ assert.throws( ); ``` +Custom error object / error instance: + +```js +assert.throws( + () => { + const err = new TypeError('Wrong value'); + err.code = 404; + throw err; + }, + { + name: 'TypeError', + message: 'Wrong value' + // Note that only properties on the error object will be tested! + } +); +``` + Note that `error` can not be a string. If a string is provided as the second argument, then `error` is assumed to be omitted and the string will be used for `message` instead. This can lead to easy-to-miss mistakes. Please read the diff --git a/lib/assert.js b/lib/assert.js index 6aae1a33a428be..4781f170e359da 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -23,6 +23,7 @@ const { isDeepEqual, isDeepStrictEqual } = require('internal/util/comparisons'); const errors = require('internal/errors'); +const { inspect } = require('util'); // The assert module provides functions that throw // AssertionError's when particular conditions are not met. The @@ -196,10 +197,44 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) { } }; -function expectedException(actual, expected) { +function createMsg(msg, key, actual, expected) { + if (msg) + return msg; + return `${key}: expected ${inspect(expected[key])}, ` + + `not ${inspect(actual[key])}`; +} + +function expectedException(actual, expected, msg) { if (typeof expected !== 'function') { - // Should be a RegExp, if not fail hard - return expected.test(actual); + if (expected instanceof RegExp) + return expected.test(actual); + // assert.doesNotThrow does not accept objects. + if (arguments.length === 2) { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'expected', + ['Function', 'RegExp'], expected); + } + // The name and message could be non enumerable. Therefore test them + // explicitly. + if ('name' in expected) { + assert.strictEqual( + actual.name, + expected.name, + createMsg(msg, 'name', actual, expected)); + } + if ('message' in expected) { + assert.strictEqual( + actual.message, + expected.message, + createMsg(msg, 'message', actual, expected)); + } + const keys = Object.keys(expected); + for (const key of keys) { + assert.deepStrictEqual( + actual[key], + expected[key], + createMsg(msg, key, actual, expected)); + } + return true; } // Guard instanceof against arrow functions as they don't have a prototype. if (expected.prototype !== undefined && actual instanceof expected) { @@ -252,7 +287,7 @@ assert.throws = function throws(block, error, message) { stackStartFn: throws }); } - if (error && expectedException(actual, error) === false) { + if (error && expectedException(actual, error, message) === false) { throw actual; } }; diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index c260eabe2e3e8d..949318d65bd8e2 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -39,16 +39,6 @@ assert.ok(a.AssertionError.prototype instanceof Error, assert.throws(makeBlock(a, false), a.AssertionError, 'ok(false)'); -// Using a object as second arg results in a failure -assert.throws( - () => { assert.throws(() => { throw new Error(); }, { foo: 'bar' }); }, - common.expectsError({ - type: TypeError, - message: 'expected.test is not a function' - }) -); - - assert.doesNotThrow(makeBlock(a, true), a.AssertionError, 'ok(true)'); assert.doesNotThrow(makeBlock(a, 'test', 'ok(\'test\')')); @@ -784,3 +774,79 @@ common.expectsError( 'Received type string' } ); + +{ + const errFn = () => { + const err = new TypeError('Wrong value'); + err.code = 404; + throw err; + }; + const errObj = { + name: 'TypeError', + message: 'Wrong value' + }; + assert.throws(errFn, errObj); + + errObj.code = 404; + assert.throws(errFn, errObj); + + errObj.code = '404'; + common.expectsError( + // eslint-disable-next-line no-restricted-syntax + () => assert.throws(errFn, errObj), + { + code: 'ERR_ASSERTION', + type: assert.AssertionError, + message: 'code: expected \'404\', not 404' + } + ); + + errObj.code = 404; + errObj.foo = 'bar'; + common.expectsError( + // eslint-disable-next-line no-restricted-syntax + () => assert.throws(errFn, errObj), + { + code: 'ERR_ASSERTION', + type: assert.AssertionError, + message: 'foo: expected \'bar\', not undefined' + } + ); + + common.expectsError( + () => assert.throws(() => { throw new Error(); }, { foo: 'bar' }, 'foobar'), + { + type: assert.AssertionError, + code: 'ERR_ASSERTION', + message: 'foobar' + } + ); + + common.expectsError( + () => assert.doesNotThrow(() => { throw new Error(); }, { foo: 'bar' }), + { + type: TypeError, + code: 'ERR_INVALID_ARG_TYPE', + message: 'The "expected" argument must be one of type Function or ' + + 'RegExp. Received type object' + } + ); + + assert.throws(() => { throw new Error('e'); }, new Error('e')); + common.expectsError( + () => assert.throws(() => { throw new TypeError('e'); }, new Error('e')), + { + type: assert.AssertionError, + code: 'ERR_ASSERTION', + message: "name: expected 'Error', not 'TypeError'" + } + ); + common.expectsError( + () => assert.throws(() => { throw new Error('foo'); }, new Error('')), + { + type: assert.AssertionError, + code: 'ERR_ASSERTION', + message: "message: expected '', not 'foo'" + } + ); +} From f96ea47cf50ffdad50dbc70d7d4302f2e2cd8df1 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Thu, 28 Dec 2017 18:58:08 +0100 Subject: [PATCH 009/134] assert: fix strict regression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using `assert()` or `assert.ok()` resulted in a error since a refactoring. Refs: https://github.com/nodejs/node/pull/17582 Backport-PR-URL: https://github.com/nodejs/node/pull/19230 PR-URL: https://github.com/nodejs/node/pull/17903 Refs: https://github.com/nodejs/node/pull/17582 Reviewed-By: Anatoli Papirovski Reviewed-By: Tobias Nießen Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- lib/assert.js | 10 +++++++++- test/parallel/test-assert.js | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/assert.js b/lib/assert.js index 4781f170e359da..05daf6d05ee55a 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -319,7 +319,15 @@ assert.ifError = function ifError(err) { if (err) throw err; }; // Expose a strict only variant of assert function strict(value, message) { - if (!value) innerFail(value, true, message, '==', strict); + if (!value) { + innerFail({ + actual: value, + expected: true, + message, + operator: '==', + stackStartFn: strict + }); + } } assert.strict = Object.assign(strict, assert, { equal: assert.strictEqual, diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 949318d65bd8e2..b2debe1d8001ac 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -753,6 +753,14 @@ common.expectsError( assert.equal(Object.keys(assert).length, Object.keys(a).length); /* eslint-enable no-restricted-properties */ assert(7); + common.expectsError( + () => assert(), + { + code: 'ERR_ASSERTION', + type: assert.AssertionError, + message: 'undefined == true' + } + ); } common.expectsError( From b35eabb83771aab59dc9fdff33df8a06d98598c3 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sun, 7 Jan 2018 23:17:29 +0100 Subject: [PATCH 010/134] lib: handle `throw undefined` in assert.throws() And make `assert.doesNotThrow()` handle it as well. Backport-PR-URL: https://github.com/nodejs/node/pull/19230 PR-URL: https://github.com/nodejs/node/pull/18029 Fixes: https://github.com/nodejs/node/issues/18027 Reviewed-By: Anna Henningsen Reviewed-By: Ruben Bridgewater Reviewed-By: Khaidi Chu Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Daniel Bevenius Reviewed-By: Colin Ihrig Reviewed-By: James M Snell --- lib/assert.js | 9 ++++++--- test/parallel/test-assert.js | 12 ++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index 05daf6d05ee55a..c3570afeb38a3a 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -31,6 +31,8 @@ const { inspect } = require('util'); const assert = module.exports = ok; +const NO_EXCEPTION_SENTINEL = {}; + // All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that // may be undefined if not provided. All assertion methods provide @@ -256,6 +258,7 @@ function getActual(block) { } catch (e) { return e; } + return NO_EXCEPTION_SENTINEL; } // Expected to throw an error. @@ -273,7 +276,7 @@ assert.throws = function throws(block, error, message) { error = null; } - if (actual === undefined) { + if (actual === NO_EXCEPTION_SENTINEL) { let details = ''; if (error && error.name) { details += ` (${error.name})`; @@ -294,7 +297,7 @@ assert.throws = function throws(block, error, message) { assert.doesNotThrow = function doesNotThrow(block, error, message) { const actual = getActual(block); - if (actual === undefined) + if (actual === NO_EXCEPTION_SENTINEL) return; if (typeof error === 'string') { @@ -308,7 +311,7 @@ assert.doesNotThrow = function doesNotThrow(block, error, message) { actual, expected: error, operator: 'doesNotThrow', - message: `Got unwanted exception${details}\n${actual.message}`, + message: `Got unwanted exception${details}\n${actual && actual.message}`, stackStartFn: doesNotThrow }); } diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index b2debe1d8001ac..462c01425dab5b 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -857,4 +857,16 @@ common.expectsError( message: "message: expected '', not 'foo'" } ); + + // eslint-disable-next-line no-throw-literal + assert.throws(() => { throw undefined; }, /undefined/); + common.expectsError( + // eslint-disable-next-line no-throw-literal + () => assert.doesNotThrow(() => { throw undefined; }), + { + type: assert.AssertionError, + code: 'ERR_ASSERTION', + message: 'Got unwanted exception.\nundefined' + } + ); } From fd4c05ab56fb40f4f855b76dca66f5c488207c68 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 9 Dec 2017 05:34:16 -0200 Subject: [PATCH 011/134] util: fix custom inspect description Using a custom inspect function on the inspected object is deprecated. Remove the reference from the option description to make sure the user will read about the deprecation in the more detailed description. Backport-PR-URL: https://github.com/nodejs/node/pull/19230 PR-URL: https://github.com/nodejs/node/pull/17576 Reviewed-By: Anna Henningsen --- doc/api/util.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/api/util.md b/doc/api/util.md index 976621ddb383e3..a001124824f0a5 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -342,8 +342,7 @@ changes: codes. Defaults to `false`. Colors are customizable, see [Customizing `util.inspect` colors][]. * `customInspect` {boolean} If `false`, then custom `inspect(depth, opts)` - functions exported on the `object` being inspected will not be called. - Defaults to `true`. + functions will not be called. Defaults to `true`. * `showProxy` {boolean} If `true`, then objects and functions that are `Proxy` objects will be introspected to show their `target` and `handler` objects. Defaults to `false`. From ce3a5af69f81893d53cf68a465eea7e6e19efcf9 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 9 Dec 2017 05:33:00 -0200 Subject: [PATCH 012/134] util: rename util.inspect argument util.inspect can actually receive any property and the description was wrong so far. This fixes it by renaming the argument to value and also updating the description. Backport-PR-URL: https://github.com/nodejs/node/pull/19230 PR-URL: https://github.com/nodejs/node/pull/17576 Reviewed-By: Anna Henningsen --- lib/util.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/util.js b/lib/util.js index cd6321cfe5270e..bb805a082b27d6 100644 --- a/lib/util.js +++ b/lib/util.js @@ -257,14 +257,14 @@ function debuglog(set) { } /** - * Echos the value of a value. Tries to print the value out + * Echos the value of any input. Tries to print the value out * in the best way possible given the different types. * - * @param {Object} obj The object to print out. + * @param {any} value The value to print out. * @param {Object} opts Optional options object that alters the output. */ -/* Legacy: obj, showHidden, depth, colors*/ -function inspect(obj, opts) { +/* Legacy: value, showHidden, depth, colors*/ +function inspect(value, opts) { // Default options const ctx = { seen: [], @@ -298,7 +298,7 @@ function inspect(obj, opts) { } if (ctx.colors) ctx.stylize = stylizeWithColor; if (ctx.maxArrayLength === null) ctx.maxArrayLength = Infinity; - return formatValue(ctx, obj, ctx.depth); + return formatValue(ctx, value, ctx.depth); } inspect.custom = customInspectSymbol; From c18ac52970b116b7d17ab7ff842e9ab5f60881f5 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 9 Dec 2017 05:27:21 -0200 Subject: [PATCH 013/134] util: add util.inspect compact option The current default formatting is not ideal and this improves the situation by formatting the output more intuitiv. 1) All object keys are now indented by 2 characters instead of sometimes 2 and sometimes 3 characters. 2) Each object key will now use an individual line instead of sharing a line potentially with multiple object keys. 3) Long strings will now be split into multiple lines in case they exceed the "lineBreak" option length (including the current indentation). 4) Opening braces are now directly behind a object property instead of using a new line. 5) Switch inspect "base" order. In case the compact option is set to `false`, inspect will now print "[Function: foo] {\n property: 'data'\n}" instead of "{ [Function: foo]\n property: 'data'\n}". Backport-PR-URL: https://github.com/nodejs/node/pull/19230 PR-URL: https://github.com/nodejs/node/pull/17576 Reviewed-By: Anna Henningsen --- doc/api/util.md | 67 ++++++++++++++ lib/util.js | 84 +++++++++++++---- test/parallel/test-util-inspect.js | 143 +++++++++++++++++++++++++++++ 3 files changed, 277 insertions(+), 17 deletions(-) diff --git a/doc/api/util.md b/doc/api/util.md index a001124824f0a5..bc1d3ae262ae50 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -316,6 +316,9 @@ stream.write('With ES6'); diff --git a/lib/util.js b/lib/util.js index bb805a082b27d6..70fd1a05564389 100644 --- a/lib/util.js +++ b/lib/util.js @@ -68,7 +68,8 @@ const inspectDefaultOptions = Object.seal({ customInspect: true, showProxy: false, maxArrayLength: 100, - breakLength: 60 + breakLength: 60, + compact: true }); const propertyIsEnumerable = Object.prototype.propertyIsEnumerable; @@ -86,6 +87,10 @@ const strEscapeSequencesReplacer = /[\x00-\x1f\x27\x5c]/g; const keyStrRegExp = /^[a-zA-Z_][a-zA-Z_0-9]*$/; const numberRegExp = /^(0|[1-9][0-9]*)$/; +const readableRegExps = {}; + +const MIN_LINE_LENGTH = 16; + // Escaped special characters. Use empty strings to fill up unused entries. const meta = [ '\\u0000', '\\u0001', '\\u0002', '\\u0003', '\\u0004', @@ -276,7 +281,8 @@ function inspect(value, opts) { showProxy: inspectDefaultOptions.showProxy, maxArrayLength: inspectDefaultOptions.maxArrayLength, breakLength: inspectDefaultOptions.breakLength, - indentationLvl: 0 + indentationLvl: 0, + compact: inspectDefaultOptions.compact }; // Legacy... if (arguments.length > 2) { @@ -374,7 +380,7 @@ function ensureDebugIsInitialized() { function formatValue(ctx, value, recurseTimes, ln) { // Primitive types cannot have properties if (typeof value !== 'object' && typeof value !== 'function') { - return formatPrimitive(ctx.stylize, value); + return formatPrimitive(ctx.stylize, value, ctx); } if (value === null) { return ctx.stylize('null', 'null'); @@ -481,10 +487,10 @@ function formatValue(ctx, value, recurseTimes, ln) { } catch (e) { /* ignore */ } if (typeof raw === 'string') { - const formatted = formatPrimitive(stylizeNoColor, raw); + const formatted = formatPrimitive(stylizeNoColor, raw, ctx); if (keyLength === raw.length) return ctx.stylize(`[String: ${formatted}]`, 'string'); - base = ` [String: ${formatted}]`; + base = `[String: ${formatted}]`; // For boxed Strings, we have to remove the 0-n indexed entries, // since they just noisy up the output and are redundant // Make boxed primitive Strings look like such @@ -505,12 +511,12 @@ function formatValue(ctx, value, recurseTimes, ln) { const name = `${constructor.name}${value.name ? `: ${value.name}` : ''}`; if (keyLength === 0) return ctx.stylize(`[${name}]`, 'special'); - base = ` [${name}]`; + base = `[${name}]`; } else if (isRegExp(value)) { // Make RegExps say that they are RegExps if (keyLength === 0 || recurseTimes < 0) return ctx.stylize(regExpToString.call(value), 'regexp'); - base = ` ${regExpToString.call(value)}`; + base = `${regExpToString.call(value)}`; } else if (isDate(value)) { if (keyLength === 0) { if (Number.isNaN(value.getTime())) @@ -518,12 +524,12 @@ function formatValue(ctx, value, recurseTimes, ln) { return ctx.stylize(dateToISOString.call(value), 'date'); } // Make dates with properties first say the date - base = ` ${dateToISOString.call(value)}`; + base = `${dateToISOString.call(value)}`; } else if (isError(value)) { // Make error with message first say the error if (keyLength === 0) return formatError(value); - base = ` ${formatError(value)}`; + base = `${formatError(value)}`; } else if (isAnyArrayBuffer(value)) { // Fast path for ArrayBuffer and SharedArrayBuffer. // Can't do the same for DataView because it has a non-primitive @@ -553,13 +559,13 @@ function formatValue(ctx, value, recurseTimes, ln) { const formatted = formatPrimitive(stylizeNoColor, raw); if (keyLength === 0) return ctx.stylize(`[Number: ${formatted}]`, 'number'); - base = ` [Number: ${formatted}]`; + base = `[Number: ${formatted}]`; } else if (typeof raw === 'boolean') { // Make boxed primitive Booleans look like such const formatted = formatPrimitive(stylizeNoColor, raw); if (keyLength === 0) return ctx.stylize(`[Boolean: ${formatted}]`, 'boolean'); - base = ` [Boolean: ${formatted}]`; + base = `[Boolean: ${formatted}]`; } else if (typeof raw === 'symbol') { const formatted = formatPrimitive(stylizeNoColor, raw); return ctx.stylize(`[Symbol: ${formatted}]`, 'symbol'); @@ -603,9 +609,42 @@ function formatNumber(fn, value) { return fn(`${value}`, 'number'); } -function formatPrimitive(fn, value) { - if (typeof value === 'string') +function formatPrimitive(fn, value, ctx) { + if (typeof value === 'string') { + if (ctx.compact === false && + value.length > MIN_LINE_LENGTH && + ctx.indentationLvl + value.length > ctx.breakLength) { + // eslint-disable-next-line max-len + const minLineLength = Math.max(ctx.breakLength - ctx.indentationLvl, MIN_LINE_LENGTH); + // eslint-disable-next-line max-len + const averageLineLength = Math.ceil(value.length / Math.ceil(value.length / minLineLength)); + const divisor = Math.max(averageLineLength, MIN_LINE_LENGTH); + var res = ''; + if (readableRegExps[divisor] === undefined) { + // Build a new RegExp that naturally breaks text into multiple lines. + // + // Rules + // 1. Greedy match all text up the max line length that ends with a + // whitespace or the end of the string. + // 2. If none matches, non-greedy match any text up to a whitespace or + // the end of the string. + // + // eslint-disable-next-line max-len, no-unescaped-regexp-dot + readableRegExps[divisor] = new RegExp(`(.|\\n){1,${divisor}}(\\s|$)|(\\n|.)+?(\\s|$)`, 'gm'); + } + const indent = ' '.repeat(ctx.indentationLvl); + const matches = value.match(readableRegExps[divisor]); + if (matches.length > 1) { + res += `${fn(strEscape(matches[0]), 'string')} +\n`; + for (var i = 1; i < matches.length - 1; i++) { + res += `${indent} ${fn(strEscape(matches[i]), 'string')} +\n`; + } + res += `${indent} ${fn(strEscape(matches[i]), 'string')}`; + return res; + } + } return fn(strEscape(value), 'string'); + } if (typeof value === 'number') return formatNumber(fn, value); if (typeof value === 'boolean') @@ -806,7 +845,7 @@ function formatProperty(ctx, value, recurseTimes, key, array) { const desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key], enumerable: true }; if (desc.value !== undefined) { - const diff = array === 0 ? 3 : 2; + const diff = array !== 0 || ctx.compact === false ? 2 : 3; ctx.indentationLvl += diff; str = formatValue(ctx, desc.value, recurseTimes, array === 0); ctx.indentationLvl -= diff; @@ -839,9 +878,19 @@ function formatProperty(ctx, value, recurseTimes, key, array) { function reduceToSingleString(ctx, output, base, braces, addLn) { const breakLength = ctx.breakLength; + var i = 0; + if (ctx.compact === false) { + const indentation = ' '.repeat(ctx.indentationLvl); + var res = `${base ? `${base} ` : ''}${braces[0]}\n${indentation} `; + for (; i < output.length - 1; i++) { + res += `${output[i]},\n${indentation} `; + } + res += `${output[i]}\n${indentation}${braces[1]}`; + return res; + } if (output.length * 2 <= breakLength) { var length = 0; - for (var i = 0; i < output.length && length <= breakLength; i++) { + for (; i < output.length && length <= breakLength; i++) { if (ctx.colors) { length += removeColors(output[i]).length + 1; } else { @@ -849,7 +898,8 @@ function reduceToSingleString(ctx, output, base, braces, addLn) { } } if (length <= breakLength) - return `${braces[0]}${base} ${join(output, ', ')} ${braces[1]}`; + return `${braces[0]}${base ? ` ${base}` : ''} ${join(output, ', ')} ` + + braces[1]; } // If the opening "brace" is too large, like in the case of "Set {", // we need to force the first item to be on the next line or the @@ -857,7 +907,7 @@ function reduceToSingleString(ctx, output, base, braces, addLn) { const indentation = ' '.repeat(ctx.indentationLvl); const extraLn = addLn === true ? `\n${indentation}` : ''; const ln = base === '' && braces[0].length === 1 ? - ' ' : `${base}\n${indentation} `; + ' ' : `${base ? ` ${base}` : base}\n${indentation} `; const str = join(output, `,\n${indentation} `); return `${extraLn}${braces[0]}${ln}${str} ${braces[1]}`; } diff --git a/test/parallel/test-util-inspect.js b/test/parallel/test-util-inspect.js index a99583d454b3f4..83f6b469d68055 100644 --- a/test/parallel/test-util-inspect.js +++ b/test/parallel/test-util-inspect.js @@ -1160,3 +1160,146 @@ if (typeof Symbol !== 'undefined') { assert.doesNotThrow(() => util.inspect(process)); /* eslint-enable accessor-pairs */ + +// Setting custom inspect property to a non-function should do nothing. +{ + const obj = { inspect: 'fhqwhgads' }; + assert.strictEqual(util.inspect(obj), "{ inspect: 'fhqwhgads' }"); +} + +{ + const o = { + a: [1, 2, [[ + 'Lorem ipsum dolor\nsit amet,\tconsectetur adipiscing elit, sed do ' + + 'eiusmod tempor incididunt ut labore et dolore magna aliqua.', + 'test', + 'foo']], 4], + b: new Map([['za', 1], ['zb', 'test']]) + }; + + let out = util.inspect(o, { compact: true, depth: 5, breakLength: 80 }); + let expect = [ + '{ a: ', + ' [ 1,', + ' 2,', + " [ [ 'Lorem ipsum dolor\\nsit amet,\\tconsectetur adipiscing elit, " + + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',", + " 'test',", + " 'foo' ] ],", + ' 4 ],', + " b: Map { 'za' => 1, 'zb' => 'test' } }", + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect(o, { compact: false, depth: 5, breakLength: 60 }); + expect = [ + '{', + ' a: [', + ' 1,', + ' 2,', + ' [', + ' [', + ' \'Lorem ipsum dolor\\nsit amet,\\tconsectetur \' +', + ' \'adipiscing elit, sed do eiusmod tempor \' +', + ' \'incididunt ut labore et dolore magna \' +', + ' \'aliqua.\',', + ' \'test\',', + ' \'foo\'', + ' ]', + ' ],', + ' 4', + ' ],', + ' b: Map {', + ' \'za\' => 1,', + ' \'zb\' => \'test\'', + ' }', + '}' + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect(o.a[2][0][0], { compact: false, breakLength: 30 }); + expect = [ + '\'Lorem ipsum dolor\\nsit \' +', + ' \'amet,\\tconsectetur \' +', + ' \'adipiscing elit, sed do \' +', + ' \'eiusmod tempor incididunt \' +', + ' \'ut labore et dolore magna \' +', + ' \'aliqua.\'' + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect( + '12345678901234567890123456789012345678901234567890', + { compact: false, breakLength: 3 }); + expect = '\'12345678901234567890123456789012345678901234567890\''; + assert.strictEqual(out, expect); + + out = util.inspect( + '12 45 78 01 34 67 90 23 56 89 123456789012345678901234567890', + { compact: false, breakLength: 3 }); + expect = [ + '\'12 45 78 01 34 \' +', + ' \'67 90 23 56 89 \' +', + ' \'123456789012345678901234567890\'' + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect( + '12 45 78 01 34 67 90 23 56 89 1234567890123 0', + { compact: false, breakLength: 3 }); + expect = [ + '\'12 45 78 01 34 \' +', + ' \'67 90 23 56 89 \' +', + ' \'1234567890123 0\'' + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect( + '12 45 78 01 34 67 90 23 56 89 12345678901234567 0', + { compact: false, breakLength: 3 }); + expect = [ + '\'12 45 78 01 34 \' +', + ' \'67 90 23 56 89 \' +', + ' \'12345678901234567 \' +', + ' \'0\'' + ].join('\n'); + assert.strictEqual(out, expect); + + o.a = () => {}; + o.b = new Number(3); + out = util.inspect(o, { compact: false, breakLength: 3 }); + expect = [ + '{', + ' a: [Function],', + ' b: [Number: 3]', + '}' + ].join('\n'); + assert.strictEqual(out, expect); + + out = util.inspect(o, { compact: false, breakLength: 3, showHidden: true }); + expect = [ + '{', + ' a: [Function] {', + ' [length]: 0,', + " [name]: ''", + ' },', + ' b: [Number: 3]', + '}' + ].join('\n'); + assert.strictEqual(out, expect); + + o[util.inspect.custom] = () => 42; + out = util.inspect(o, { compact: false, breakLength: 3 }); + expect = '42'; + assert.strictEqual(out, expect); + + o[util.inspect.custom] = () => '12 45 78 01 34 67 90 23'; + out = util.inspect(o, { compact: false, breakLength: 3 }); + expect = '12 45 78 01 34 67 90 23'; + assert.strictEqual(out, expect); + + o[util.inspect.custom] = () => ({ a: '12 45 78 01 34 67 90 23' }); + out = util.inspect(o, { compact: false, breakLength: 3 }); + expect = '{\n a: \'12 45 78 01 34 \' +\n \'67 90 23\'\n}'; + assert.strictEqual(out, expect); +} From 5aa3a2d172efb5cdca07ba6f0f2b8b054ced97ea Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 9 Dec 2017 19:38:20 -0200 Subject: [PATCH 014/134] assert: improve error messages From now on all error messages produced by `assert` in strict mode will produce a error diff. Backport-PR-URL: https://github.com/nodejs/node/pull/19230 PR-URL: https://github.com/nodejs/node/pull/17615 Reviewed-By: James M Snell Reviewed-By: Matteo Collina --- doc/api/assert.md | 33 ++++++++ lib/assert.js | 16 +++- lib/internal/errors.js | 150 ++++++++++++++++++++++++++++++++++- test/parallel/test-assert.js | 143 ++++++++++++++++++++++++++++++++- 4 files changed, 332 insertions(+), 10 deletions(-) diff --git a/doc/api/assert.md b/doc/api/assert.md index d53bccd21a998d..68b01350dfdee6 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -17,6 +17,9 @@ For more information about the used equality comparisons see + +* `env` {object} A object containing the environment variables to check. + Defaults to `process.env`. +* Returns: {number} + +Returns: +* 1 for 2, +* 4 for 16, +* 8 for 256, +* 24 for 16,777,216 +colors supported. + +Use this to determine what colors the terminal supports. Due to the nature of +colors in terminals it is possible to either have false positives or false +negatives. It depends on process information and the environment variables that +may lie about what terminal is used. +To enforce a specific behavior without relying on `process.env` it is possible +to pass in an object with different settings. + +Use the `NODE_DISABLE_COLORS` environment variable to enforce this function to +always return 1. + ## tty.isatty(fd) ## Exercise: Make a PR adding yourself to the README @@ -202,9 +213,11 @@ onboarding session. for 48/72 hours to land). * Be sure to add the `PR-URL: ` and appropriate `Reviewed-By:` metadata. - * [`core-validate-commit`][] automates the validation of commit messages. * [`node-core-utils`][] automates the generation of metadata and the landing process. See the documentation of [`git-node`][]. + * [`core-validate-commit`][] automates the validation of commit messages. + This will be run during `git node land --final` of the [`git-node`][] + command. ## Final notes @@ -227,9 +240,13 @@ onboarding session. [Code of Conduct]: https://github.com/nodejs/admin/blob/master/CODE_OF_CONDUCT.md [`core-validate-commit`]: https://github.com/evanlucas/core-validate-commit -[`git-node`]: https://github.com/nodejs/node-core-utils#git-node +[`git-node`]: https://github.com/nodejs/node-core-utils/blob/master/docs/git-node.md [`node-core-utils`]: https://github.com/nodejs/node-core-utils [Landing Pull Requests]: https://github.com/nodejs/node/blob/master/COLLABORATOR_GUIDE.md#landing-pull-requests [https://github.com/nodejs/node/commit/ce986de829457c39257cd205067602e765768fb0]: https://github.com/nodejs/node/commit/ce986de829457c39257cd205067602e765768fb0 [Publicizing or hiding organization membership]: https://help.github.com/articles/publicizing-or-hiding-organization-membership/ +[set up the credentials]: https://github.com/nodejs/node-core-utils#setting-up-credentials +[two-factor authentication]: https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/ [Updating Node.js from Upstream]: ./onboarding-extras.md#updating-nodejs-from-upstream +[using a TOTP mobile app]: https://help.github.com/articles/configuring-two-factor-authentication-via-a-totp-mobile-app/ +[who-to-cc]: ./onboarding-extras.md#who-to-cc-in-issues From 152c931f5397a435f5e0c0155743dac309fc9bbc Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Mon, 5 Mar 2018 11:12:08 +0100 Subject: [PATCH 028/134] stream: make Duplex inherits from DuplexBase Add ability to subclass `stream.Duplex` without inheriting the "no-half-open enforcer" regardless of the value of the `allowHalfOpen` option. PR-URL: https://github.com/nodejs/node/pull/18974 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Anna Henningsen Reviewed-By: Matteo Collina Reviewed-By: James M Snell Reviewed-By: Chen Gang Reviewed-By: Ruben Bridgewater --- lib/_stream_duplex.js | 26 ++++--------------------- lib/internal/streams/duplex_base.js | 30 +++++++++++++++++++++++++++++ node.gyp | 1 + 3 files changed, 35 insertions(+), 22 deletions(-) create mode 100644 lib/internal/streams/duplex_base.js diff --git a/lib/_stream_duplex.js b/lib/_stream_duplex.js index 59ce83292789b5..79ff582f459109 100644 --- a/lib/_stream_duplex.js +++ b/lib/_stream_duplex.js @@ -29,33 +29,15 @@ module.exports = Duplex; const util = require('util'); -const Readable = require('_stream_readable'); -const Writable = require('_stream_writable'); - -util.inherits(Duplex, Readable); - -{ - // avoid scope creep, the keys array can then be collected - const keys = Object.keys(Writable.prototype); - for (var v = 0; v < keys.length; v++) { - const method = keys[v]; - if (!Duplex.prototype[method]) - Duplex.prototype[method] = Writable.prototype[method]; - } -} +const DuplexBase = require('internal/streams/duplex_base'); + +util.inherits(Duplex, DuplexBase); function Duplex(options) { if (!(this instanceof Duplex)) return new Duplex(options); - Readable.call(this, options); - Writable.call(this, options); - - if (options && options.readable === false) - this.readable = false; - - if (options && options.writable === false) - this.writable = false; + DuplexBase.call(this, options); this.allowHalfOpen = true; if (options && options.allowHalfOpen === false) { diff --git a/lib/internal/streams/duplex_base.js b/lib/internal/streams/duplex_base.js new file mode 100644 index 00000000000000..df3c5c37a80ea7 --- /dev/null +++ b/lib/internal/streams/duplex_base.js @@ -0,0 +1,30 @@ +'use strict'; + +const util = require('util'); +const Readable = require('_stream_readable'); +const Writable = require('_stream_writable'); + +function DuplexBase(options) { + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) + this.readable = false; + + if (options && options.writable === false) + this.writable = false; +} + +util.inherits(DuplexBase, Readable); + +{ + // Avoid scope creep, the keys array can then be collected. + const keys = Object.keys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + const method = keys[v]; + if (!DuplexBase.prototype[method]) + DuplexBase.prototype[method] = Writable.prototype[method]; + } +} + +module.exports = DuplexBase; diff --git a/node.gyp b/node.gyp index d85f6a491a9eea..d2cc59f10706cc 100644 --- a/node.gyp +++ b/node.gyp @@ -142,6 +142,7 @@ 'lib/internal/vm/Module.js', 'lib/internal/streams/lazy_transform.js', 'lib/internal/streams/BufferList.js', + 'lib/internal/streams/duplex_base.js', 'lib/internal/streams/legacy.js', 'lib/internal/streams/destroy.js', 'lib/internal/wrap_js_stream.js', From 5b12d3a58ee8eef8ec0f6fc0e31ac1f412a86af5 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Sat, 24 Feb 2018 09:44:42 +0100 Subject: [PATCH 029/134] net: do not inherit the no-half-open enforcer `Socket.prototype.destroySoon()` is called as soon as `UV_EOF` is read if the `allowHalfOpen` option is disabled. This already works as a "no-half-open enforcer" so there is no need to inherit another from `stream.Duplex`. PR-URL: https://github.com/nodejs/node/pull/18974 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Anna Henningsen Reviewed-By: Matteo Collina Reviewed-By: James M Snell Reviewed-By: Chen Gang Reviewed-By: Ruben Bridgewater --- lib/net.js | 11 +++++++---- test/parallel/test-http-connect.js | 7 +------ test/parallel/test-net-socket-no-halfopen-enforcer.js | 11 +++++++++++ 3 files changed, 19 insertions(+), 10 deletions(-) create mode 100644 test/parallel/test-net-socket-no-halfopen-enforcer.js diff --git a/lib/net.js b/lib/net.js index 90e0db558e3a9b..17a128a4f0c8db 100644 --- a/lib/net.js +++ b/lib/net.js @@ -50,6 +50,7 @@ const { async_id_symbol } = process.binding('async_wrap'); const { newUid, defaultTriggerAsyncIdScope } = require('internal/async_hooks'); const { nextTick } = require('internal/process/next_tick'); const errors = require('internal/errors'); +const DuplexBase = require('internal/streams/duplex_base'); const dns = require('dns'); const kLastWriteQueueSize = Symbol('lastWriteQueueSize'); @@ -211,7 +212,11 @@ function Socket(options) { else if (options === undefined) options = {}; - stream.Duplex.call(this, options); + // `DuplexBase` is just a slimmed down constructor for `Duplex` which allow + // us to not inherit the "no-half-open enforcer" as there is already one in + // place. Instances of `Socket` are still instances of `Duplex`, that is, + // `socket instanceof Duplex === true`. + DuplexBase.call(this, options); if (options.handle) { this._handle = options.handle; // private @@ -236,8 +241,6 @@ function Socket(options) { this._writev = null; this._write = makeSyncWrite(fd); } - this.readable = options.readable !== false; - this.writable = options.writable !== false; } else { // these will be set once there is a connection this.readable = this.writable = false; @@ -256,7 +259,7 @@ function Socket(options) { this._writableState.decodeStrings = false; // default to *not* allowing half open sockets - this.allowHalfOpen = options && options.allowHalfOpen || false; + this.allowHalfOpen = options.allowHalfOpen || false; // if we have a handle, then start the flow of data into the // buffer. if not, then this will happen when we connect diff --git a/test/parallel/test-http-connect.js b/test/parallel/test-http-connect.js index 9b7432f03a7542..af0948dd067054 100644 --- a/test/parallel/test-http-connect.js +++ b/test/parallel/test-http-connect.js @@ -68,12 +68,7 @@ server.listen(0, common.mustCall(() => { assert.strictEqual(socket.listeners('connect').length, 0); assert.strictEqual(socket.listeners('data').length, 0); assert.strictEqual(socket.listeners('drain').length, 0); - - // the stream.Duplex onend listener - // allow 0 here, so that i can run the same test on streams1 impl - assert(socket.listenerCount('end') <= 2, - `Found ${socket.listenerCount('end')} end listeners`); - + assert.strictEqual(socket.listeners('end').length, 1); assert.strictEqual(socket.listeners('free').length, 0); assert.strictEqual(socket.listeners('close').length, 0); assert.strictEqual(socket.listeners('error').length, 0); diff --git a/test/parallel/test-net-socket-no-halfopen-enforcer.js b/test/parallel/test-net-socket-no-halfopen-enforcer.js new file mode 100644 index 00000000000000..3df5b6d7b9c8cb --- /dev/null +++ b/test/parallel/test-net-socket-no-halfopen-enforcer.js @@ -0,0 +1,11 @@ +'use strict'; +require('../common'); + +// This test ensures that `net.Socket` does not inherit the no-half-open +// enforcer from `stream.Duplex`. + +const { Socket } = require('net'); +const { strictEqual } = require('assert'); + +const socket = new Socket({ allowHalfOpen: false }); +strictEqual(socket.listenerCount('end'), 1); From 12f19a6b86e792a09042be52fa49c54ea5ebbc98 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Thu, 1 Mar 2018 17:44:51 -0500 Subject: [PATCH 030/134] n-api: update documentation Document which APIs work while an exception is pending. This is the list of all APIs which do not start with `NAPI_PREAMBLE(env)`. Fixes: https://github.com/nodejs/abi-stable-node/issues/257 PR-URL: https://github.com/nodejs/node/pull/19078 Reviewed-By: Michael Dawson --- doc/api/n-api.md | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/doc/api/n-api.md b/doc/api/n-api.md index 44a046f5650c4b..19208f5fefe3dd 100644 --- a/doc/api/n-api.md +++ b/doc/api/n-api.md @@ -279,6 +279,8 @@ valid up until an n-api function is called on the same `env`. information as it is not subject to SemVer and may change at any time. It is intended only for logging purposes. +This API can be called even if there is a pending JavaScript exception. + ### Exceptions Any N-API function call may result in a pending JavaScript exception. This is @@ -504,7 +506,6 @@ Returns `napi_ok` if the API succeeded. This API returns a JavaScript RangeError with the text provided. - #### napi_get_and_clear_last_exception + +* Returns: {Buffer|undefined} The latest `Finished` message that has been +sent to the socket as part of a SSL/TLS handshake, or `undefined` if +no `Finished` message has been sent yet. + +As the `Finished` messages are message digests of the complete handshake +(with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can +be used for external authentication procedures when the authentication +provided by SSL/TLS is not desired or is not enough. + +Corresponds to the `SSL_get_finished` routine in OpenSSL and may be used +to implement the `tls-unique` channel binding from [RFC 5929][]. + ### tlsSocket.getPeerCertificate([detailed]) + +* Returns: {Buffer|undefined} The latest `Finished` message that is expected +or has actually been received from the socket as part of a SSL/TLS handshake, +or `undefined` if there is no `Finished` message so far. + +As the `Finished` messages are message digests of the complete handshake +(with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can +be used for external authentication procedures when the authentication +provided by SSL/TLS is not desired or is not enough. + +Corresponds to the `SSL_get_peer_finished` routine in OpenSSL and may be used +to implement the `tls-unique` channel binding from [RFC 5929][]. + ### tlsSocket.getProtocol() - `algorithm` {string} - `key` {string | Buffer | TypedArray | DataView} @@ -1288,7 +1293,8 @@ available cipher algorithms. The `key` is the raw key used by the `algorithm` and `iv` is an [initialization vector][]. Both arguments must be `'utf8'` encoded strings, -[Buffers][`Buffer`], `TypedArray`, or `DataView`s. +[Buffers][`Buffer`], `TypedArray`, or `DataView`s. If the cipher does not need +an initialization vector, `iv` may be `null`. ### crypto.createCredentials(details) - `algorithm` {string} - `key` {string | Buffer | TypedArray | DataView} @@ -1350,7 +1361,8 @@ available cipher algorithms. The `key` is the raw key used by the `algorithm` and `iv` is an [initialization vector][]. Both arguments must be `'utf8'` encoded strings, -[Buffers][`Buffer`], `TypedArray`, or `DataView`s. +[Buffers][`Buffer`], `TypedArray`, or `DataView`s. If the cipher does not need +an initialization vector, `iv` may be `null`. ### crypto.createDiffieHellman(prime[, primeEncoding][, generator][, generatorEncoding]) ```js assert.doesNotThrow( () => { @@ -358,6 +359,7 @@ assert.doesNotThrow( However, the following will result in an `AssertionError` with the message 'Got unwanted exception (TypeError)..': + ```js assert.doesNotThrow( () => { @@ -371,6 +373,7 @@ If an `AssertionError` is thrown and a value is provided for the `message` parameter, the value of `message` will be appended to the `AssertionError` message: + ```js assert.doesNotThrow( () => { diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 5f863b7c297a66..6375311fa6e31c 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -120,7 +120,7 @@ assert.ifError(null); assert.ifError(); common.expectsError( - () => assert.doesNotThrow(() => thrower(Error), 'user message'), + () => a.doesNotThrow(() => thrower(Error), 'user message'), { type: a.AssertionError, code: 'ERR_ASSERTION', @@ -130,7 +130,7 @@ common.expectsError( ); common.expectsError( - () => assert.doesNotThrow(() => thrower(Error), 'user message'), + () => a.doesNotThrow(() => thrower(Error), 'user message'), { code: 'ERR_ASSERTION', message: /Got unwanted exception: user message\n\[object Object\]/ @@ -138,7 +138,7 @@ common.expectsError( ); common.expectsError( - () => assert.doesNotThrow(() => thrower(Error)), + () => a.doesNotThrow(() => thrower(Error)), { code: 'ERR_ASSERTION', message: /Got unwanted exception\.\n\[object Object\]/ @@ -307,7 +307,7 @@ try { // Verify AssertionError is the result from doesNotThrow with custom Error. try { - assert.doesNotThrow(() => { + a.doesNotThrow(() => { throw new TypeError('wrong type'); }, TypeError, rangeError); } catch (e) { @@ -645,7 +645,7 @@ common.expectsError( ); common.expectsError( - () => assert.doesNotThrow(() => { throw new Error(); }, { foo: 'bar' }), + () => a.doesNotThrow(() => { throw new Error(); }, { foo: 'bar' }), { type: TypeError, code: 'ERR_INVALID_ARG_TYPE', @@ -676,7 +676,7 @@ common.expectsError( assert.throws(() => { throw undefined; }, /undefined/); common.expectsError( // eslint-disable-next-line no-throw-literal - () => assert.doesNotThrow(() => { throw undefined; }), + () => a.doesNotThrow(() => { throw undefined; }), { type: assert.AssertionError, code: 'ERR_ASSERTION', From 9d1e409ee3080b9ec1b7ea05d96d4a0ca3c2698a Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 13 Feb 2018 03:01:46 +0100 Subject: [PATCH 121/134] tools: enable no-unsafe-finally This enables the `no-unsafe-finally` eslint rule to make sure we have a proper control flow in try / catch. Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/18745 Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: Luigi Pinca Reviewed-By: James M Snell --- .eslintrc.yaml | 1 + lib/timers.js | 32 ++++++++++++++++---------------- test/common/index.js | 14 +++----------- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 96436055ffcee5..99489d2e7d8589 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -157,6 +157,7 @@ rules: }] no-tabs: error no-trailing-spaces: error + no-unsafe-finally: error object-curly-spacing: [error, always] one-var-declaration-per-line: error operator-linebreak: [error, after] diff --git a/lib/timers.js b/lib/timers.js index 46cd770fc643bd..c82d6cfdbb11e9 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -314,24 +314,24 @@ function tryOnTimeout(timer, list) { } } - if (!threw) return; - - // Postpone all later list events to next tick. We need to do this - // so that the events are called in the order they were created. - const lists = list._unrefed === true ? unrefedLists : refedLists; - for (var key in lists) { - if (key > list.msecs) { - lists[key].nextTick = true; + if (threw) { + // Postpone all later list events to next tick. We need to do this + // so that the events are called in the order they were created. + const lists = list._unrefed === true ? unrefedLists : refedLists; + for (var key in lists) { + if (key > list.msecs) { + lists[key].nextTick = true; + } } + // We need to continue processing after domain error handling + // is complete, but not by using whatever domain was left over + // when the timeout threw its exception. + const domain = process.domain; + process.domain = null; + // If we threw, we need to process the rest of the list in nextTick. + process.nextTick(listOnTimeoutNT, list); + process.domain = domain; } - // We need to continue processing after domain error handling - // is complete, but not by using whatever domain was left over - // when the timeout threw its exception. - const domain = process.domain; - process.domain = null; - // If we threw, we need to process the rest of the list in nextTick. - process.nextTick(listOnTimeoutNT, list); - process.domain = domain; } } diff --git a/test/common/index.js b/test/common/index.js index eb4d5a5251cab8..165014e585c49f 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -514,21 +514,13 @@ exports.canCreateSymLink = function() { const whoamiPath = path.join(process.env.SystemRoot, 'System32', 'whoami.exe'); - let err = false; - let output = ''; - try { - output = execSync(`${whoamiPath} /priv`, { timout: 1000 }); + const output = execSync(`${whoamiPath} /priv`, { timout: 1000 }); + return output.includes('SeCreateSymbolicLinkPrivilege'); } catch (e) { - err = true; - } finally { - if (err || !output.includes('SeCreateSymbolicLinkPrivilege')) { - return false; - } + return false; } } - - return true; }; exports.getCallSite = function getCallSite(top) { From ff82acb95ab85c2e9dccc720481826c5ad3ac494 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 12 Feb 2018 23:24:54 +0100 Subject: [PATCH 122/134] doc: update buffer examples Move the print statements below a console.log call. Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/18758 Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell Reviewed-By: Vse Mozhet Byt --- doc/api/buffer.md | 391 +++++++++++++++++++--------------------------- 1 file changed, 161 insertions(+), 230 deletions(-) diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 8925f6d895572e..da46fa7c2e4341 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -161,11 +161,10 @@ Example: ```js const buf = Buffer.from('hello world', 'ascii'); -// Prints: 68656c6c6f20776f726c64 console.log(buf.toString('hex')); - -// Prints: aGVsbG8gd29ybGQ= +// Prints: 68656c6c6f20776f726c64 console.log(buf.toString('base64')); +// Prints: aGVsbG8gd29ybGQ= ``` The character encodings currently supported by Node.js include: @@ -239,23 +238,20 @@ arr[1] = 4000; // Copies the contents of `arr` const buf1 = Buffer.from(arr); - // Shares memory with `arr` const buf2 = Buffer.from(arr.buffer); -// Prints: console.log(buf1); - -// Prints: +// Prints: console.log(buf2); +// Prints: arr[1] = 6000; -// Prints: console.log(buf1); - -// Prints: +// Prints: console.log(buf2); +// Prints: ``` Note that when creating a `Buffer` using a [`TypedArray`]'s `.buffer`, it is @@ -268,8 +264,8 @@ Example: const arr = new Uint16Array(20); const buf = Buffer.from(arr.buffer, 0, 16); -// Prints: 16 console.log(buf.length); +// Prints: 16 ``` The `Buffer.from()` and [`TypedArray.from()`] have different signatures and @@ -384,14 +380,14 @@ arr[1] = 4000; // Shares memory with `arr` const buf = new Buffer(arr.buffer); -// Prints: console.log(buf); +// Prints: // Changing the original Uint16Array changes the Buffer also arr[1] = 6000; -// Prints: console.log(buf); +// Prints: ``` ### new Buffer(buffer) @@ -420,11 +416,10 @@ const buf2 = new Buffer(buf1); buf1[0] = 0x61; -// Prints: auffer console.log(buf1.toString()); - -// Prints: buffer +// Prints: auffer console.log(buf2.toString()); +// Prints: buffer ``` ### new Buffer(size) @@ -462,8 +457,8 @@ Example: ```js const buf = new Buffer(10); -// Prints: console.log(buf); +// Prints: ``` ### new Buffer(string[, encoding]) @@ -489,17 +484,14 @@ provided, the `encoding` parameter identifies the character encoding of `string` ```js const buf1 = new Buffer('this is a tést'); - -// Prints: this is a tést -console.log(buf1.toString()); - -// Prints: this is a tC)st -console.log(buf1.toString('ascii')); - const buf2 = new Buffer('7468697320697320612074c3a97374', 'hex'); +console.log(buf1.toString()); // Prints: this is a tést console.log(buf2.toString()); +// Prints: this is a tést +console.log(buf1.toString('ascii')); +// Prints: this is a tC)st ``` ### Class Method: Buffer.alloc(size[, fill[, encoding]]) @@ -526,8 +518,8 @@ Example: ```js const buf = Buffer.alloc(5); -// Prints: console.log(buf); +// Prints: ``` Allocates a new `Buffer` of `size` bytes. If the `size` is larger than @@ -542,8 +534,8 @@ Example: ```js const buf = Buffer.alloc(5, 'a'); -// Prints: console.log(buf); +// Prints: ``` If both `fill` and `encoding` are specified, the allocated `Buffer` will be @@ -554,8 +546,8 @@ Example: ```js const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64'); -// Prints: console.log(buf); +// Prints: ``` Calling [`Buffer.alloc()`] can be significantly slower than the alternative @@ -589,13 +581,13 @@ Example: ```js const buf = Buffer.allocUnsafe(10); -// Prints: (contents may vary): console.log(buf); +// Prints: (contents may vary): buf.fill(0); -// Prints: console.log(buf); +// Prints: ``` A `TypeError` will be thrown if `size` is not a number. @@ -698,9 +690,9 @@ Example: ```js const str = '\u00bd + \u00bc = \u00be'; -// Prints: ½ + ¼ = ¾: 9 characters, 12 bytes console.log(`${str}: ${str.length} characters, ` + `${Buffer.byteLength(str, 'utf8')} bytes`); +// Prints: ½ + ¼ = ¾: 9 characters, 12 bytes ``` When `string` is a `Buffer`/[`DataView`]/[`TypedArray`]/[`ArrayBuffer`]/ @@ -730,9 +722,9 @@ const buf1 = Buffer.from('1234'); const buf2 = Buffer.from('0123'); const arr = [buf1, buf2]; +console.log(arr.sort(Buffer.compare)); // Prints: [ , ] // (This result is equal to: [buf2, buf1]) -console.log(arr.sort(Buffer.compare)); ``` ### Class Method: Buffer.concat(list[, totalLength]) @@ -772,16 +764,15 @@ const buf2 = Buffer.alloc(14); const buf3 = Buffer.alloc(18); const totalLength = buf1.length + buf2.length + buf3.length; -// Prints: 42 console.log(totalLength); +// Prints: 42 const bufA = Buffer.concat([buf1, buf2, buf3], totalLength); -// Prints: console.log(bufA); - -// Prints: 42 +// Prints: console.log(bufA.length); +// Prints: 42 ``` ### Class Method: Buffer.from(array) @@ -829,14 +820,14 @@ arr[1] = 4000; // Shares memory with `arr` const buf = Buffer.from(arr.buffer); -// Prints: console.log(buf); +// Prints: // Changing the original Uint16Array changes the Buffer also arr[1] = 6000; -// Prints: console.log(buf); +// Prints: ``` The optional `byteOffset` and `length` arguments specify a memory range within @@ -848,8 +839,8 @@ Example: const ab = new ArrayBuffer(10); const buf = Buffer.from(ab, 0, 2); -// Prints: 2 console.log(buf.length); +// Prints: 2 ``` A `TypeError` will be thrown if `arrayBuffer` is not an [`ArrayBuffer`] or a @@ -872,11 +863,10 @@ const buf2 = Buffer.from(buf1); buf1[0] = 0x61; -// Prints: auffer console.log(buf1.toString()); - -// Prints: buffer +// Prints: auffer console.log(buf2.toString()); +// Prints: buffer ``` A `TypeError` will be thrown if `buffer` is not a `Buffer`. @@ -894,17 +884,14 @@ provided, the `encoding` parameter identifies the character encoding of `string` ```js const buf1 = Buffer.from('this is a tést'); - -// Prints: this is a tést -console.log(buf1.toString()); - -// Prints: this is a tC)st -console.log(buf1.toString('ascii')); - const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex'); +console.log(buf1.toString()); // Prints: this is a tést console.log(buf2.toString()); +// Prints: this is a tést +console.log(buf1.toString('ascii')); +// Prints: this is a tC)st ``` A `TypeError` will be thrown if `string` is not a string. @@ -926,7 +913,7 @@ For objects whose `valueOf()` function returns a value not strictly equal to ```js const buf = Buffer.from(new String('this is a test')); -// +// Prints: ``` For objects that support `Symbol.toPrimitive`, returns @@ -940,7 +927,7 @@ class Foo { } const buf = Buffer.from(new Foo(), 'utf8'); -// +// Prints: ``` ### Class Method: Buffer.isBuffer(obj) @@ -998,8 +985,8 @@ for (let i = 0; i < str.length; i++) { buf[i] = str.charCodeAt(i); } -// Prints: Node.js console.log(buf.toString('ascii')); +// Prints: Node.js ``` ### buf.buffer @@ -1051,24 +1038,19 @@ const buf1 = Buffer.from('ABC'); const buf2 = Buffer.from('BCD'); const buf3 = Buffer.from('ABCD'); -// Prints: 0 console.log(buf1.compare(buf1)); - -// Prints: -1 +// Prints: 0 console.log(buf1.compare(buf2)); - // Prints: -1 console.log(buf1.compare(buf3)); - -// Prints: 1 +// Prints: -1 console.log(buf2.compare(buf1)); - // Prints: 1 console.log(buf2.compare(buf3)); - +// Prints: 1 +console.log([buf1, buf2, buf3].sort(Buffer.compare)); // Prints: [ , , ] // (This result is equal to: [buf1, buf3, buf2]) -console.log([buf1, buf2, buf3].sort(Buffer.compare)); ``` The optional `targetStart`, `targetEnd`, `sourceStart`, and `sourceEnd` @@ -1079,14 +1061,12 @@ and `buf` respectively. const buf1 = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9]); const buf2 = Buffer.from([5, 6, 7, 8, 9, 1, 2, 3, 4]); -// Prints: 0 console.log(buf1.compare(buf2, 5, 9, 0, 4)); - -// Prints: -1 +// Prints: 0 console.log(buf1.compare(buf2, 0, 6, 4)); - -// Prints: 1 +// Prints: -1 console.log(buf1.compare(buf2, 5, 6, 5)); +// Prints: 1 ``` A `RangeError` will be thrown if: `targetStart < 0`, `sourceStart < 0`, @@ -1123,8 +1103,8 @@ for (let i = 0; i < 26; i++) { buf1.copy(buf2, 8, 16, 20); -// Prints: !!!!!!!!qrst!!!!!!!!!!!!! console.log(buf2.toString('ascii', 0, 25)); +// Prints: !!!!!!!!qrst!!!!!!!!!!!!! ``` Example: Create a single `Buffer` and copy data from one region to an @@ -1140,8 +1120,8 @@ for (let i = 0; i < 26; i++) { buf.copy(buf, 0, 4, 10); -// Prints: efghijghijklmnopqrstuvwxyz console.log(buf.toString()); +// Prints: efghijghijklmnopqrstuvwxyz ``` ### buf.entries() @@ -1159,6 +1139,9 @@ Example: Log the entire contents of a `Buffer` ```js const buf = Buffer.from('buffer'); +for (const pair of buf.entries()) { + console.log(pair); +} // Prints: // [0, 98] // [1, 117] @@ -1166,9 +1149,6 @@ const buf = Buffer.from('buffer'); // [3, 102] // [4, 101] // [5, 114] -for (const pair of buf.entries()) { - console.log(pair); -} ``` ### buf.equals(otherBuffer) @@ -1191,11 +1171,10 @@ const buf1 = Buffer.from('ABC'); const buf2 = Buffer.from('414243', 'hex'); const buf3 = Buffer.from('ABCD'); -// Prints: true console.log(buf1.equals(buf2)); - -// Prints: false +// Prints: true console.log(buf1.equals(buf3)); +// Prints: false ``` ### buf.fill(value[, offset[, end]][, encoding]) @@ -1223,8 +1202,8 @@ Example: Fill a `Buffer` with the ASCII character `'h'` ```js const b = Buffer.allocUnsafe(50).fill('h'); -// Prints: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh console.log(b.toString()); +// Prints: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh ``` `value` is coerced to a `uint32` value if it is not a String or Integer. @@ -1235,8 +1214,8 @@ then only the first bytes of that character that fit into `buf` are written. Example: Fill a `Buffer` with a two-byte character ```js -// Prints: console.log(Buffer.allocUnsafe(3).fill('\u0222')); +// Prints: ``` If `value` contains invalid characters, it is truncated; if no valid @@ -1244,12 +1223,13 @@ fill data remains, no filling is performed: ```js const buf = Buffer.allocUnsafe(5); -// Prints: + console.log(buf.fill('a')); -// Prints: +// Prints: console.log(buf.fill('aazz', 'hex')); // Prints: console.log(buf.fill('zz', 'hex')); +// Throws an exception. ``` ### buf.includes(value[, byteOffset][, encoding]) @@ -1268,27 +1248,20 @@ Equivalent to [`buf.indexOf() !== -1`][`buf.indexOf()`]. ```js const buf = Buffer.from('this is a buffer'); -// Prints: true console.log(buf.includes('this')); - // Prints: true console.log(buf.includes('is')); - // Prints: true console.log(buf.includes(Buffer.from('a buffer'))); - // Prints: true -// (97 is the decimal ASCII value for 'a') console.log(buf.includes(97)); - -// Prints: false +// Prints: true (97 is the decimal ASCII value for 'a') console.log(buf.includes(Buffer.from('a buffer example'))); - -// Prints: true -console.log(buf.includes(Buffer.from('a buffer example').slice(0, 8))); - // Prints: false +console.log(buf.includes(Buffer.from('a buffer example').slice(0, 8))); +// Prints: true console.log(buf.includes('this', 4)); +// Prints: false ``` ### buf.indexOf(value[, byteOffset][, encoding]) @@ -1323,32 +1296,25 @@ If `value` is: ```js const buf = Buffer.from('this is a buffer'); -// Prints: 0 console.log(buf.indexOf('this')); - -// Prints: 2 +// Prints: 0 console.log(buf.indexOf('is')); - -// Prints: 8 +// Prints: 2 console.log(buf.indexOf(Buffer.from('a buffer'))); - // Prints: 8 -// (97 is the decimal ASCII value for 'a') console.log(buf.indexOf(97)); - -// Prints: -1 +// Prints: 8 (97 is the decimal ASCII value for 'a') console.log(buf.indexOf(Buffer.from('a buffer example'))); - -// Prints: 8 +// Prints: -1 console.log(buf.indexOf(Buffer.from('a buffer example').slice(0, 8))); +// Prints: 8 const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2'); -// Prints: 4 console.log(utf16Buffer.indexOf('\u03a3', 0, 'ucs2')); - -// Prints: 6 +// Prints: 4 console.log(utf16Buffer.indexOf('\u03a3', -4, 'ucs2')); +// Prints: 6 ``` If `value` is not a string, number, or `Buffer`, this method will throw a @@ -1393,6 +1359,9 @@ Example: ```js const buf = Buffer.from('buffer'); +for (const key of buf.keys()) { + console.log(key); +} // Prints: // 0 // 1 @@ -1400,9 +1369,6 @@ const buf = Buffer.from('buffer'); // 3 // 4 // 5 -for (const key of buf.keys()) { - console.log(key); -} ``` ### buf.lastIndexOf(value[, byteOffset][, encoding]) @@ -1428,35 +1394,27 @@ instead of front to back. ```js const buf = Buffer.from('this buffer is a buffer'); -// Prints: 0 console.log(buf.lastIndexOf('this')); - -// Prints: 17 +// Prints: 0 console.log(buf.lastIndexOf('buffer')); - // Prints: 17 console.log(buf.lastIndexOf(Buffer.from('buffer'))); - -// Prints: 15 -// (97 is the decimal ASCII value for 'a') +// Prints: 17 console.log(buf.lastIndexOf(97)); - -// Prints: -1 +// Prints: 15 (97 is the decimal ASCII value for 'a') console.log(buf.lastIndexOf(Buffer.from('yolo'))); - -// Prints: 5 -console.log(buf.lastIndexOf('buffer', 5)); - // Prints: -1 +console.log(buf.lastIndexOf('buffer', 5)); +// Prints: 5 console.log(buf.lastIndexOf('buffer', 4)); +// Prints: -1 const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'ucs2'); -// Prints: 6 console.log(utf16Buffer.lastIndexOf('\u03a3', undefined, 'ucs2')); - -// Prints: 4 +// Prints: 6 console.log(utf16Buffer.lastIndexOf('\u03a3', -5, 'ucs2')); +// Prints: 4 ``` If `value` is not a string, number, or `Buffer`, this method will throw a @@ -1503,13 +1461,13 @@ Example: Create a `Buffer` and write a shorter ASCII string to it ```js const buf = Buffer.alloc(1234); -// Prints: 1234 console.log(buf.length); +// Prints: 1234 buf.write('some string', 0, 'ascii'); -// Prints: 1234 console.log(buf.length); +// Prints: 1234 ``` While the `length` property is not immutable, changing the value of `length` @@ -1522,13 +1480,13 @@ let buf = Buffer.allocUnsafe(10); buf.write('abcdefghj', 0, 'ascii'); -// Prints: 10 console.log(buf.length); +// Prints: 10 buf = buf.slice(0, 5); -// Prints: 5 console.log(buf.length); +// Prints: 5 ``` ### buf.parent @@ -1560,18 +1518,15 @@ the resulting behavior is undefined. ```js const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]); -// Prints: 8.20788039913184e-304 console.log(buf.readDoubleBE()); - -// Prints: 5.447603722011605e-270 +// Prints: 8.20788039913184e-304 console.log(buf.readDoubleLE()); - -// Throws an exception: RangeError: Index out of range +// Prints: 5.447603722011605e-270 console.log(buf.readDoubleLE(1)); - +// Throws an exception: RangeError: Index out of range +console.log(buf.readDoubleLE(1, true)); // Warning: reads passed end of buffer! // This will result in a segmentation fault! Don't do this! -console.log(buf.readDoubleLE(1, true)); ``` ### buf.readFloatBE(offset[, noAssert]) @@ -1594,18 +1549,15 @@ the resulting behavior is undefined. ```js const buf = Buffer.from([1, 2, 3, 4]); -// Prints: 2.387939260590663e-38 console.log(buf.readFloatBE()); - -// Prints: 1.539989614439558e-36 +// Prints: 2.387939260590663e-38 console.log(buf.readFloatLE()); - -// Throws an exception: RangeError: Index out of range +// Prints: 1.539989614439558e-36 console.log(buf.readFloatLE(1)); - +// Throws an exception: RangeError: Index out of range +console.log(buf.readFloatLE(1, true)); // Warning: reads passed end of buffer! // This will result in a segmentation fault! Don't do this! -console.log(buf.readFloatLE(1, true)); ``` ### buf.readInt8(offset[, noAssert]) @@ -1627,14 +1579,12 @@ Integers read from a `Buffer` are interpreted as two's complement signed values. ```js const buf = Buffer.from([-1, 5]); -// Prints: -1 console.log(buf.readInt8(0)); - -// Prints: 5 +// Prints: -1 console.log(buf.readInt8(1)); - -// Throws an exception: RangeError: Index out of range +// Prints: 5 console.log(buf.readInt8(2)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readInt16BE(offset[, noAssert]) @@ -1659,14 +1609,12 @@ Integers read from a `Buffer` are interpreted as two's complement signed values. ```js const buf = Buffer.from([0, 5]); -// Prints: 5 console.log(buf.readInt16BE()); - -// Prints: 1280 +// Prints: 5 console.log(buf.readInt16LE()); - -// Throws an exception: RangeError: Index out of range +// Prints: 1280 console.log(buf.readInt16LE(1)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readInt32BE(offset[, noAssert]) @@ -1691,14 +1639,12 @@ Integers read from a `Buffer` are interpreted as two's complement signed values. ```js const buf = Buffer.from([0, 0, 0, 5]); -// Prints: 5 console.log(buf.readInt32BE()); - -// Prints: 83886080 +// Prints: 5 console.log(buf.readInt32LE()); - -// Throws an exception: RangeError: Index out of range +// Prints: 83886080 console.log(buf.readInt32LE(1)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readIntBE(offset, byteLength[, noAssert]) @@ -1722,14 +1668,12 @@ the resulting behavior is undefined. ```js const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); -// Prints: -546f87a9cbee console.log(buf.readIntLE(0, 6).toString(16)); - -// Prints: 1234567890ab +// Prints: -546f87a9cbee console.log(buf.readIntBE(0, 6).toString(16)); - -// Throws an exception: RangeError: Index out of range +// Prints: 1234567890ab console.log(buf.readIntBE(1, 6).toString(16)); +// Throws: RangeError [ERR_INDEX_OUT_OF_RANGE]: Index out of range ``` ### buf.readUInt8(offset[, noAssert]) @@ -1749,14 +1693,12 @@ the resulting behavior is undefined. ```js const buf = Buffer.from([1, -2]); -// Prints: 1 console.log(buf.readUInt8(0)); - -// Prints: 254 +// Prints: 1 console.log(buf.readUInt8(1)); - -// Throws an exception: RangeError: Index out of range +// Prints: 254 console.log(buf.readUInt8(2)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readUInt16BE(offset[, noAssert]) @@ -1779,20 +1721,16 @@ the resulting behavior is undefined. ```js const buf = Buffer.from([0x12, 0x34, 0x56]); -// Prints: 1234 console.log(buf.readUInt16BE(0).toString(16)); - -// Prints: 3412 +// Prints: 1234 console.log(buf.readUInt16LE(0).toString(16)); - -// Prints: 3456 +// Prints: 3412 console.log(buf.readUInt16BE(1).toString(16)); - -// Prints: 5634 +// Prints: 3456 console.log(buf.readUInt16LE(1).toString(16)); - -// Throws an exception: RangeError: Index out of range +// Prints: 5634 console.log(buf.readUInt16LE(2).toString(16)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readUInt32BE(offset[, noAssert]) @@ -1815,14 +1753,12 @@ the resulting behavior is undefined. ```js const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]); -// Prints: 12345678 console.log(buf.readUInt32BE(0).toString(16)); - -// Prints: 78563412 +// Prints: 12345678 console.log(buf.readUInt32LE(0).toString(16)); - -// Throws an exception: RangeError: Index out of range +// Prints: 78563412 console.log(buf.readUInt32LE(1).toString(16)); +// Throws an exception: RangeError: Index out of range ``` ### buf.readUIntBE(offset, byteLength[, noAssert]) @@ -1846,14 +1782,12 @@ the resulting behavior is undefined. ```js const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]); -// Prints: 1234567890ab console.log(buf.readUIntBE(0, 6).toString(16)); - -// Prints: ab9078563412 +// Prints: 1234567890ab console.log(buf.readUIntLE(0, 6).toString(16)); - -// Throws an exception: RangeError: Index out of range +// Prints: ab9078563412 console.log(buf.readUIntBE(1, 6).toString(16)); +// Throws an exception: RangeError: Index out of range ``` ### buf.slice([start[, end]]) @@ -1897,13 +1831,13 @@ for (let i = 0; i < 26; i++) { const buf2 = buf1.slice(0, 3); -// Prints: abc console.log(buf2.toString('ascii', 0, buf2.length)); +// Prints: abc buf1[0] = 33; -// Prints: !bc console.log(buf2.toString('ascii', 0, buf2.length)); +// Prints: !bc ``` Specifying negative indexes causes the slice to be generated relative to the @@ -1912,17 +1846,17 @@ end of `buf` rather than the beginning. ```js const buf = Buffer.from('buffer'); +console.log(buf.slice(-6, -1).toString()); // Prints: buffe // (Equivalent to buf.slice(0, 5)) -console.log(buf.slice(-6, -1).toString()); +console.log(buf.slice(-6, -2).toString()); // Prints: buff // (Equivalent to buf.slice(0, 4)) -console.log(buf.slice(-6, -2).toString()); +console.log(buf.slice(-5, -2).toString()); // Prints: uff // (Equivalent to buf.slice(1, 4)) -console.log(buf.slice(-5, -2).toString()); ``` ### buf.swap16() @@ -1938,18 +1872,18 @@ Interprets `buf` as an array of unsigned 16-bit integers and swaps the byte-orde ```js const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); -// Prints: console.log(buf1); +// Prints: buf1.swap16(); -// Prints: console.log(buf1); +// Prints: const buf2 = Buffer.from([0x1, 0x2, 0x3]); -// Throws an exception: RangeError: Buffer size must be a multiple of 16-bits buf2.swap16(); +// Throws an exception: RangeError: Buffer size must be a multiple of 16-bits ``` ### buf.swap32() @@ -1965,18 +1899,18 @@ Interprets `buf` as an array of unsigned 32-bit integers and swaps the byte-orde ```js const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); -// Prints: console.log(buf1); +// Prints: buf1.swap32(); -// Prints: console.log(buf1); +// Prints: const buf2 = Buffer.from([0x1, 0x2, 0x3]); -// Throws an exception: RangeError: Buffer size must be a multiple of 32-bits buf2.swap32(); +// Throws an exception: RangeError: Buffer size must be a multiple of 32-bits ``` ### buf.swap64() @@ -1992,18 +1926,18 @@ Throws a `RangeError` if [`buf.length`] is not a multiple of 8. ```js const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]); -// Prints: console.log(buf1); +// Prints: buf1.swap64(); -// Prints: console.log(buf1); +// Prints: const buf2 = Buffer.from([0x1, 0x2, 0x3]); -// Throws an exception: RangeError: Buffer size must be a multiple of 64-bits buf2.swap64(); +// Throws an exception: RangeError: Buffer size must be a multiple of 64-bits ``` Note that JavaScript cannot encode 64-bit integers. This method is intended @@ -2025,8 +1959,8 @@ Example: const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); const json = JSON.stringify(buf); -// Prints: {"type":"Buffer","data":[1,2,3,4,5]} console.log(json); +// Prints: {"type":"Buffer","data":[1,2,3,4,5]} const copy = JSON.parse(json, (key, value) => { return value && value.type === 'Buffer' ? @@ -2034,8 +1968,8 @@ const copy = JSON.parse(json, (key, value) => { value; }); -// Prints: console.log(copy); +// Prints: ``` ### buf.toString([encoding[, start[, end]]]) @@ -2063,22 +1997,19 @@ for (let i = 0; i < 26; i++) { buf1[i] = i + 97; } -// Prints: abcdefghijklmnopqrstuvwxyz console.log(buf1.toString('ascii')); - -// Prints: abcde +// Prints: abcdefghijklmnopqrstuvwxyz console.log(buf1.toString('ascii', 0, 5)); +// Prints: abcde const buf2 = Buffer.from('tést'); -// Prints: 74c3a97374 console.log(buf2.toString('hex')); - -// Prints: té +// Prints: 74c3a97374 console.log(buf2.toString('utf8', 0, 3)); - // Prints: té console.log(buf2.toString(undefined, 0, 3)); +// Prints: té ``` ### buf.values() @@ -2094,6 +2025,9 @@ called automatically when a `Buffer` is used in a `for..of` statement. ```js const buf = Buffer.from('buffer'); +for (const value of buf.values()) { + console.log(value); +} // Prints: // 98 // 117 @@ -2101,10 +2035,10 @@ const buf = Buffer.from('buffer'); // 102 // 101 // 114 -for (const value of buf.values()) { + +for (const value of buf) { console.log(value); } - // Prints: // 98 // 117 @@ -2112,9 +2046,6 @@ for (const value of buf.values()) { // 102 // 101 // 114 -for (const value of buf) { - console.log(value); -} ``` ### buf.write(string[, offset[, length]][, encoding]) @@ -2140,8 +2071,8 @@ const buf = Buffer.allocUnsafe(256); const len = buf.write('\u00bd + \u00bc = \u00be', 0); -// Prints: 12 bytes: ½ + ¼ = ¾ console.log(`${len} bytes: ${buf.toString('utf8', 0, len)}`); +// Prints: 12 bytes: ½ + ¼ = ¾ ``` ### buf.writeDoubleBE(value, offset[, noAssert]) @@ -2168,13 +2099,13 @@ const buf = Buffer.allocUnsafe(8); buf.writeDoubleBE(0xdeadbeefcafebabe, 0); -// Prints: console.log(buf); +// Prints: buf.writeDoubleLE(0xdeadbeefcafebabe, 0); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeFloatBE(value, offset[, noAssert]) @@ -2201,13 +2132,13 @@ const buf = Buffer.allocUnsafe(4); buf.writeFloatBE(0xcafebabe, 0); -// Prints: console.log(buf); +// Prints: buf.writeFloatLE(0xcafebabe, 0); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeInt8(value, offset[, noAssert]) @@ -2235,8 +2166,8 @@ const buf = Buffer.allocUnsafe(2); buf.writeInt8(2, 0); buf.writeInt8(-2, 1); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeInt16BE(value, offset[, noAssert]) @@ -2266,8 +2197,8 @@ const buf = Buffer.allocUnsafe(4); buf.writeInt16BE(0x0102, 0); buf.writeInt16LE(0x0304, 2); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeInt32BE(value, offset[, noAssert]) @@ -2297,8 +2228,8 @@ const buf = Buffer.allocUnsafe(8); buf.writeInt32BE(0x01020304, 0); buf.writeInt32LE(0x05060708, 4); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeIntBE(value, offset, byteLength[, noAssert]) @@ -2326,13 +2257,13 @@ const buf = Buffer.allocUnsafe(6); buf.writeIntBE(0x1234567890ab, 0, 6); -// Prints: console.log(buf); +// Prints: buf.writeIntLE(0x1234567890ab, 0, 6); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeUInt8(value, offset[, noAssert]) @@ -2360,8 +2291,8 @@ buf.writeUInt8(0x4, 1); buf.writeUInt8(0x23, 2); buf.writeUInt8(0x42, 3); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeUInt16BE(value, offset[, noAssert]) @@ -2389,14 +2320,14 @@ const buf = Buffer.allocUnsafe(4); buf.writeUInt16BE(0xdead, 0); buf.writeUInt16BE(0xbeef, 2); -// Prints: console.log(buf); +// Prints: buf.writeUInt16LE(0xdead, 0); buf.writeUInt16LE(0xbeef, 2); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeUInt32BE(value, offset[, noAssert]) @@ -2423,13 +2354,13 @@ const buf = Buffer.allocUnsafe(4); buf.writeUInt32BE(0xfeedface, 0); -// Prints: console.log(buf); +// Prints: buf.writeUInt32LE(0xfeedface, 0); -// Prints: console.log(buf); +// Prints: ``` ### buf.writeUIntBE(value, offset, byteLength[, noAssert]) @@ -2457,13 +2388,13 @@ const buf = Buffer.allocUnsafe(6); buf.writeUIntBE(0x1234567890ab, 0, 6); -// Prints: console.log(buf); +// Prints: buf.writeUIntLE(0x1234567890ab, 0, 6); -// Prints: console.log(buf); +// Prints: ``` ## buffer.INSPECT_MAX_BYTES @@ -2591,13 +2522,13 @@ const { SlowBuffer } = require('buffer'); const buf = new SlowBuffer(5); -// Prints: (contents may vary): console.log(buf); +// Prints: (contents may vary): buf.fill(0); -// Prints: console.log(buf); +// Prints: ``` ## Buffer Constants From 9e10ddc21596c5b5b86319bbbe2ea4c758ee0b23 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 17 Feb 2018 03:45:07 +0100 Subject: [PATCH 123/134] tools: enable eslint no-undef-init rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also fixes the three entries that did not pass. Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/18831 Reviewed-By: Luigi Pinca Reviewed-By: Matheus Marchini Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso Reviewed-By: Anatoli Papirovski Reviewed-By: Colin Ihrig --- test/parallel/test-fs-utimes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/parallel/test-fs-utimes.js b/test/parallel/test-fs-utimes.js index 3dc0bb59def6a2..738fc7576a8b5e 100644 --- a/test/parallel/test-fs-utimes.js +++ b/test/parallel/test-fs-utimes.js @@ -88,7 +88,7 @@ function testIt(atime, mtime, callback) { expect_errno('futimesSync', fd, ex, 'ENOSYS'); } - let err = undefined; + let err; try { fs.utimesSync('foobarbaz', atime, mtime); } catch (ex) { From d4d7df83716b18c4d6791783ce566ce029d334a5 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 17 Feb 2018 03:46:15 +0100 Subject: [PATCH 124/134] tools: enable eslint strict key-spacing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/18831 Reviewed-By: Luigi Pinca Reviewed-By: Matheus Marchini Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso Reviewed-By: Anatoli Papirovski Reviewed-By: Colin Ihrig --- benchmark/http/_chunky_http_client.js | 4 ++-- test/parallel/test-eslint-require-buffer.js | 8 ++++---- test/parallel/test-https-agent-servername.js | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/benchmark/http/_chunky_http_client.js b/benchmark/http/_chunky_http_client.js index a90535e489f4c9..7728a5d06c60aa 100644 --- a/benchmark/http/_chunky_http_client.js +++ b/benchmark/http/_chunky_http_client.js @@ -5,8 +5,8 @@ const common = require('../common.js'); const net = require('net'); const bench = common.createBenchmark(main, { - len: [1, 4, 8, 16, 32, 64, 128], - n: [5, 50, 500, 2000], + len: [1, 4, 8, 16, 32, 64, 128], + n: [5, 50, 500, 2000], type: ['send'], }); diff --git a/test/parallel/test-eslint-require-buffer.js b/test/parallel/test-eslint-require-buffer.js index ca2c44cb322515..bdc794dd594240 100644 --- a/test/parallel/test-eslint-require-buffer.js +++ b/test/parallel/test-eslint-require-buffer.js @@ -36,14 +36,14 @@ ruleTester.run('require-buffer', rule, { output: useStrict + bufferModule + useBuffer, }, { - code: mockComment + useBuffer, + code: mockComment + useBuffer, errors: [{ message }], - output: mockComment + bufferModule + useBuffer, + output: mockComment + bufferModule + useBuffer, }, { - code: mockComment + useStrict + useBuffer, + code: mockComment + useStrict + useBuffer, errors: [{ message }], - output: mockComment + useStrict + bufferModule + useBuffer, + output: mockComment + useStrict + bufferModule + useBuffer, }, ] }); diff --git a/test/parallel/test-https-agent-servername.js b/test/parallel/test-https-agent-servername.js index 985fbb3ce3f76e..df14d113994f89 100644 --- a/test/parallel/test-https-agent-servername.js +++ b/test/parallel/test-https-agent-servername.js @@ -10,7 +10,7 @@ const fixtures = require('../common/fixtures'); const options = { key: fixtures.readKey('agent1-key.pem'), cert: fixtures.readKey('agent1-cert.pem'), - ca: fixtures.readKey('ca1-cert.pem') + ca: fixtures.readKey('ca1-cert.pem') }; From b04dd7b35102b35951442907abf8e069da46473b Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 17 Feb 2018 03:51:11 +0100 Subject: [PATCH 125/134] tools: enable eslint one-var rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/18831 Reviewed-By: Luigi Pinca Reviewed-By: Matheus Marchini Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso Reviewed-By: Anatoli Papirovski Reviewed-By: Colin Ihrig --- benchmark/tls/tls-connect.js | 6 +-- test/parallel/test-cluster-worker-kill.js | 45 +++++++++++------------ 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/benchmark/tls/tls-connect.js b/benchmark/tls/tls-connect.js index da0f5e08d5e6db..524d7468d000a1 100644 --- a/benchmark/tls/tls-connect.js +++ b/benchmark/tls/tls-connect.js @@ -1,7 +1,7 @@ 'use strict'; -var fs = require('fs'), - path = require('path'), - tls = require('tls'); +const fs = require('fs'); +const path = require('path'); +const tls = require('tls'); const common = require('../common.js'); const bench = common.createBenchmark(main, { diff --git a/test/parallel/test-cluster-worker-kill.js b/test/parallel/test-cluster-worker-kill.js index 38e2deb1555c2d..bb2d3495d95a4d 100644 --- a/test/parallel/test-cluster-worker-kill.js +++ b/test/parallel/test-cluster-worker-kill.js @@ -40,29 +40,28 @@ if (cluster.isWorker) { } else if (cluster.isMaster) { - const KILL_SIGNAL = 'SIGKILL', - expected_results = { - cluster_emitDisconnect: [1, "the cluster did not emit 'disconnect'"], - cluster_emitExit: [1, "the cluster did not emit 'exit'"], - cluster_exitCode: [null, 'the cluster exited w/ incorrect exitCode'], - cluster_signalCode: [KILL_SIGNAL, - 'the cluster exited w/ incorrect signalCode'], - worker_emitDisconnect: [1, "the worker did not emit 'disconnect'"], - worker_emitExit: [1, "the worker did not emit 'exit'"], - worker_state: ['disconnected', 'the worker state is incorrect'], - worker_exitedAfter: [false, - 'the .exitedAfterDisconnect flag is incorrect'], - worker_died: [true, 'the worker is still running'], - worker_exitCode: [null, 'the worker exited w/ incorrect exitCode'], - worker_signalCode: [KILL_SIGNAL, - 'the worker exited w/ incorrect signalCode'] - }, - results = { - cluster_emitDisconnect: 0, - cluster_emitExit: 0, - worker_emitDisconnect: 0, - worker_emitExit: 0 - }; + const KILL_SIGNAL = 'SIGKILL'; + const expected_results = { + cluster_emitDisconnect: [1, "the cluster did not emit 'disconnect'"], + cluster_emitExit: [1, "the cluster did not emit 'exit'"], + cluster_exitCode: [null, 'the cluster exited w/ incorrect exitCode'], + cluster_signalCode: [KILL_SIGNAL, + 'the cluster exited w/ incorrect signalCode'], + worker_emitDisconnect: [1, "the worker did not emit 'disconnect'"], + worker_emitExit: [1, "the worker did not emit 'exit'"], + worker_state: ['disconnected', 'the worker state is incorrect'], + worker_exitedAfter: [false, 'the .exitedAfterDisconnect flag is incorrect'], + worker_died: [true, 'the worker is still running'], + worker_exitCode: [null, 'the worker exited w/ incorrect exitCode'], + worker_signalCode: [KILL_SIGNAL, + 'the worker exited w/ incorrect signalCode'] + }; + const results = { + cluster_emitDisconnect: 0, + cluster_emitExit: 0, + worker_emitDisconnect: 0, + worker_emitExit: 0 + }; // start worker From cb732aeda47f17aeafad567fa90cfdf5f09d3d6d Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 17 Feb 2018 03:58:50 +0100 Subject: [PATCH 126/134] doc: enable eslint prefer-template rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/18831 Reviewed-By: Luigi Pinca Reviewed-By: Matheus Marchini Reviewed-By: Anna Henningsen Reviewed-By: Michaël Zasso Reviewed-By: Anatoli Papirovski Reviewed-By: Colin Ihrig --- doc/.eslintrc.yaml | 1 + doc/api/esm.md | 4 ++-- doc/api/stream.md | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/.eslintrc.yaml b/doc/.eslintrc.yaml index c8c1612e3a100b..7b38afec10276a 100644 --- a/doc/.eslintrc.yaml +++ b/doc/.eslintrc.yaml @@ -12,6 +12,7 @@ rules: no-var: error prefer-const: error prefer-rest-params: error + prefer-template: error # Stylistic Issues no-multiple-empty-lines: [error, {max: 1, maxEOF: 0, maxBOF: 0}] diff --git a/doc/api/esm.md b/doc/api/esm.md index e6c8525dbc02d4..4f658bc6802ad9 100644 --- a/doc/api/esm.md +++ b/doc/api/esm.md @@ -114,7 +114,7 @@ given module specifier and parent file URL: ```js const baseURL = new URL('file://'); -baseURL.pathname = process.cwd() + '/'; +baseURL.pathname = `${process.cwd()}/`; export async function resolve(specifier, parentModuleURL = baseURL, @@ -158,7 +158,7 @@ const builtins = Module.builtinModules; const JS_EXTENSIONS = new Set(['.js', '.mjs']); const baseURL = new URL('file://'); -baseURL.pathname = process.cwd() + '/'; +baseURL.pathname = `${process.cwd()}/`; export function resolve(specifier, parentModuleURL = baseURL, defaultResolve) { if (builtins.includes(specifier)) { diff --git a/doc/api/stream.md b/doc/api/stream.md index a92e11e71a2402..99c159dfefe86b 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -1801,7 +1801,7 @@ class Counter extends Readable { if (i > this._max) this.push(null); else { - const str = '' + i; + const str = String(i); const buf = Buffer.from(str, 'ascii'); this.push(buf); } From d57a2421fc24c0e56d9c7190b5fcfb78f095e988 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 19 Feb 2018 01:49:30 +0100 Subject: [PATCH 127/134] errors: implement new error handling This implements a function based system. Instead of passing in the error code as first argument, the error code itself is a error class. It already contains the correct error type, so while adding a new error no one has to think about the error type anymore. In case a single error code has more than one error type, the error class has properties for the non default error types. Those can be used as fallback. This prevents typos, makes the implementation easier and it is less verbose when writing the code for a new error. The implementation itself does not interfere with the old implementation. So the old and the new system can co-exist and it is possible to slowly migrate the old ones to the new system. Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/18857 Reviewed-By: Anna Henningsen Reviewed-By: Gus Caplan Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- lib/internal/errors.js | 56 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 9cc731e99fb3af..50d1cd3fb53b2c 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -12,6 +12,7 @@ const kCode = Symbol('code'); const messages = new Map(); +const codes = {}; var green = ''; var red = ''; @@ -194,6 +195,54 @@ function createErrDiff(actual, expected, operator) { return `${msg}${skipped ? skippedMsg : ''}\n${res}${other}${end}`; } +function makeNodeErrorWithCode(Base, key) { + return class NodeError extends Base { + constructor(...args) { + super(message(key, args)); + } + + get name() { + return `${super.name} [${key}]`; + } + + set name(value) { + defineProperty(this, 'name', { + configurable: true, + enumerable: true, + value, + writable: true + }); + } + + get code() { + return key; + } + + set code(value) { + defineProperty(this, 'code', { + configurable: true, + enumerable: true, + value, + writable: true + }); + } + }; +} + +// Utility function for registering the error codes. Only used here. Exported +// *only* to allow for testing. +function E(sym, val, def, ...otherClasses) { + messages.set(sym, val); + if (def === undefined) return; + def = makeNodeErrorWithCode(def, sym); + if (otherClasses.length !== 0) { + otherClasses.forEach((clazz) => { + def[clazz.name] = makeNodeErrorWithCode(clazz, sym); + }); + } + codes[sym] = def; +} + class AssertionError extends Error { constructor(options) { if (typeof options !== 'object' || options === null) { @@ -296,12 +345,6 @@ function message(key, args) { return String(fmt.apply(null, args)); } -// Utility function for registering the error codes. Only used here. Exported -// *only* to allow for testing. -function E(sym, val) { - messages.set(sym, typeof val === 'function' ? val : String(val)); -} - /** * This used to be util._errnoException(). * @@ -412,6 +455,7 @@ module.exports = exports = { RangeError: makeNodeError(RangeError), URIError: makeNodeError(URIError), AssertionError, + codes, E // This is exported only to facilitate testing. }; From ffa16aad60eba68baa1e75129b4f7e79581cfff1 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 19 Feb 2018 01:50:56 +0100 Subject: [PATCH 128/134] errors: update all internal errors This updates all internal errors to the new error type. While doing so it removes unused errors. A few errors currently seem to have the wrong type. To identify them later, comments were added next to the error type. Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/18857 Reviewed-By: Anna Henningsen Reviewed-By: Gus Caplan Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- doc/api/errors.md | 55 ---- lib/internal/errors.js | 383 +++++++++++++------------- test/parallel/test-internal-errors.js | 13 - 3 files changed, 199 insertions(+), 252 deletions(-) diff --git a/doc/api/errors.md b/doc/api/errors.md index 95700d0f6707bf..0f60cdcc913f6c 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -735,12 +735,6 @@ falsy value. An attempt was made to add more headers after the headers had already been sent. - -### ERR_HTTP_INVALID_CHAR - -An invalid character was found in an HTTP response status message (reason -phrase). - ### ERR_HTTP_INVALID_STATUS_CODE @@ -752,11 +746,6 @@ Status code was outside the regular status code range (100-999). The `Trailer` header was set even though the transfer encoding does not support that. - -### ERR_HTTP2_ALREADY_SHUTDOWN - -Occurs with multiple attempts to shutdown an HTTP/2 session. - ### ERR_HTTP2_ALTSVC_INVALID_ORIGIN @@ -785,22 +774,12 @@ forbidden. For HTTP/2 requests using the `CONNECT` method, the `:scheme` pseudo-header is forbidden. - -### ERR_HTTP2_FRAME_ERROR - -A failure occurred sending an individual frame on the HTTP/2 session. - ### ERR_HTTP2_GOAWAY_SESSION New HTTP/2 Streams may not be opened after the `Http2Session` has received a `GOAWAY` frame from the connected peer. - -### ERR_HTTP2_HEADER_REQUIRED - -A required header was missing in an HTTP/2 message. - ### ERR_HTTP2_HEADER_SINGLE_VALUE @@ -812,22 +791,11 @@ have only a single value. An additional headers was specified after an HTTP/2 response was initiated. - -### ERR_HTTP2_HEADERS_OBJECT - -An HTTP/2 Headers Object was expected. - ### ERR_HTTP2_HEADERS_SENT An attempt was made to send multiple response headers. - -### ERR_HTTP2_INFO_HEADERS_AFTER_RESPOND - -HTTP/2 Informational headers must only be sent *prior* to calling the -`Http2Stream.prototype.respond()` method. - ### ERR_HTTP2_INFO_STATUS_NOT_ALLOWED @@ -1218,14 +1186,6 @@ strict compliance with the API specification (which in some cases may accept `func(undefined)` and `func()` are treated identically, and the [`ERR_INVALID_ARG_TYPE`][] error code may be used instead. - -### ERR_MISSING_DYNAMIC_INSTANTIATE_HOOK - -> Stability: 1 - Experimental - -An [ES6 module][] loader hook specified `format: 'dynamic` but did not provide a -`dynamicInstantiate` hook. - ### ERR_MISSING_MODULE @@ -1254,11 +1214,6 @@ would be possible by calling a callback more than once. While using `N-API`, a constructor passed was not a function. - -### ERR_NAPI_CONS_PROTOTYPE_OBJECT - -While using `N-API`, `Constructor.prototype` was not an object. - ### ERR_NAPI_INVALID_DATAVIEW_ARGS @@ -1300,11 +1255,6 @@ A Node.js API was called in an unsupported manner, such as An input argument value was outside an acceptable range. - -### ERR_PARSE_HISTORY_DATA - -The `REPL` module was unable parse data from the REPL history file. - ### ERR_REQUIRE_ESM @@ -1442,11 +1392,6 @@ recommended to use 2048 bits or larger for stronger security. A TLS/SSL handshake timed out. In this case, the server must also abort the connection. - -### ERR_TLS_RENEGOTIATION_FAILED - -A TLS renegotiation request has failed in a non-specific way. - ### ERR_TLS_REQUIRED_SERVER_NAME diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 50d1cd3fb53b2c..c349afe52ac050 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -472,124 +472,127 @@ module.exports = exports = { // Any error code added here should also be added to the documentation // // Note: Please try to keep these in alphabetical order -E('ERR_ARG_NOT_ITERABLE', '%s must be iterable'); -E('ERR_ASSERTION', '%s'); -E('ERR_ASYNC_CALLBACK', '%s must be a function'); -E('ERR_ASYNC_TYPE', 'Invalid name for async "type": %s'); -E('ERR_BUFFER_OUT_OF_BOUNDS', bufferOutOfBounds); +// +// Note: Node.js specific errors must begin with the prefix ERR_ + +E('ERR_ARG_NOT_ITERABLE', '%s must be iterable', TypeError); +E('ERR_ASSERTION', '%s', AssertionError); +E('ERR_ASYNC_CALLBACK', '%s must be a function', TypeError); +E('ERR_ASYNC_TYPE', 'Invalid name for async "type": %s', TypeError); +E('ERR_BUFFER_OUT_OF_BOUNDS', bufferOutOfBounds, RangeError); E('ERR_BUFFER_TOO_LARGE', - `Cannot create a Buffer larger than 0x${kMaxLength.toString(16)} bytes`); -E('ERR_CHILD_CLOSED_BEFORE_REPLY', 'Child closed before reply received'); + `Cannot create a Buffer larger than 0x${kMaxLength.toString(16)} bytes`, + RangeError); +E('ERR_CHILD_CLOSED_BEFORE_REPLY', + 'Child closed before reply received', Error); E('ERR_CONSOLE_WRITABLE_STREAM', - 'Console expects a writable stream instance for %s'); -E('ERR_CPU_USAGE', 'Unable to obtain cpu usage %s'); + 'Console expects a writable stream instance for %s', TypeError); +E('ERR_CPU_USAGE', 'Unable to obtain cpu usage %s', Error); E('ERR_CRYPTO_CUSTOM_ENGINE_NOT_SUPPORTED', - 'Custom engines not supported by this OpenSSL'); -E('ERR_CRYPTO_ECDH_INVALID_FORMAT', 'Invalid ECDH format: %s'); -E('ERR_CRYPTO_ENGINE_UNKNOWN', 'Engine "%s" was not found'); + 'Custom engines not supported by this OpenSSL', Error); +E('ERR_CRYPTO_ECDH_INVALID_FORMAT', 'Invalid ECDH format: %s', TypeError); +E('ERR_CRYPTO_ENGINE_UNKNOWN', 'Engine "%s" was not found', Error); E('ERR_CRYPTO_FIPS_FORCED', - 'Cannot set FIPS mode, it was forced with --force-fips at startup.'); -E('ERR_CRYPTO_FIPS_UNAVAILABLE', 'Cannot set FIPS mode in a non-FIPS build.'); -E('ERR_CRYPTO_HASH_DIGEST_NO_UTF16', 'hash.digest() does not support UTF-16'); -E('ERR_CRYPTO_HASH_FINALIZED', 'Digest already called'); -E('ERR_CRYPTO_HASH_UPDATE_FAILED', 'Hash update failed'); -E('ERR_CRYPTO_INVALID_DIGEST', 'Invalid digest: %s'); -E('ERR_CRYPTO_SIGN_KEY_REQUIRED', 'No key provided to sign'); + 'Cannot set FIPS mode, it was forced with --force-fips at startup.', Error); +E('ERR_CRYPTO_FIPS_UNAVAILABLE', 'Cannot set FIPS mode in a non-FIPS build.', + Error); +E('ERR_CRYPTO_HASH_DIGEST_NO_UTF16', 'hash.digest() does not support UTF-16', + Error); +E('ERR_CRYPTO_HASH_FINALIZED', 'Digest already called', Error); +E('ERR_CRYPTO_HASH_UPDATE_FAILED', 'Hash update failed', Error); +E('ERR_CRYPTO_INVALID_DIGEST', 'Invalid digest: %s', TypeError); +// Switch to TypeError. The current implementation does not seem right. +E('ERR_CRYPTO_SIGN_KEY_REQUIRED', 'No key provided to sign', Error); E('ERR_CRYPTO_TIMING_SAFE_EQUAL_LENGTH', - 'Input buffers must have the same length'); -E('ERR_DNS_SET_SERVERS_FAILED', 'c-ares failed to set servers: "%s" [%s]'); + 'Input buffers must have the same length', RangeError); +E('ERR_DNS_SET_SERVERS_FAILED', 'c-ares failed to set servers: "%s" [%s]', + Error); E('ERR_DOMAIN_CALLBACK_NOT_AVAILABLE', 'A callback was registered through ' + - 'process.setUncaughtExceptionCaptureCallback(), which is mutually ' + - 'exclusive with using the `domain` module'); + 'process.setUncaughtExceptionCaptureCallback(), which is mutually ' + + 'exclusive with using the `domain` module', + Error); E('ERR_DOMAIN_CANNOT_SET_UNCAUGHT_EXCEPTION_CAPTURE', 'The `domain` module is in use, which is mutually exclusive with calling ' + - 'process.setUncaughtExceptionCaptureCallback()'); + 'process.setUncaughtExceptionCaptureCallback()', + Error); E('ERR_ENCODING_INVALID_ENCODED_DATA', - 'The encoded data was not valid for encoding %s'); -E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported'); -E('ERR_FALSY_VALUE_REJECTION', 'Promise was rejected with falsy value'); -E('ERR_HTTP2_ALREADY_SHUTDOWN', - 'Http2Session is already shutdown or destroyed'); + 'The encoded data was not valid for encoding %s', TypeError); +E('ERR_ENCODING_NOT_SUPPORTED', 'The "%s" encoding is not supported', + RangeError); // One entry is currently falsy implemented as "Error" +E('ERR_FALSY_VALUE_REJECTION', 'Promise was rejected with falsy value', Error); E('ERR_HTTP2_ALTSVC_INVALID_ORIGIN', - 'HTTP/2 ALTSVC frames require a valid origin'); + 'HTTP/2 ALTSVC frames require a valid origin', TypeError); E('ERR_HTTP2_ALTSVC_LENGTH', - 'HTTP/2 ALTSVC frames are limited to 16382 bytes'); + 'HTTP/2 ALTSVC frames are limited to 16382 bytes', TypeError); E('ERR_HTTP2_CONNECT_AUTHORITY', - ':authority header is required for CONNECT requests'); + ':authority header is required for CONNECT requests', Error); E('ERR_HTTP2_CONNECT_PATH', - 'The :path header is forbidden for CONNECT requests'); + 'The :path header is forbidden for CONNECT requests', Error); E('ERR_HTTP2_CONNECT_SCHEME', - 'The :scheme header is forbidden for CONNECT requests'); -E('ERR_HTTP2_FRAME_ERROR', - (type, code, id) => { - let msg = `Error sending frame type ${type}`; - if (id !== undefined) - msg += ` for stream ${id}`; - msg += ` with code ${code}`; - return msg; - }); + 'The :scheme header is forbidden for CONNECT requests', Error); E('ERR_HTTP2_GOAWAY_SESSION', - 'New streams cannot be created after receiving a GOAWAY'); + 'New streams cannot be created after receiving a GOAWAY', Error); E('ERR_HTTP2_HEADERS_AFTER_RESPOND', - 'Cannot specify additional headers after response initiated'); -E('ERR_HTTP2_HEADERS_OBJECT', 'Headers must be an object'); -E('ERR_HTTP2_HEADERS_SENT', 'Response has already been initiated.'); -E('ERR_HTTP2_HEADER_REQUIRED', 'The %s header is required'); + 'Cannot specify additional headers after response initiated', Error); +E('ERR_HTTP2_HEADERS_SENT', 'Response has already been initiated.', Error); E('ERR_HTTP2_HEADER_SINGLE_VALUE', - 'Header field "%s" must have only a single value'); -E('ERR_HTTP2_INFO_HEADERS_AFTER_RESPOND', - 'Cannot send informational headers after the HTTP message has been sent'); + 'Header field "%s" must have only a single value', Error); E('ERR_HTTP2_INFO_STATUS_NOT_ALLOWED', - 'Informational status codes cannot be used'); + 'Informational status codes cannot be used', RangeError); E('ERR_HTTP2_INVALID_CONNECTION_HEADERS', - 'HTTP/1 Connection specific headers are forbidden: "%s"'); -E('ERR_HTTP2_INVALID_HEADER_VALUE', 'Invalid value "%s" for header "%s"'); + 'HTTP/1 Connection specific headers are forbidden: "%s"', Error); +E('ERR_HTTP2_INVALID_HEADER_VALUE', + 'Invalid value "%s" for header "%s"', TypeError); E('ERR_HTTP2_INVALID_INFO_STATUS', - 'Invalid informational status code: %s'); + 'Invalid informational status code: %s', RangeError); E('ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH', - 'Packed settings length must be a multiple of six'); + 'Packed settings length must be a multiple of six', RangeError); E('ERR_HTTP2_INVALID_PSEUDOHEADER', - '"%s" is an invalid pseudoheader or is used incorrectly'); -E('ERR_HTTP2_INVALID_SESSION', 'The session has been destroyed'); + '"%s" is an invalid pseudoheader or is used incorrectly', Error); +E('ERR_HTTP2_INVALID_SESSION', 'The session has been destroyed', Error); E('ERR_HTTP2_INVALID_SETTING_VALUE', - 'Invalid value for setting "%s": %s'); -E('ERR_HTTP2_INVALID_STREAM', 'The stream has been destroyed'); + 'Invalid value for setting "%s": %s', TypeError, RangeError); +E('ERR_HTTP2_INVALID_STREAM', 'The stream has been destroyed', Error); E('ERR_HTTP2_MAX_PENDING_SETTINGS_ACK', - 'Maximum number of pending settings acknowledgements (%s)'); + 'Maximum number of pending settings acknowledgements (%s)', Error); E('ERR_HTTP2_NO_SOCKET_MANIPULATION', - 'HTTP/2 sockets should not be directly manipulated (e.g. read and written)'); + 'HTTP/2 sockets should not be directly manipulated (e.g. read and written)', + Error); E('ERR_HTTP2_OUT_OF_STREAMS', - 'No stream ID is available because maximum stream ID has been reached'); + 'No stream ID is available because maximum stream ID has been reached', + Error); E('ERR_HTTP2_PAYLOAD_FORBIDDEN', - 'Responses with %s status must not have a payload'); -E('ERR_HTTP2_PING_CANCEL', 'HTTP2 ping cancelled'); -E('ERR_HTTP2_PING_LENGTH', 'HTTP2 ping payload must be 8 bytes'); -E('ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED', 'Cannot set HTTP/2 pseudo-headers'); -E('ERR_HTTP2_PUSH_DISABLED', 'HTTP/2 client has disabled push streams'); -E('ERR_HTTP2_SEND_FILE', 'Only regular files can be sent'); -E('ERR_HTTP2_SESSION_ERROR', 'Session closed with error code %s'); + 'Responses with %s status must not have a payload', Error); +E('ERR_HTTP2_PING_CANCEL', 'HTTP2 ping cancelled', Error); +E('ERR_HTTP2_PING_LENGTH', 'HTTP2 ping payload must be 8 bytes', RangeError); +E('ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED', + 'Cannot set HTTP/2 pseudo-headers', Error); +E('ERR_HTTP2_PUSH_DISABLED', 'HTTP/2 client has disabled push streams', Error); +E('ERR_HTTP2_SEND_FILE', 'Only regular files can be sent', Error); +E('ERR_HTTP2_SESSION_ERROR', 'Session closed with error code %s', Error); E('ERR_HTTP2_SOCKET_BOUND', - 'The socket is already bound to an Http2Session'); + 'The socket is already bound to an Http2Session', Error); E('ERR_HTTP2_STATUS_101', - 'HTTP status code 101 (Switching Protocols) is forbidden in HTTP/2'); -E('ERR_HTTP2_STATUS_INVALID', 'Invalid status code: %s'); -E('ERR_HTTP2_STREAM_CANCEL', 'The pending stream has been canceled'); -E('ERR_HTTP2_STREAM_ERROR', 'Stream closed with error code %s'); -E('ERR_HTTP2_STREAM_SELF_DEPENDENCY', 'A stream cannot depend on itself'); -E('ERR_HTTP2_UNSUPPORTED_PROTOCOL', 'protocol "%s" is unsupported.'); + 'HTTP status code 101 (Switching Protocols) is forbidden in HTTP/2', Error); +E('ERR_HTTP2_STATUS_INVALID', 'Invalid status code: %s', RangeError); +E('ERR_HTTP2_STREAM_CANCEL', 'The pending stream has been canceled', Error); +E('ERR_HTTP2_STREAM_ERROR', 'Stream closed with error code %s', Error); +E('ERR_HTTP2_STREAM_SELF_DEPENDENCY', + 'A stream cannot depend on itself', Error); +E('ERR_HTTP2_UNSUPPORTED_PROTOCOL', 'protocol "%s" is unsupported.', Error); E('ERR_HTTP_HEADERS_SENT', - 'Cannot %s headers after they are sent to the client'); -E('ERR_HTTP_INVALID_CHAR', 'Invalid character in statusMessage.'); -E('ERR_HTTP_INVALID_STATUS_CODE', 'Invalid status code: %s'); + 'Cannot %s headers after they are sent to the client', Error); +E('ERR_HTTP_INVALID_STATUS_CODE', 'Invalid status code: %s', RangeError); E('ERR_HTTP_TRAILER_INVALID', - 'Trailers are invalid with this transfer encoding'); -E('ERR_INDEX_OUT_OF_RANGE', 'Index out of range'); -E('ERR_INSPECTOR_ALREADY_CONNECTED', 'The inspector is already connected'); -E('ERR_INSPECTOR_CLOSED', 'Session was closed'); -E('ERR_INSPECTOR_NOT_AVAILABLE', 'Inspector is not available'); -E('ERR_INSPECTOR_NOT_CONNECTED', 'Session is not connected'); -E('ERR_INVALID_ARG_TYPE', invalidArgType); + 'Trailers are invalid with this transfer encoding', Error); +E('ERR_INDEX_OUT_OF_RANGE', 'Index out of range', RangeError); +E('ERR_INSPECTOR_ALREADY_CONNECTED', + 'The inspector is already connected', Error); +E('ERR_INSPECTOR_CLOSED', 'Session was closed', Error); +E('ERR_INSPECTOR_NOT_AVAILABLE', 'Inspector is not available', Error); +E('ERR_INSPECTOR_NOT_CONNECTED', 'Session is not connected', Error); +E('ERR_INVALID_ARG_TYPE', invalidArgType, TypeError); E('ERR_INVALID_ARG_VALUE', (name, value, reason = 'is invalid') => { const util = lazyUtil(); let inspected = util.inspect(value); @@ -597,136 +600,148 @@ E('ERR_INVALID_ARG_VALUE', (name, value, reason = 'is invalid') => { inspected = inspected.slice(0, 128) + '...'; } return `The argument '${name}' ${reason}. Received ${inspected}`; -}), +}, TypeError, RangeError); // Some are currently falsy implemented as "Error" E('ERR_INVALID_ARRAY_LENGTH', (name, len, actual) => { internalAssert(typeof actual === 'number', 'actual must be a number'); return `The array "${name}" (length ${actual}) must be of length ${len}.`; - }); -E('ERR_INVALID_ASYNC_ID', 'Invalid %s value: %s'); -E('ERR_INVALID_BUFFER_SIZE', 'Buffer size must be a multiple of %s'); -E('ERR_INVALID_CALLBACK', 'Callback must be a function'); -E('ERR_INVALID_CHAR', invalidChar); + }, TypeError); +E('ERR_INVALID_ASYNC_ID', 'Invalid %s value: %s', RangeError); +E('ERR_INVALID_BUFFER_SIZE', + 'Buffer size must be a multiple of %s', RangeError); +E('ERR_INVALID_CALLBACK', 'Callback must be a function', TypeError); +E('ERR_INVALID_CHAR', invalidChar, TypeError); //Check falsy "Error" entries. E('ERR_INVALID_CURSOR_POS', - 'Cannot set cursor row without setting its column'); -E('ERR_INVALID_DOMAIN_NAME', 'Unable to determine the domain name'); -E('ERR_INVALID_FD', '"fd" must be a positive integer: %s'); -E('ERR_INVALID_FD_TYPE', 'Unsupported fd type: %s'); + 'Cannot set cursor row without setting its column', Error); +E('ERR_INVALID_DOMAIN_NAME', 'Unable to determine the domain name', Error); +E('ERR_INVALID_FD', + '"fd" must be a positive integer: %s', RangeError); +E('ERR_INVALID_FD_TYPE', 'Unsupported fd type: %s', TypeError); E('ERR_INVALID_FILE_URL_HOST', - 'File URL host must be "localhost" or empty on %s'); -E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s'); -E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent'); -E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]'); -E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s'); + 'File URL host must be "localhost" or empty on %s', TypeError); +E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s', TypeError); +E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent', TypeError); +E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]', TypeError); +E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s', TypeError, Error); E('ERR_INVALID_OPT_VALUE', (name, value) => - `The value "${String(value)}" is invalid for option "${name}"`); + `The value "${String(value)}" is invalid for option "${name}"`, + TypeError, + RangeError); E('ERR_INVALID_OPT_VALUE_ENCODING', - 'The value "%s" is invalid for option "encoding"'); -E('ERR_INVALID_PERFORMANCE_MARK', 'The "%s" performance mark has not been set'); -E('ERR_INVALID_PROTOCOL', 'Protocol "%s" not supported. Expected "%s"'); + 'The value "%s" is invalid for option "encoding"', TypeError); +E('ERR_INVALID_PERFORMANCE_MARK', + 'The "%s" performance mark has not been set', Error); +E('ERR_INVALID_PROTOCOL', 'Protocol "%s" not supported. Expected "%s"', Error); E('ERR_INVALID_REPL_EVAL_CONFIG', - 'Cannot specify both "breakEvalOnSigint" and "eval" for REPL'); + 'Cannot specify both "breakEvalOnSigint" and "eval" for REPL', Error); E('ERR_INVALID_SYNC_FORK_INPUT', - 'Asynchronous forks do not support Buffer, Uint8Array or string input: %s'); -E('ERR_INVALID_THIS', 'Value of "this" must be of type %s'); -E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple'); -E('ERR_INVALID_URI', 'URI malformed'); -E('ERR_INVALID_URL', 'Invalid URL: %s'); + 'Asynchronous forks do not support Buffer, Uint8Array or string input: %s', + TypeError); +E('ERR_INVALID_THIS', 'Value of "this" must be of type %s', TypeError); +E('ERR_INVALID_TUPLE', '%s must be an iterable %s tuple', TypeError); +E('ERR_INVALID_URI', 'URI malformed', URIError); +E('ERR_INVALID_URL', 'Invalid URL: %s', TypeError); E('ERR_INVALID_URL_SCHEME', - (expected) => `The URL must be ${oneOf(expected, 'scheme')}`); -E('ERR_IPC_CHANNEL_CLOSED', 'Channel closed'); -E('ERR_IPC_DISCONNECTED', 'IPC channel is already disconnected'); -E('ERR_IPC_ONE_PIPE', 'Child process can have only one IPC pipe'); -E('ERR_IPC_SYNC_FORK', 'IPC cannot be used with synchronous forks'); -E('ERR_METHOD_NOT_IMPLEMENTED', 'The %s method is not implemented'); -E('ERR_MISSING_ARGS', missingArgs); -E('ERR_MISSING_DYNAMIC_INSTANTIATE_HOOK', - 'The ES Module loader may not return a format of \'dynamic\' when no ' + - 'dynamicInstantiate function was provided'); -E('ERR_MISSING_MODULE', 'Cannot find module %s'); -E('ERR_MODULE_RESOLUTION_LEGACY', '%s not found by import in %s.' + - ' Legacy behavior in require() would have found it at %s'); -E('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times'); -E('ERR_NAPI_CONS_FUNCTION', 'Constructor must be a function'); -E('ERR_NAPI_CONS_PROTOTYPE_OBJECT', 'Constructor.prototype must be an object'); + (expected) => `The URL must be ${oneOf(expected, 'scheme')}`, TypeError); +E('ERR_IPC_CHANNEL_CLOSED', 'Channel closed', Error); +E('ERR_IPC_DISCONNECTED', 'IPC channel is already disconnected', Error); +E('ERR_IPC_ONE_PIPE', 'Child process can have only one IPC pipe', Error); +E('ERR_IPC_SYNC_FORK', 'IPC cannot be used with synchronous forks', Error); +E('ERR_METHOD_NOT_IMPLEMENTED', 'The %s method is not implemented', Error); +E('ERR_MISSING_ARGS', missingArgs, TypeError); +E('ERR_MISSING_MODULE', 'Cannot find module %s', Error); +E('ERR_MODULE_RESOLUTION_LEGACY', + '%s not found by import in %s.' + + ' Legacy behavior in require() would have found it at %s', + Error); +E('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times', Error); +E('ERR_NAPI_CONS_FUNCTION', 'Constructor must be a function', TypeError); E('ERR_NAPI_INVALID_DATAVIEW_ARGS', 'byte_offset + byte_length should be less than or eqaul to the size in ' + - 'bytes of the array passed in'); -E('ERR_NAPI_INVALID_TYPEDARRAY_ALIGNMENT', 'start offset of %s should be a ' + - 'multiple of %s'); -E('ERR_NAPI_INVALID_TYPEDARRAY_LENGTH', 'Invalid typed array length'); -E('ERR_NO_CRYPTO', 'Node.js is not compiled with OpenSSL crypto support'); -E('ERR_NO_ICU', '%s is not supported on Node.js compiled without ICU'); -E('ERR_NO_LONGER_SUPPORTED', '%s is no longer supported'); -E('ERR_OUT_OF_RANGE', 'The "%s" argument is out of range'); -E('ERR_PARSE_HISTORY_DATA', 'Could not parse history data in %s'); -E('ERR_REQUIRE_ESM', 'Must use import to load ES Module: %s'); + 'bytes of the array passed in', + RangeError); +E('ERR_NAPI_INVALID_TYPEDARRAY_ALIGNMENT', + 'start offset of %s should be a multiple of %s', RangeError); +E('ERR_NAPI_INVALID_TYPEDARRAY_LENGTH', + 'Invalid typed array length', RangeError); +E('ERR_NO_CRYPTO', + 'Node.js is not compiled with OpenSSL crypto support', Error); +E('ERR_NO_ICU', + '%s is not supported on Node.js compiled without ICU', TypeError); +E('ERR_NO_LONGER_SUPPORTED', '%s is no longer supported', Error); +E('ERR_OUT_OF_RANGE', 'The "%s" argument is out of range', RangeError); +E('ERR_REQUIRE_ESM', 'Must use import to load ES Module: %s', Error); E('ERR_SERVER_ALREADY_LISTEN', - 'Listen method has been called more than once without closing.'); -E('ERR_SOCKET_ALREADY_BOUND', 'Socket is already bound'); -E('ERR_SOCKET_BAD_BUFFER_SIZE', 'Buffer size must be a positive integer'); -E('ERR_SOCKET_BAD_PORT', 'Port should be > 0 and < 65536. Received %s.'); + 'Listen method has been called more than once without closing.', Error); +E('ERR_SOCKET_ALREADY_BOUND', 'Socket is already bound', Error); +E('ERR_SOCKET_BAD_BUFFER_SIZE', + 'Buffer size must be a positive integer', TypeError); +E('ERR_SOCKET_BAD_PORT', + 'Port should be > 0 and < 65536. Received %s.', RangeError); E('ERR_SOCKET_BAD_TYPE', - 'Bad socket type specified. Valid types are: udp4, udp6'); -E('ERR_SOCKET_BUFFER_SIZE', 'Could not get or set buffer size: %s'); -E('ERR_SOCKET_CANNOT_SEND', 'Unable to send data'); -E('ERR_SOCKET_CLOSED', 'Socket is closed'); -E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running'); -E('ERR_STDERR_CLOSE', 'process.stderr cannot be closed'); -E('ERR_STDOUT_CLOSE', 'process.stdout cannot be closed'); -E('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable'); -E('ERR_STREAM_NULL_VALUES', 'May not write null values to stream'); -E('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF'); -E('ERR_STREAM_READ_NOT_IMPLEMENTED', '_read() is not implemented'); -E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event'); -E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode'); -E('ERR_STREAM_WRITE_AFTER_END', 'write after end'); + 'Bad socket type specified. Valid types are: udp4, udp6', TypeError); +E('ERR_SOCKET_BUFFER_SIZE', 'Could not get or set buffer size: %s', Error); +E('ERR_SOCKET_CANNOT_SEND', 'Unable to send data', Error); +E('ERR_SOCKET_CLOSED', 'Socket is closed', Error); +E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running', Error); +E('ERR_STDERR_CLOSE', 'process.stderr cannot be closed', Error); +E('ERR_STDOUT_CLOSE', 'process.stdout cannot be closed', Error); +E('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable', Error); +E('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError); +E('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF', Error); +E('ERR_STREAM_READ_NOT_IMPLEMENTED', '_read() is not implemented', Error); +E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', + 'stream.unshift() after end event', Error); +E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode', Error); +E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error); E('ERR_TLS_CERT_ALTNAME_INVALID', - 'Hostname/IP does not match certificate\'s altnames: %s'); -E('ERR_TLS_DH_PARAM_SIZE', 'DH parameter size %s is less than 2048'); -E('ERR_TLS_HANDSHAKE_TIMEOUT', 'TLS handshake timeout'); -E('ERR_TLS_RENEGOTIATION_FAILED', 'Failed to renegotiate'); + 'Hostname/IP does not match certificate\'s altnames: %s', Error); +E('ERR_TLS_DH_PARAM_SIZE', 'DH parameter size %s is less than 2048', Error); +E('ERR_TLS_HANDSHAKE_TIMEOUT', 'TLS handshake timeout', Error); E('ERR_TLS_REQUIRED_SERVER_NAME', - '"servername" is required parameter for Server.addContext'); -E('ERR_TLS_SESSION_ATTACK', 'TLS session renegotiation attack detected'); + '"servername" is required parameter for Server.addContext', Error); +E('ERR_TLS_SESSION_ATTACK', 'TLS session renegotiation attack detected', Error); E('ERR_TRANSFORM_ALREADY_TRANSFORMING', - 'Calling transform done when still transforming'); + 'Calling transform done when still transforming', Error); E('ERR_TRANSFORM_WITH_LENGTH_0', - 'Calling transform done when writableState.length != 0'); + 'Calling transform done when writableState.length != 0', Error); E('ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET', '`process.setupUncaughtExceptionCapture()` was called while a capture ' + - 'callback was already active'); -E('ERR_UNESCAPED_CHARACTERS', '%s contains unescaped characters'); + 'callback was already active', + Error); +E('ERR_UNESCAPED_CHARACTERS', '%s contains unescaped characters', TypeError); E('ERR_UNHANDLED_ERROR', (err) => { const msg = 'Unhandled error.'; if (err === undefined) return msg; return `${msg} (${err})`; - }); -E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s'); -E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s'); -E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s'); -E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s'); -E('ERR_UNKNOWN_STDIN_TYPE', 'Unknown stdin file type'); -E('ERR_UNKNOWN_STREAM_TYPE', 'Unknown stream file type'); -E('ERR_V8BREAKITERATOR', 'Full ICU data not installed. ' + - 'See https://github.com/nodejs/node/wiki/Intl'); + }, Error); +E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s', TypeError); +E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s', Error); +E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s', RangeError); +E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s', TypeError); +E('ERR_UNKNOWN_STDIN_TYPE', 'Unknown stdin file type', Error); +E('ERR_UNKNOWN_STREAM_TYPE', 'Unknown stream file type', Error); +E('ERR_V8BREAKITERATOR', + 'Full ICU data not installed. See https://github.com/nodejs/node/wiki/Intl', + Error); E('ERR_VALID_PERFORMANCE_ENTRY_TYPE', - 'At least one valid performance entry type is required'); + 'At least one valid performance entry type is required', Error); E('ERR_VALUE_OUT_OF_RANGE', (start, end, value) => { return `The value of "${start}" must be ${end}. Received "${value}"`; -}); -E('ERR_VM_MODULE_ALREADY_LINKED', 'Module has already been linked'); +}, RangeError); +E('ERR_VM_MODULE_ALREADY_LINKED', 'Module has already been linked', Error); E('ERR_VM_MODULE_DIFFERENT_CONTEXT', - 'Linked modules must use the same context'); + 'Linked modules must use the same context', Error); E('ERR_VM_MODULE_LINKING_ERRORED', - 'Linking has already failed for the provided module'); + 'Linking has already failed for the provided module', Error); E('ERR_VM_MODULE_NOT_LINKED', - 'Module must be linked before it can be instantiated'); -E('ERR_VM_MODULE_NOT_MODULE', 'Provided module is not an instance of Module'); -E('ERR_VM_MODULE_STATUS', 'Module status %s'); -E('ERR_ZLIB_BINDING_CLOSED', 'zlib binding closed'); -E('ERR_ZLIB_INITIALIZATION_FAILED', 'Initialization failed'); + 'Module must be linked before it can be instantiated', Error); +E('ERR_VM_MODULE_NOT_MODULE', + 'Provided module is not an instance of Module', Error); +E('ERR_VM_MODULE_STATUS', 'Module status %s', Error); +E('ERR_ZLIB_BINDING_CLOSED', 'zlib binding closed', Error); +E('ERR_ZLIB_INITIALIZATION_FAILED', 'Initialization failed', Error); function invalidArgType(name, expected, actual) { internalAssert(name, 'name is required'); diff --git a/test/parallel/test-internal-errors.js b/test/parallel/test-internal-errors.js index 680fedc585d161..f5876b7f568dd9 100644 --- a/test/parallel/test-internal-errors.js +++ b/test/parallel/test-internal-errors.js @@ -292,19 +292,6 @@ assert.strictEqual( errors.message('ERR_ENCODING_NOT_SUPPORTED', ['enc']), 'The "enc" encoding is not supported'); -// Test ERR_HTTP2_HEADER_REQUIRED -assert.strictEqual( - errors.message('ERR_HTTP2_HEADER_REQUIRED', ['test']), - 'The test header is required'); - -// Test ERR_HTTP2_FRAME_ERROR -assert.strictEqual( - errors.message('ERR_HTTP2_FRAME_ERROR', ['foo', 'bar', 'baz']), - 'Error sending frame type foo for stream baz with code bar'); -assert.strictEqual( - errors.message('ERR_HTTP2_FRAME_ERROR', ['foo', 'bar']), - 'Error sending frame type foo with code bar'); - // Test error messages for async_hooks assert.strictEqual( errors.message('ERR_ASYNC_CALLBACK', ['init']), From 07845fc19e496ee30c00a4abd10e3c8b4072f1f2 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 19 Feb 2018 01:51:58 +0100 Subject: [PATCH 129/134] console: port errors to new system This ports the errors to the new error system. Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/18857 Reviewed-By: Anna Henningsen Reviewed-By: Gus Caplan Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- lib/console.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/console.js b/lib/console.js index ac75664e850e56..ad6276297f26f7 100644 --- a/lib/console.js +++ b/lib/console.js @@ -21,7 +21,7 @@ 'use strict'; -const errors = require('internal/errors'); +const { ERR_CONSOLE_WRITABLE_STREAM } = require('internal/errors').codes; const util = require('util'); const kCounts = Symbol('counts'); @@ -35,12 +35,12 @@ function Console(stdout, stderr, ignoreErrors = true) { return new Console(stdout, stderr, ignoreErrors); } if (!stdout || typeof stdout.write !== 'function') { - throw new errors.TypeError('ERR_CONSOLE_WRITABLE_STREAM', 'stdout'); + throw new ERR_CONSOLE_WRITABLE_STREAM('stdout'); } if (!stderr) { stderr = stdout; } else if (typeof stderr.write !== 'function') { - throw new errors.TypeError('ERR_CONSOLE_WRITABLE_STREAM', 'stderr'); + throw new ERR_CONSOLE_WRITABLE_STREAM('stderr'); } var prop = { From f4f0266bfe63cae6d1e2990abc280ffb657d3019 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Mon, 19 Feb 2018 02:20:46 +0100 Subject: [PATCH 130/134] errors: add comments about falsy error types Some error types are not properly set. This adds comments which ones are probably falty and to what they should be set instead. Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/18857 Reviewed-By: Anna Henningsen Reviewed-By: Gus Caplan Reviewed-By: James M Snell Reviewed-By: Joyee Cheung --- lib/internal/errors.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/internal/errors.js b/lib/internal/errors.js index c349afe52ac050..d08b1bfad156c0 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -536,10 +536,14 @@ E('ERR_HTTP2_GOAWAY_SESSION', E('ERR_HTTP2_HEADERS_AFTER_RESPOND', 'Cannot specify additional headers after response initiated', Error); E('ERR_HTTP2_HEADERS_SENT', 'Response has already been initiated.', Error); + +// This should probably be a `TypeError`. E('ERR_HTTP2_HEADER_SINGLE_VALUE', 'Header field "%s" must have only a single value', Error); E('ERR_HTTP2_INFO_STATUS_NOT_ALLOWED', 'Informational status codes cannot be used', RangeError); + +// This should probably be a `TypeError`. E('ERR_HTTP2_INVALID_CONNECTION_HEADERS', 'HTTP/1 Connection specific headers are forbidden: "%s"', Error); E('ERR_HTTP2_INVALID_HEADER_VALUE', @@ -548,6 +552,8 @@ E('ERR_HTTP2_INVALID_INFO_STATUS', 'Invalid informational status code: %s', RangeError); E('ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH', 'Packed settings length must be a multiple of six', RangeError); + +// This should probably be a `TypeError`. E('ERR_HTTP2_INVALID_PSEUDOHEADER', '"%s" is an invalid pseudoheader or is used incorrectly', Error); E('ERR_HTTP2_INVALID_SESSION', 'The session has been destroyed', Error); @@ -566,6 +572,8 @@ E('ERR_HTTP2_PAYLOAD_FORBIDDEN', 'Responses with %s status must not have a payload', Error); E('ERR_HTTP2_PING_CANCEL', 'HTTP2 ping cancelled', Error); E('ERR_HTTP2_PING_LENGTH', 'HTTP2 ping payload must be 8 bytes', RangeError); + +// This should probably be a `TypeError`. E('ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED', 'Cannot set HTTP/2 pseudo-headers', Error); E('ERR_HTTP2_PUSH_DISABLED', 'HTTP/2 client has disabled push streams', Error); @@ -611,8 +619,12 @@ E('ERR_INVALID_BUFFER_SIZE', 'Buffer size must be a multiple of %s', RangeError); E('ERR_INVALID_CALLBACK', 'Callback must be a function', TypeError); E('ERR_INVALID_CHAR', invalidChar, TypeError); //Check falsy "Error" entries. + +// This should probably be a `TypeError`. E('ERR_INVALID_CURSOR_POS', 'Cannot set cursor row without setting its column', Error); + +// This should probably be a `TypeError`. E('ERR_INVALID_DOMAIN_NAME', 'Unable to determine the domain name', Error); E('ERR_INVALID_FD', '"fd" must be a positive integer: %s', RangeError); @@ -622,6 +634,7 @@ E('ERR_INVALID_FILE_URL_HOST', E('ERR_INVALID_FILE_URL_PATH', 'File URL path %s', TypeError); E('ERR_INVALID_HANDLE_TYPE', 'This handle type cannot be sent', TypeError); E('ERR_INVALID_HTTP_TOKEN', '%s must be a valid HTTP token ["%s"]', TypeError); +// The `Error` should probably be a `TypeError`. E('ERR_INVALID_IP_ADDRESS', 'Invalid IP address: %s', TypeError, Error); E('ERR_INVALID_OPT_VALUE', (name, value) => `The value "${String(value)}" is invalid for option "${name}"`, @@ -631,7 +644,11 @@ E('ERR_INVALID_OPT_VALUE_ENCODING', 'The value "%s" is invalid for option "encoding"', TypeError); E('ERR_INVALID_PERFORMANCE_MARK', 'The "%s" performance mark has not been set', Error); + +// This should probably be a `TypeError`. E('ERR_INVALID_PROTOCOL', 'Protocol "%s" not supported. Expected "%s"', Error); + +// This should probably be a `TypeError`. E('ERR_INVALID_REPL_EVAL_CONFIG', 'Cannot specify both "breakEvalOnSigint" and "eval" for REPL', Error); E('ERR_INVALID_SYNC_FORK_INPUT', @@ -703,6 +720,8 @@ E('ERR_TLS_REQUIRED_SERVER_NAME', E('ERR_TLS_SESSION_ATTACK', 'TLS session renegotiation attack detected', Error); E('ERR_TRANSFORM_ALREADY_TRANSFORMING', 'Calling transform done when still transforming', Error); + +// This should probably be a `RangeError`. E('ERR_TRANSFORM_WITH_LENGTH_0', 'Calling transform done when writableState.length != 0', Error); E('ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET', @@ -717,14 +736,20 @@ E('ERR_UNHANDLED_ERROR', return `${msg} (${err})`; }, Error); E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s', TypeError); + +// This should probably be a `TypeError`. E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s', Error); E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s', RangeError); E('ERR_UNKNOWN_SIGNAL', 'Unknown signal: %s', TypeError); E('ERR_UNKNOWN_STDIN_TYPE', 'Unknown stdin file type', Error); + +// This should probably be a `TypeError`. E('ERR_UNKNOWN_STREAM_TYPE', 'Unknown stream file type', Error); E('ERR_V8BREAKITERATOR', 'Full ICU data not installed. See https://github.com/nodejs/node/wiki/Intl', Error); + +// This should probably be a `TypeError`. E('ERR_VALID_PERFORMANCE_ENTRY_TYPE', 'At least one valid performance entry type is required', Error); E('ERR_VALUE_OUT_OF_RANGE', (start, end, value) => { From 6997af7378e77bb95f9dd73a2e41bd8953f0c15e Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 30 Dec 2017 03:20:51 +0100 Subject: [PATCH 131/134] repl: upper case comments first char MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/17919 Reviewed-By: James M Snell Reviewed-By: Tobias Nießen Reviewed-By: Luigi Pinca Reviewed-By: Weijia Wang Reviewed-By: Khaidi Chu Reviewed-By: Jon Moss Reviewed-By: Lance Ball --- lib/repl.js | 52 +++++++++++++++++++++++----------------------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index 5294bb96177e5e..f8951ba243a369 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -79,7 +79,7 @@ const kBufferedCommandSymbol = Symbol('bufferedCommand'); const kContextId = Symbol('contextId'); try { - // hack for require.resolve("./relative") to work properly. + // Hack for require.resolve("./relative") to work properly. module.filename = path.resolve('repl'); } catch (e) { // path.resolve('repl') fails when the current working directory has been @@ -89,7 +89,7 @@ try { module.filename = path.resolve(dirname, 'repl'); } -// hack for repl require to work properly with node_modules folders +// Hack for repl require to work properly with node_modules folders module.paths = Module._nodeModulePaths(module.filename); // If obj.hasOwnProperty has been overridden, then calling @@ -99,14 +99,12 @@ function hasOwnProperty(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); } - // Can overridden with custom print functions, such as `probe` or `eyes.js`. // This is the default "writer" value if none is passed in the REPL options. exports.writer = util.inspect; exports._builtinLibs = internalModule.builtinLibs; - function REPLServer(prompt, stream, eval_, @@ -149,7 +147,6 @@ function REPLServer(prompt, var self = this; self._domain = dom || domain.create(); - self.useGlobal = !!useGlobal; self.ignoreUndefined = !!ignoreUndefined; self.replMode = replMode || exports.REPL_MODE_SLOPPY; @@ -162,7 +159,7 @@ function REPLServer(prompt, // Context id for use with the inspector protocol. self[kContextId] = undefined; - // just for backwards compat, see github.com/joyent/node/pull/7127 + // Just for backwards compat, see github.com/joyent/node/pull/7127 self.rli = this; const savedRegExMatches = ['', '', '', '', '', '', '', '', '', '']; @@ -187,8 +184,7 @@ function REPLServer(prompt, wrappedCmd = true; } - // first, create the Script object to check the syntax - + // First, create the Script object to check the syntax if (code === '\n') return cb(null); @@ -207,13 +203,13 @@ function REPLServer(prompt, } catch (e) { debug('parse error %j', code, e); if (wrappedCmd) { + // Unwrap and try again wrappedCmd = false; - // unwrap and try again code = input; wrappedErr = e; continue; } - // preserve original error for wrapped command + // Preserve original error for wrapped command const error = wrappedErr || e; if (isRecoverableError(error, code)) err = new Recoverable(error); @@ -321,7 +317,7 @@ function REPLServer(prompt, if (!input && !output) { // legacy API, passing a 'stream'/'socket' option if (!stream) { - // use stdin and stdout as the default streams if none were given + // Use stdin and stdout as the default streams if none were given stream = process; } if (stream.stdin && stream.stdout) { @@ -371,7 +367,7 @@ function REPLServer(prompt, this.commands = Object.create(null); defineDefaultCommands(this); - // figure out which "writer" function to use + // Figure out which "writer" function to use self.writer = options.writer || exports.writer; if (options.useColors === undefined) { @@ -387,14 +383,14 @@ function REPLServer(prompt, } function filterInternalStackFrames(error, structuredStack) { - // search from the bottom of the call stack to + // Search from the bottom of the call stack to // find the first frame with a null function name if (typeof structuredStack !== 'object') return structuredStack; const idx = structuredStack.reverse().findIndex( (frame) => frame.getFunctionName() === null); - // if found, get rid of it and everything below it + // If found, get rid of it and everything below it structuredStack = structuredStack.splice(idx + 1); return structuredStack; } @@ -571,7 +567,7 @@ function REPLServer(prompt, return; } - // editor mode + // Editor mode if (key.ctrl && !key.shift) { switch (key.name) { case 'd': // End editor mode @@ -591,7 +587,7 @@ function REPLServer(prompt, case 'down': // Override next history item break; case 'tab': - // prevent double tab behavior + // Prevent double tab behavior self._previousKey = null; ttyWrite(d, key); break; @@ -861,10 +857,8 @@ function complete(line, callback) { } var completions; - - // list of completion lists, one for each inheritance "level" + // List of completion lists, one for each inheritance "level" var completionGroups = []; - var completeOn, i, group, c; // REPL commands (e.g. ".break"). @@ -1042,7 +1036,7 @@ function complete(line, callback) { } } } catch (e) { - //console.log("completion error walking prototype chain:" + e); + // console.log("completion error walking prototype chain:" + e); } } @@ -1085,7 +1079,7 @@ function complete(line, callback) { } if (completionGroups.length) { - var uniq = {}; // unique completions across all groups + var uniq = {}; // Unique completions across all groups completions = []; // Completion group 0 is the "closest" // (least far up the inheritance chain) @@ -1100,7 +1094,7 @@ function complete(line, callback) { uniq[c] = true; } } - completions.push(''); // separator btwn groups + completions.push(''); // Separator btwn groups } while (completions.length && completions[completions.length - 1] === '') { completions.pop(); @@ -1167,7 +1161,7 @@ function _memory(cmd) { self.lines = self.lines || []; self.lines.level = self.lines.level || []; - // save the line so I can do magic later + // Save the line so I can do magic later if (cmd) { // TODO should I tab the level? const len = self.lines.level.length ? self.lines.level.length - 1 : 0; @@ -1181,7 +1175,7 @@ function _memory(cmd) { // Because I can not tell the difference between a } that // closes an object literal and a } that closes a function if (cmd) { - // going down is { and ( e.g. function() { + // Going down is { and ( e.g. function() { // going up is } and ) var dw = cmd.match(/{|\(/g); var up = cmd.match(/}|\)/g); @@ -1192,8 +1186,8 @@ function _memory(cmd) { if (depth) { (function workIt() { if (depth > 0) { - // going... down. - // push the line#, depth count, and if the line is a function. + // Going... down. + // Push the line#, depth count, and if the line is a function. // Since JS only has functional scope I only need to remove // "function() {" lines, clearly this will not work for // "function() @@ -1205,16 +1199,16 @@ function _memory(cmd) { isFunction: /\bfunction\b/.test(cmd) }); } else if (depth < 0) { - // going... up. + // Going... up. var curr = self.lines.level.pop(); if (curr) { var tmp = curr.depth + depth; if (tmp < 0) { - //more to go, recurse + // More to go, recurse depth += curr.depth; workIt(); } else if (tmp > 0) { - //remove and push back + // Remove and push back curr.depth += depth; self.lines.level.push(curr); } From 55f7bbb0bd111c42ad7970473f44b2dd8da00a03 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 30 Dec 2017 03:22:01 +0100 Subject: [PATCH 132/134] repl: refactor code for readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backport-PR-URL: https://github.com/nodejs/node/pull/19244 PR-URL: https://github.com/nodejs/node/pull/17919 Reviewed-By: James M Snell Reviewed-By: Tobias Nießen Reviewed-By: Luigi Pinca Reviewed-By: Weijia Wang Reviewed-By: Khaidi Chu Reviewed-By: Jon Moss Reviewed-By: Lance Ball --- lib/repl.js | 83 +++++++++++++++++------------------------------------ 1 file changed, 26 insertions(+), 57 deletions(-) diff --git a/lib/repl.js b/lib/repl.js index f8951ba243a369..5779e849f06017 100644 --- a/lib/repl.js +++ b/lib/repl.js @@ -320,15 +320,10 @@ function REPLServer(prompt, // Use stdin and stdout as the default streams if none were given stream = process; } - if (stream.stdin && stream.stdout) { - // We're given custom object with 2 streams, or the `process` object - input = stream.stdin; - output = stream.stdout; - } else { - // We're given a duplex readable/writable Stream, like a `net.Socket` - input = stream; - output = stream; - } + // We're given a duplex readable/writable Stream, like a `net.Socket` + // or a custom object with 2 streams, or the `process` object + input = stream.stdin || stream; + output = stream.stdout || stream; } self.inputStream = input; @@ -663,7 +658,7 @@ REPLServer.prototype.createContext = function() { Object.defineProperty(context, 'console', { configurable: true, enumerable: true, - get: () => _console + value: _console }); var names = Object.getOwnPropertyNames(global); @@ -1035,19 +1030,16 @@ function complete(line, callback) { break; } } - } catch (e) { - // console.log("completion error walking prototype chain:" + e); - } + } catch (e) {} } if (memberGroups.length) { for (i = 0; i < memberGroups.length; i++) { - completionGroups.push(memberGroups[i].map(function(member) { - return expr + '.' + member; - })); + completionGroups.push( + memberGroups[i].map((member) => `${expr}.${member}`)); } if (filter) { - filter = expr + '.' + filter; + filter = `${expr}.${filter}`; } } @@ -1068,9 +1060,8 @@ function complete(line, callback) { if (completionGroups.length && filter) { var newCompletionGroups = []; for (i = 0; i < completionGroups.length; i++) { - group = completionGroups[i].filter(function(elem) { - return elem.indexOf(filter) === 0; - }); + group = completionGroups[i] + .filter((elem) => elem.indexOf(filter) === 0); if (group.length) { newCompletionGroups.push(group); } @@ -1400,55 +1391,33 @@ function isCodeRecoverable(code) { if (previous === '\\' && (stringLiteral || isRegExpLiteral)) { current = null; - continue; - } - - if (stringLiteral) { + } else if (stringLiteral) { if (stringLiteral === current) { stringLiteral = null; } - continue; - } else { - if (isRegExpLiteral && current === '/') { - isRegExpLiteral = false; - continue; - } - - if (isBlockComment && previous === '*' && current === '/') { - isBlockComment = false; - continue; - } - - if (isSingleComment && current === '\n') { - isSingleComment = false; - continue; - } - - if (isBlockComment || isRegExpLiteral || isSingleComment) continue; - + } else if (isRegExpLiteral && current === '/') { + isRegExpLiteral = false; + } else if (isBlockComment && previous === '*' && current === '/') { + isBlockComment = false; + } else if (isSingleComment && current === '\n') { + isSingleComment = false; + } else if (!isBlockComment && !isRegExpLiteral && !isSingleComment) { if (current === '/' && previous === '/') { isSingleComment = true; - continue; - } - - if (previous === '/') { + } else if (previous === '/') { if (current === '*') { isBlockComment = true; - } else if ( // Distinguish between a division operator and the start of a regex // by examining the non-whitespace character that precedes the / - [null, '(', '[', '{', '}', ';'].includes(prevTokenChar) - ) { + } else if ([null, '(', '[', '{', '}', ';'].includes(prevTokenChar)) { isRegExpLiteral = true; } - continue; + } else { + if (current.trim()) prevTokenChar = current; + if (current === '\'' || current === '"') { + stringLiteral = current; + } } - - if (current.trim()) prevTokenChar = current; - } - - if (current === '\'' || current === '"') { - stringLiteral = current; } } From 3914e977414c05849553328e375c8fb2c2aaa347 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Thu, 8 Mar 2018 16:22:23 +0100 Subject: [PATCH 133/134] http2: fixes error handling There should be no default error handling when using Http2Stream. All errors will end up in `'streamError'` on the server anyway, but they are emitted on `'stream'` as well, otherwise some error conditions are impossible to debug. See: https://github.com/nodejs/node/pull/14991 Backport-PR-URL: https://github.com/nodejs/node/pull/19478 PR-URL: https://github.com/nodejs/node/pull/19232 Reviewed-By: James M Snell --- lib/internal/http2/core.js | 7 ------- test/parallel/test-http2-misbehaving-multiplex.js | 7 +++++++ test/parallel/test-http2-server-errors.js | 8 ++++++-- .../parallel/test-http2-server-push-stream-head.js | 6 ++++++ test/parallel/test-http2-server-rst-stream.js | 14 +++++++++++--- .../test-http2-server-stream-session-destroy.js | 5 +++++ 6 files changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js index 4aee67b825605c..86e33d9cda0da8 100644 --- a/lib/internal/http2/core.js +++ b/lib/internal/http2/core.js @@ -2041,19 +2041,12 @@ function afterOpen(session, options, headers, streamOptions, err, fd) { headers, streamOptions)); } -function streamOnError(err) { - // we swallow the error for parity with HTTP1 - // all the errors that ends here are not critical for the project -} - - class ServerHttp2Stream extends Http2Stream { constructor(session, handle, id, options, headers) { super(session, options); this[kInit](id, handle); this[kProtocol] = headers[HTTP2_HEADER_SCHEME]; this[kAuthority] = headers[HTTP2_HEADER_AUTHORITY]; - this.on('error', streamOnError); } // true if the remote peer accepts push streams diff --git a/test/parallel/test-http2-misbehaving-multiplex.js b/test/parallel/test-http2-misbehaving-multiplex.js index 7d5a7a2f552d49..757e66b100e435 100644 --- a/test/parallel/test-http2-misbehaving-multiplex.js +++ b/test/parallel/test-http2-misbehaving-multiplex.js @@ -14,7 +14,14 @@ const server = h2.createServer(); server.on('stream', common.mustCall((stream) => { stream.respond(); stream.end('ok'); + + // the error will be emitted asynchronously + stream.on('error', common.expectsError({ + code: 'ERR_HTTP2_ERROR', + message: 'Stream was already closed or invalid' + })); }, 2)); + server.on('session', common.mustCall((session) => { session.on('error', common.expectsError({ code: 'ERR_HTTP2_ERROR', diff --git a/test/parallel/test-http2-server-errors.js b/test/parallel/test-http2-server-errors.js index a3586bd64d46e7..bbdf312fc153d4 100644 --- a/test/parallel/test-http2-server-errors.js +++ b/test/parallel/test-http2-server-errors.js @@ -54,12 +54,16 @@ const h2 = require('http2'); const server = h2.createServer(); + process.on('uncaughtException', common.mustCall(function(err) { + assert.strictEqual(err.message, 'kaboom no handler'); + })); + server.on('stream', common.mustCall(function(stream) { - // there is no 'error' handler, and this will not crash + // there is no 'error' handler, and this will crash stream.write('hello'); stream.resume(); - expected = new Error('kaboom'); + expected = new Error('kaboom no handler'); stream.destroy(expected); server.close(); })); diff --git a/test/parallel/test-http2-server-push-stream-head.js b/test/parallel/test-http2-server-push-stream-head.js index cd2276746f4bdd..35e22c0ce3b561 100644 --- a/test/parallel/test-http2-server-push-stream-head.js +++ b/test/parallel/test-http2-server-push-stream-head.js @@ -21,6 +21,12 @@ server.on('stream', common.mustCall((stream, headers) => { }, common.mustCall((err, push, headers) => { assert.strictEqual(push._writableState.ended, true); push.respond(); + // cannot write to push() anymore + push.on('error', common.expectsError({ + type: Error, + code: 'ERR_STREAM_WRITE_AFTER_END', + message: 'write after end' + })); assert(!push.write('test')); stream.end('test'); })); diff --git a/test/parallel/test-http2-server-rst-stream.js b/test/parallel/test-http2-server-rst-stream.js index d19704509a5e5f..6e4e9ccb88e611 100644 --- a/test/parallel/test-http2-server-rst-stream.js +++ b/test/parallel/test-http2-server-rst-stream.js @@ -18,14 +18,22 @@ const { const tests = [ [NGHTTP2_NO_ERROR, false], [NGHTTP2_NO_ERROR, false], - [NGHTTP2_PROTOCOL_ERROR, true], + [NGHTTP2_PROTOCOL_ERROR, true, 1], [NGHTTP2_CANCEL, false], - [NGHTTP2_REFUSED_STREAM, true], - [NGHTTP2_INTERNAL_ERROR, true] + [NGHTTP2_REFUSED_STREAM, true, 7], + [NGHTTP2_INTERNAL_ERROR, true, 2] ]; const server = http2.createServer(); server.on('stream', (stream, headers) => { + const test = tests.find((t) => t[0] === Number(headers.rstcode)); + if (test[1]) { + stream.on('error', common.expectsError({ + type: Error, + code: 'ERR_HTTP2_STREAM_ERROR', + message: `Stream closed with error code ${test[2]}` + })); + } stream.close(headers.rstcode | 0); }); diff --git a/test/parallel/test-http2-server-stream-session-destroy.js b/test/parallel/test-http2-server-stream-session-destroy.js index 5eb04a8d376635..989c72ec959679 100644 --- a/test/parallel/test-http2-server-stream-session-destroy.js +++ b/test/parallel/test-http2-server-stream-session-destroy.js @@ -34,6 +34,11 @@ server.on('stream', common.mustCall((stream) => { type: Error } ); + stream.on('error', common.expectsError({ + type: Error, + code: 'ERR_STREAM_WRITE_AFTER_END', + message: 'write after end' + })); assert.strictEqual(stream.write('data'), false); })); From 74fb02f689e5e5f911c3a85faf3cdddcd316e076 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Sun, 18 Mar 2018 14:45:41 +0100 Subject: [PATCH 134/134] 2018-03-21, Version 9.9.0 (Current) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Notable changes: * assert: - From now on all error messages produced by `assert` in strict mode will produce a error diff. (Ruben Bridgewater) https://github.com/nodejs/node/pull/17615 - From now on it is possible to use a validation object in throws instead of the other possibilities. (Ruben Bridgewater) https://github.com/nodejs/node/pull/17584 * crypto: - allow passing null as IV unless required (Tobias Nießen) https://github.com/nodejs/node/pull/18644 * fs: - support as and as+ flags in stringToFlags() (Sarat Addepalli) https://github.com/nodejs/node/pull/18801 * tls: - expose Finished messages in TLSSocket (Anton Salikhmetov) https://github.com/nodejs/node/pull/19102 * tty: - Add getColorDepth function to determine if terminal supports colors (Ruben Bridgewater) https://github.com/nodejs/node/pull/17615 * util: - add util.inspect compact option (Ruben Bridgewater) https://github.com/nodejs/node/pull/17576 * **Added new collaborators** - [watson](https://github.com/watson) Thomas Watson PR-URL: https://github.com/nodejs/node/pull/19428 --- CHANGELOG.md | 3 +- doc/api/assert.md | 12 +-- doc/api/crypto.md | 4 +- doc/api/tls.md | 4 +- doc/api/tty.md | 2 +- doc/api/util.md | 4 +- doc/changelogs/CHANGELOG_V9.md | 159 +++++++++++++++++++++++++++++++++ src/node_version.h | 6 +- 8 files changed, 177 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ace79efd98eb37..74b83c56eb87f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,8 @@ release. -9.8.0
+9.9.0
+9.8.0
9.7.1
9.7.0
9.6.1
diff --git a/doc/api/assert.md b/doc/api/assert.md index c1bcc9ebb31a5b..2ecf628e4aa80a 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -15,12 +15,12 @@ For more information about the used equality comparisons see ## Strict mode @@ -765,8 +765,8 @@ instead of the `AssertionError`. * Returns: {Buffer|undefined} The latest `Finished` message that has been @@ -646,7 +646,7 @@ If the peer does not provide a certificate, an empty object will be returned. ### tlsSocket.getPeerFinished() * Returns: {Buffer|undefined} The latest `Finished` message that is expected diff --git a/doc/api/tty.md b/doc/api/tty.md index ce6dbae8fa6e7d..a3ade6656f3c19 100644 --- a/doc/api/tty.md +++ b/doc/api/tty.md @@ -123,7 +123,7 @@ is updated whenever the `'resize'` event is emitted. ### writeStream.getColorDepth([env]) * `env` {object} A object containing the environment variables to check. diff --git a/doc/api/util.md b/doc/api/util.md index bc1d3ae262ae50..77940425e1d226 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -316,8 +316,8 @@ stream.write('With ES6');