From a2a2f06ce0ea4119692906b5d307c76ba25a1860 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Thu, 25 Jan 2018 04:39:02 +0800 Subject: [PATCH] errors: improve the description of ERR_INVALID_ARG_VALUE - Allow user to customize why the argument is invalid - Display the argument with util.inspect so null bytes can be displayed properly. PR-URL: https://github.com/nodejs/node/pull/18358 Reviewed-By: James M Snell Reviewed-By: Jon Moss --- lib/internal/errors.js | 22 +++++++++++++++++----- test/parallel/test-internal-errors.js | 14 ++++++++++++-- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 2643d555cd5b75..0927cee81d2d5a 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -17,7 +17,13 @@ const { kMaxLength } = process.binding('buffer'); const { defineProperty } = Object; // Lazily loaded -var util = null; +var util_ = null; +function lazyUtil() { + if (!util_) { + util_ = require('util'); + } + return util_; +} function makeNodeError(Base) { return class NodeError extends Base { @@ -68,11 +74,11 @@ class AssertionError extends Error { if (message) { super(message); } else { + const util = lazyUtil(); if (actual && actual.stack && actual instanceof Error) actual = `${actual.name}: ${actual.message}`; if (expected && expected.stack && expected instanceof Error) expected = `${expected.name}: ${expected.message}`; - if (util === null) util = require('util'); super(`${util.inspect(actual).slice(0, 128)} ` + `${operator} ${util.inspect(expected).slice(0, 128)}`); } @@ -107,7 +113,7 @@ function message(key, args) { if (typeof msg === 'function') { fmt = msg; } else { - if (util === null) util = require('util'); + const util = lazyUtil(); fmt = util.format; if (args === undefined || args.length === 0) return msg; @@ -263,8 +269,14 @@ 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); -E('ERR_INVALID_ARG_VALUE', (name, value) => - `The value "${String(value)}" is invalid for argument "${name}"`); +E('ERR_INVALID_ARG_VALUE', (name, value, reason = 'is invalid') => { + const util = lazyUtil(); + let inspected = util.inspect(value); + if (inspected.length > 128) { + inspected = inspected.slice(0, 128) + '...'; + } + return `The argument '${name}' ${reason}. Received ${inspected}`; +}), E('ERR_INVALID_ARRAY_LENGTH', (name, len, actual) => { internalAssert(typeof actual === 'number', 'actual must be a number'); diff --git a/test/parallel/test-internal-errors.js b/test/parallel/test-internal-errors.js index 78582a53504748..ae5e2672285688 100644 --- a/test/parallel/test-internal-errors.js +++ b/test/parallel/test-internal-errors.js @@ -334,10 +334,20 @@ assert.strictEqual( } { - const error = new errors.Error('ERR_INVALID_ARG_VALUE', 'foo', 'bar'); + const error = new errors.Error('ERR_INVALID_ARG_VALUE', 'foo', '\u0000bar'); assert.strictEqual( error.message, - 'The value "bar" is invalid for argument "foo"' + 'The argument \'foo\' is invalid. Received \'\\u0000bar\'' + ); +} + +{ + const error = new errors.Error( + 'ERR_INVALID_ARG_VALUE', + 'foo', { a: 1 }, 'must have property \'b\''); + assert.strictEqual( + error.message, + 'The argument \'foo\' must have property \'b\'. Received { a: 1 }' ); }