-1

After refactoring custom errors for ES6 in a large public library (pg-promise), I'm getting some strange reports that the custom errors may not instantiate correctly in some special cases, ones that I haven't been able to reproduce, after lots of attempts.

Could someone with experience in implementing custom errors, please tell me if the refactoring that was done is 1:1 correct, or if I've missed something.

Original ES5 Code

function CustomError(errCode) {
    var temp = Error.apply(this, arguments);
    temp.name = this.name = 'CustomError';
    this.stack = temp.stack;
    this.code = errCode;
}

CustomError.prototype = Object.create(Error.prototype, {
    constructor: {
        value: CustomError,
        writable: true,
        configurable: true
    }
});

CustomError.prototype.toString = function () {
    console.log('errCode:', this.code);
};

CustomError.prototype.inspect = function () {
    return this.toString();
};

Refactored ES6 Code:

class CustomError extends Error {
    constructor(errCode) {
        super();
        Error.captureStackTrace(this, CustomError);
        this.code = errCode;
    }
}

CustomError.prototype.toString = function () {
    console.log('errCode:', this.code);
};

CustomError.prototype.inspect = function () {
    return this.toString();
};

Both examples are required to work the same under any Node.js 4.x and later, instantiated as:

const error = new CustomError(123);
console.log(error);

According to a bug report, sometimes such a type is supposedly created without the right this context, or more accurately, the error says: can't use 'code' of undefined that's inside toString.

UPDATE

After looking at this article: Custom JavaScript Errors in ES6, and its example:

class GoodError extends Error {
    constructor(...args) {
        super(...args)
        Error.captureStackTrace(this, GoodError)
    }
}

it seems that passing in the arguments like that is what I am missing. But how can I update my CustomError class correctly to do the same, considering that:

  • Syntax ...args doesn't work in Node.js 4.x, so I cannot use it
  • I need to combine it with the existing custruction parameters, such as errCode
16
  • 1
    One thing to notice is super() should be super(arguments). Commented Jun 30, 2017 at 16:17
  • @destoryer Shouldn't it be super(...arguments)? Commented Jun 30, 2017 at 16:19
  • @PeterMader Yes, thanks. Commented Jun 30, 2017 at 16:19
  • I can't think of anything you could do that would prevent the this context from being passed correctly. Commented Jun 30, 2017 at 16:19
  • 1
    Why are you using the class syntax and prototype syntax? Why not use one? Commented Jun 30, 2017 at 16:24

1 Answer 1

1

I believe this is equivalent to your ES5 code

class CustomError extends Error {

    constructor( errCode ){
        super(...arguments);
        this.name = "CustomError";
        this.code = errCode;
    }

    toString(){
        console.log('errCode:', this.code);
    }

    inspect(){
        return this.toString();
    }

}

You can replace super(...arguments) with

super();
Error.apply(this, arguments);
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you! This will take me a few days to get feedback from the library's users to find out whether or not this helped with the problem. But for the moment it seems like the best I can try so far.
Why did you skip this line though? - Error.captureStackTrace(this, CustomError). I thought it was essential for capturing the stack trace.
It was not in the ES5 code, and I believe it's redundant. super(...arguments), or generally new Error() sets the .stack property.
Not according to this: medium.com/@xjamundx/… or is this guy wrong?
After all the feedback, and lots of experimenting I gave up, and reverted everything back to the ES5 syntax: github.com/vitaly-t/pg-promise/issues/361. I still have no idea what was wrong, and applying the code from this answer didn't help, sadly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.