diff options
author | Ruben Bridgewater <ruben@bridgewater.de> | 2018-05-02 16:21:40 +0200 |
---|---|---|
committer | Michaƫl Zasso <targos@protonmail.com> | 2018-05-12 17:33:24 +0200 |
commit | 5d06c1e1ae53a11d91e0b3ef0687b384e5f3c3f8 (patch) | |
tree | dedabe73d4f4dec4e6ae661c1769eb464323a914 /lib/internal/errors.js | |
parent | 01abed1c362af295bffe3c2286955928ad1dd42b (diff) | |
download | node-new-5d06c1e1ae53a11d91e0b3ef0687b384e5f3c3f8.tar.gz |
assert: move AssertionError into own file
This moves the `assert` parts from `internal/errors` into an own
file. `internal/errors` got bigger and bigger and it was difficult
to keep a good overview of what was going on. While doing so it
also removes the `internalAssert` function and just lazy loads
`assert`.
PR-URL: https://github.com/nodejs/node/pull/20486
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
Diffstat (limited to 'lib/internal/errors.js')
-rw-r--r-- | lib/internal/errors.js | 314 |
1 files changed, 18 insertions, 296 deletions
diff --git a/lib/internal/errors.js b/lib/internal/errors.js index fc306e256c..0a46e2e7a9 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -15,18 +15,6 @@ const kInfo = Symbol('info'); const messages = new Map(); const codes = {}; -let blue = ''; -let green = ''; -let red = ''; -let white = ''; - -const READABLE_OPERATOR = { - deepStrictEqual: 'Input A expected to strictly deep-equal input B', - notDeepStrictEqual: 'Input A expected to strictly not deep-equal input B', - strictEqual: 'Input A expected to strictly equal input B', - notStrictEqual: 'Input A expected to strictly not equal input B' -}; - const { errmap, UV_EAI_MEMORY, @@ -37,10 +25,10 @@ const { kMaxLength } = process.binding('buffer'); const { defineProperty } = Object; // Lazily loaded -var util; -var buffer; +let util; +let assert; -var internalUtil = null; +let internalUtil = null; function lazyInternalUtil() { if (!internalUtil) { internalUtil = require('internal/util'); @@ -48,35 +36,11 @@ function lazyInternalUtil() { return internalUtil; } -function copyError(source) { - const keys = Object.keys(source); - const target = Object.create(Object.getPrototypeOf(source)); - for (const key of keys) { - target[key] = source[key]; - } - Object.defineProperty(target, 'message', { value: source.message }); - return target; -} - -function inspectValue(val) { - // The util.inspect default values could be changed. This makes sure the - // error messages contain the necessary information nevertheless. - return util.inspect( - val, - { - compact: false, - customInspect: false, - depth: 1000, - maxArrayLength: Infinity, - // Assert compares only enumerable properties (with a few exceptions). - showHidden: false, - // Having a long line as error is better than wrapping the line for - // comparison. - breakLength: Infinity, - // Assert does not detect proxies currently. - showProxy: false - } - ).split('\n'); +let buffer; +function lazyBuffer() { + if (buffer === undefined) + buffer = require('buffer').Buffer; + return buffer; } // A specialized Error that includes an additional info property with @@ -241,254 +205,14 @@ function E(sym, val, def, ...otherClasses) { codes[sym] = def; } -function lazyBuffer() { - if (buffer === undefined) - buffer = require('buffer').Buffer; - return buffer; -} - -function createErrDiff(actual, expected, operator) { - var other = ''; - var res = ''; - var lastPos = 0; - var end = ''; - var skipped = false; - if (util === undefined) util = require('util'); - const actualLines = inspectValue(actual); - const expectedLines = inspectValue(expected); - const msg = READABLE_OPERATOR[operator] + - `:\n${green}+ expected${white} ${red}- actual${white}`; - const skippedMsg = ` ${blue}...${white} Lines skipped`; - - // Remove all ending lines that match (this optimizes the output for - // readability by reducing the number of total changed lines). - var a = actualLines[actualLines.length - 1]; - var b = expectedLines[expectedLines.length - 1]; - var i = 0; - while (a === b) { - if (i++ < 2) { - end = `\n ${a}${end}`; - } else { - other = a; - } - actualLines.pop(); - expectedLines.pop(); - if (actualLines.length === 0 || expectedLines.length === 0) - break; - a = actualLines[actualLines.length - 1]; - b = expectedLines[expectedLines.length - 1]; - } - if (i > 3) { - end = `\n${blue}...${white}${end}`; - skipped = true; - } - if (other !== '') { - end = `\n ${other}${end}`; - other = ''; - } - - const maxLines = Math.max(actualLines.length, expectedLines.length); - var printedLines = 0; - var identical = 0; - for (i = 0; i < maxLines; i++) { - // Only extra expected lines exist - const cur = i - lastPos; - if (actualLines.length < i + 1) { - if (cur > 1 && i > 2) { - if (cur > 4) { - res += `\n${blue}...${white}`; - skipped = true; - } else if (cur > 3) { - res += `\n ${expectedLines[i - 2]}`; - printedLines++; - } - res += `\n ${expectedLines[i - 1]}`; - printedLines++; - } - lastPos = i; - other += `\n${green}+${white} ${expectedLines[i]}`; - printedLines++; - // Only extra actual lines exist - } else if (expectedLines.length < i + 1) { - if (cur > 1 && i > 2) { - if (cur > 4) { - res += `\n${blue}...${white}`; - skipped = true; - } else if (cur > 3) { - res += `\n ${actualLines[i - 2]}`; - printedLines++; - } - res += `\n ${actualLines[i - 1]}`; - printedLines++; - } - lastPos = i; - res += `\n${red}-${white} ${actualLines[i]}`; - printedLines++; - // Lines diverge - } else if (actualLines[i] !== expectedLines[i]) { - if (cur > 1 && i > 2) { - if (cur > 4) { - res += `\n${blue}...${white}`; - skipped = true; - } else if (cur > 3) { - res += `\n ${actualLines[i - 2]}`; - printedLines++; - } - res += `\n ${actualLines[i - 1]}`; - printedLines++; - } - lastPos = i; - res += `\n${red}-${white} ${actualLines[i]}`; - other += `\n${green}+${white} ${expectedLines[i]}`; - printedLines += 2; - // Lines are identical - } else { - res += other; - other = ''; - if (cur === 1 || i === 0) { - res += `\n ${actualLines[i]}`; - printedLines++; - } - identical++; - } - // Inspected object to big (Show ~20 rows max) - if (printedLines > 20 && i < maxLines - 2) { - return `${msg}${skippedMsg}\n${res}\n${blue}...${white}${other}\n` + - `${blue}...${white}`; - } - } - - // Strict equal with identical objects that are not identical by reference. - if (identical === maxLines) { - // E.g., assert.deepStrictEqual(Symbol(), Symbol()) - const base = operator === 'strictEqual' ? - 'Input objects identical but not reference equal:' : - 'Input objects not identical:'; - - // We have to get the result again. The lines were all removed before. - const actualLines = inspectValue(actual); - - // Only remove lines in case it makes sense to collapse those. - // TODO: Accept env to always show the full error. - if (actualLines.length > 30) { - actualLines[26] = `${blue}...${white}`; - while (actualLines.length > 27) { - actualLines.pop(); - } - } - - return `${base}\n\n${actualLines.join('\n')}\n`; - } - return `${msg}${skipped ? skippedMsg : ''}\n${res}${other}${end}`; -} - -class AssertionError extends Error { - constructor(options) { - if (typeof options !== 'object' || options === null) { - throw new codes.ERR_INVALID_ARG_TYPE('options', 'Object', options); - } - var { - actual, - expected, - message, - operator, - stackStartFn - } = options; - - if (message != null) { - super(message); - } else { - if (process.stdout.isTTY) { - // Reset on each call to make sure we handle dynamically set environment - // variables correct. - if (process.stdout.getColorDepth() !== 1) { - blue = '\u001b[34m'; - green = '\u001b[32m'; - white = '\u001b[39m'; - red = '\u001b[31m'; - } else { - blue = ''; - green = ''; - white = ''; - red = ''; - } - } - if (util === undefined) util = require('util'); - // Prevent the error stack from being visible by duplicating the error - // in a very close way to the original in case both sides are actually - // instances of Error. - if (typeof actual === 'object' && actual !== null && - typeof expected === 'object' && expected !== null && - 'stack' in actual && actual instanceof Error && - 'stack' in expected && expected instanceof Error) { - actual = copyError(actual); - expected = copyError(expected); - } - - if (operator === 'deepStrictEqual' || operator === 'strictEqual') { - super(createErrDiff(actual, expected, operator)); - } else if (operator === 'notDeepStrictEqual' || - operator === 'notStrictEqual') { - // In case the objects are equal but the operator requires unequal, show - // the first object and say A equals B - const res = inspectValue(actual); - const base = `Identical input passed to ${operator}:`; - - // Only remove lines in case it makes sense to collapse those. - // TODO: Accept env to always show the full error. - if (res.length > 30) { - res[26] = `${blue}...${white}`; - while (res.length > 27) { - res.pop(); - } - } - - // Only print a single input. - if (res.length === 1) { - super(`${base} ${res[0]}`); - } else { - super(`${base}\n\n${res.join('\n')}\n`); - } - } else { - let res = util.inspect(actual); - let other = util.inspect(expected); - if (res.length > 128) - res = `${res.slice(0, 125)}...`; - if (other.length > 128) - other = `${other.slice(0, 125)}...`; - super(`${res} ${operator} ${other}`); - } - } - - this.generatedMessage = !message; - this.name = 'AssertionError [ERR_ASSERTION]'; - this.code = 'ERR_ASSERTION'; - this.actual = actual; - this.expected = expected; - this.operator = operator; - Error.captureStackTrace(this, stackStartFn); - } -} - -// This is defined here instead of using the assert module to avoid a -// circular dependency. The effect is largely the same. -function internalAssert(condition, message) { - if (!condition) { - throw new AssertionError({ - message, - actual: false, - expected: true, - operator: '==' - }); - } -} - function getMessage(key, args) { const msg = messages.get(key); + if (util === undefined) util = require('util'); + if (assert === undefined) assert = require('assert'); if (typeof msg === 'function') { - internalAssert( + assert( msg.length <= args.length, // Default options do not count. `Code: ${key}; The provided arguments length (${args.length}) does not ` + `match the required ones (${msg.length}).` @@ -497,7 +221,7 @@ function getMessage(key, args) { } const expectedLength = (msg.match(/%[dfijoOs]/g) || []).length; - internalAssert( + assert( expectedLength === args.length, `Code: ${key}; The provided arguments length (${args.length}) does not ` + `match the required ones (${expectedLength}).` @@ -693,11 +417,9 @@ module.exports = { uvException, isStackOverflowError, getMessage, - AssertionError, SystemError, codes, - E, // This is exported only to facilitate testing. - errorCache: new Map() // This is in here only to facilitate testing. + E // This is exported only to facilitate testing. }; // To declare an error message, use the E(sym, val, def) function above. The sym @@ -1045,7 +767,7 @@ E('ERR_VM_MODULE_STATUS', 'Module status %s', Error); E('ERR_ZLIB_INITIALIZATION_FAILED', 'Initialization failed', Error); function invalidArgType(name, expected, actual) { - internalAssert(typeof name === 'string', 'name must be a string'); + assert(typeof name === 'string', "'name' must be a string"); // determiner: 'must be' or 'must not be' let determiner; @@ -1071,7 +793,7 @@ function invalidArgType(name, expected, actual) { } function missingArgs(...args) { - internalAssert(args.length > 0, 'At least one arg needs to be specified'); + assert(args.length > 0, 'At least one arg needs to be specified'); let msg = 'The '; const len = args.length; args = args.map((a) => `"${a}"`); @@ -1091,11 +813,11 @@ function missingArgs(...args) { } function oneOf(expected, thing) { - internalAssert(typeof thing === 'string', '`thing` has to be of type string'); + assert(typeof thing === 'string', '`thing` has to be of type string'); if (Array.isArray(expected)) { const len = expected.length; - internalAssert(len > 0, - 'At least one expected value needs to be specified'); + assert(len > 0, + 'At least one expected value needs to be specified'); expected = expected.map((i) => String(i)); if (len > 2) { return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or ` + |