From 7d6c963b9d5716fa3f502f8c97245c6cd6ec4a7c Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Fri, 14 Jun 2019 16:29:25 +0200 Subject: [PATCH] assert: DRY .throws code This refactors some code for less duplication. Backport-PR-URL: https://github.com/nodejs/node/pull/31431 PR-URL: https://github.com/nodejs/node/pull/28263 Reviewed-By: Rich Trott Reviewed-By: Benjamin Gruenbaum Reviewed-By: James M Snell --- lib/assert.js | 88 ++++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index eb74493c443902..52523db3948ca7 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -25,6 +25,7 @@ const { ObjectAssign, ObjectIs, ObjectKeys, + ObjectPrototypeIsPrototypeOf, Map, } = primordials; @@ -571,6 +572,9 @@ function compareExceptionKey(actual, expected, key, message, keys, fn) { } function expectedException(actual, expected, message, fn) { + let generatedMessage = false; + let throwError = false; + if (typeof expected !== 'function') { // Handle regular expressions. if (isRegExp(expected)) { @@ -583,20 +587,9 @@ function expectedException(actual, expected, message, fn) { message = 'The input did not match the regular expression ' + `${inspect(expected)}. Input:\n\n${inspect(str)}\n`; } - - const err = new AssertionError({ - actual, - expected, - message, - operator: fn.name, - stackStartFn: fn - }); - err.generatedMessage = generatedMessage; - throw err; - } - - // Handle primitives properly. - if (typeof actual !== 'object' || actual === null) { + throwError = true; + // Handle primitives properly. + } else if (typeof actual !== 'object' || actual === null) { const err = new AssertionError({ actual, expected, @@ -606,43 +599,52 @@ function expectedException(actual, expected, message, fn) { }); err.operator = fn.name; throw err; - } - - // Handle validation objects. - const keys = ObjectKeys(expected); - // Special handle errors to make sure the name and the message are compared - // as well. - if (expected instanceof Error) { - keys.push('name', 'message'); - } else if (keys.length === 0) { - throw new ERR_INVALID_ARG_VALUE('error', - expected, 'may not be an empty object'); - } - if (isDeepEqual === undefined) lazyLoadComparison(); - for (const key of keys) { - if (typeof actual[key] === 'string' && - isRegExp(expected[key]) && - expected[key].test(actual[key])) { - continue; + } else { + // Handle validation objects. + const keys = ObjectKeys(expected); + // Special handle errors to make sure the name and the message are + // compared as well. + if (expected instanceof Error) { + keys.push('name', 'message'); + } else if (keys.length === 0) { + throw new ERR_INVALID_ARG_VALUE('error', + expected, 'may not be an empty object'); + } + if (isDeepEqual === undefined) lazyLoadComparison(); + for (const key of keys) { + if (typeof actual[key] === 'string' && + isRegExp(expected[key]) && + expected[key].test(actual[key])) { + continue; + } + compareExceptionKey(actual, expected, key, message, keys, fn); } - compareExceptionKey(actual, expected, key, message, keys, fn); + return; } - return; - } - // Guard instanceof against arrow functions as they don't have a prototype. // Check for matching Error classes. - if (expected.prototype !== undefined && actual instanceof expected) { + } else if (expected.prototype !== undefined && actual instanceof expected) { return; - } - if (Error.isPrototypeOf(expected)) { + } else if (ObjectPrototypeIsPrototypeOf(Error, expected)) { throw actual; + } else { + // Check validation functions return value. + const res = expected.call({}, actual); + if (res !== true) { + throw actual; + } } - // Check validation functions return value. - const res = expected.call({}, actual); - if (res !== true) { - throw actual; + if (throwError) { + const err = new AssertionError({ + actual, + expected, + message, + operator: fn.name, + stackStartFn: fn + }); + err.generatedMessage = generatedMessage; + throw err; } }