Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

errors: improve invalid arg type #13834

Merged
merged 2 commits into from
Jul 3, 2017

Conversation

BridgeAR
Copy link
Member

I reworked the ERR_INVALID_ARG_TYPE error type in a way that provides more information to the user than before.
All of these errors now return what was actually provided and failed.
The information about what was provided and what is expected is more specific (as in not only the type is checked but also the constructor).
I also fixed a few typos and wrong usages like using typeof arg as actual value instead of arg and one entry that actually checks a property, not an argument.

There is one point that might be thought about: mixing multiple expected values can only print either instance of or type of. So ['Array', 'string'] will result in instance of Array or string and not instance of Array or type of string. I could test each entry but I feel that is somewhat unnecessary?

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

errors

@nodejs-github-bot nodejs-github-bot added dont-land-on-v4.x errors Issues and PRs related to JavaScript errors originated in Node.js core. lib / src Issues and PRs related to general changes in the lib or src directory. whatwg-url Issues and PRs related to the WHATWG URL implementation. labels Jun 21, 2017
@BridgeAR BridgeAR changed the title Improve invalid arg type errors: improve invalid arg type Jun 21, 2017
@BridgeAR
Copy link
Member Author

Ref #13730
Ref #13733 (one error is actually not touched here and is fixed in this PR instead).

if (actual == null) {
received = String(actual);
} else if (typeof actual === 'object') {
if (actual.constructor !== undefined) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to use single equals to also check for null.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, as far as I can tell someone would have to explicitly set the constructor to null... that would be really weird but I'll change it accordingly.

@mscdex mscdex added the semver-major PRs that contain breaking changes and should be released in the next major version. label Jun 21, 2017
@mscdex
Copy link
Contributor

mscdex commented Jun 21, 2017

Marking as semver-major due to changes in error messages.

@BridgeAR
Copy link
Member Author

@mscdex this should not be semver major as the main intention of the internal errors was to change error messages when ever.

@mscdex
Copy link
Contributor

mscdex commented Jun 21, 2017

@BridgeAR Right, that's the end goal, but I think until the new error mechanism is widely adopted (e.g. users start checking the special error properties instead of .message) we're still marking error message changes as semver-major. /cc @jasnell to be sure.

@mhdawson
Copy link
Member

Like the improvement. Agree we should still be making these changes semver-major until we get overall agreement that we can starting treating error messages changes differently.

Also needs a rebase.

@refack
Copy link
Contributor

refack commented Jun 23, 2017

Like the improvement. Agree we should still be making these changes semver-major until we get overall agreement that we can starting treating error messages changes differently.

There are mixed messages being conveyed #13730 (comment)... IMHO the CTC should discuss and decide.
ping @jasnell

@BridgeAR
Copy link
Member Author

Rebased

@refack
Copy link
Contributor

refack commented Jun 26, 2017

IMHO in the tests when you assert the message it should be a RegEx anchored with start-of-line and end in "Received": /^The "last argument" argument must be of type function\. Received/ because whatever comes after "Received" is dependent of the actual input, while the rest is static for each case.

@refack
Copy link
Contributor

refack commented Jun 26, 2017

Another idea: export a function from errors: invalidArg(opts) that you use as error.invalidArgs({expected: "gaga", bar}); then you can infer the type of the second arg's name and value:

function invalidArg(opts) {
  assert.strictEqual(Object.keys(opts).length, 2);
  assert.strictEqual('expected' in opts, true);
  const exp = opts.expected;
  delete opts.expected;
  const actKey = Object.keys(opts)[0];
  const actVal = opts[actKey];
  throw new TypeError('ERR_INVALID_ARG_TYPE', actKey, exp, actVal
// if we add a stackLimit arg
// ,invalidArg);
}

Copy link
Contributor

@refack refack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -34,13 +34,13 @@ for (let i = 0; i < 10; i++) {
const invalidUserArgument = common.expectsError({
code: 'ERR_INVALID_ARG_TYPE',
type: TypeError,
message: 'The "preValue.user" property must be of type Number'
message: /The "prevValue\.user" property must be of type number/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you anchor these /^...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

lib/util.js Outdated
throw new errors.TypeError('ERR_INVALID_ARG_TYPE',
'superCtor.prototype',
'function',
superCtor.prototype);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO for readability use undefined

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally prefer it this way to have a consistent way of doing this but I don't have strong feelings about it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Generally I yield to the OP. So it's your call.

lib/util.js Outdated
@@ -205,7 +205,8 @@ Object.defineProperty(inspect, 'defaultOptions', {
},
set: function(options) {
if (options === null || typeof options !== 'object') {
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'object');
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'options', 'object',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personal style nit: Is these cases chop down the args like in L1082

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

@BridgeAR
Copy link
Member Author

@refack

you can infer the type of the second arg's name and value

I feel like this is a bit to much magic and the call itself won't be much shorter. So I'd say let's stick to how it is currently.


I also added the Received part in the RegExp if the line length allowed it. I hope that's fine, I personally don't see much benefit in adding the Received as it might theoretically change and it is already checked that all arguments are properly passed to the internal error.

@refack
Copy link
Contributor

refack commented Jun 26, 2017

you can infer the type of the second arg's name and value

I feel like this is a bit to much magic and the call itself won't be much shorter. So I'd say let's stick to how it is currently.

👍

I also added the Received part in the RegExp if the line length allowed it. I hope that's fine, I personally don't see much benefit in adding the Received as it might theoretically change and it is already checked that all arguments are properly passed to the internal error.

Just so it doesn't change "accidentally". Changes in test files get more review attention, so IMHO it's best to assert as much as possible, then later change carefully.

@refack
Copy link
Contributor

refack commented Jun 26, 2017

@BridgeAR
Copy link
Member Author

Rebased

Copy link
Member

@mhdawson mhdawson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a question. In a number of tests the check stops at 'Received' any reason we can't validate the additional information after 'Received' as well ?

@BridgeAR
Copy link
Member Author

It is in most cases possible to use the exact value. In the end I don't think that it's that important to test for the message strictly as it can change more often but I'm fine with changing it.

This was referenced Sep 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked PRs that are blocked by other issues or PRs. errors Issues and PRs related to JavaScript errors originated in Node.js core. invalid Issues and PRs that are invalid. lib / src Issues and PRs related to general changes in the lib or src directory. semver-major PRs that contain breaking changes and should be released in the next major version. whatwg-url Issues and PRs related to the WHATWG URL implementation.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants