2

Refer this, the Custom Errors in ES6 can be written as following:

class MyError extends Error {
  constructor(message) {
    super(message);
    this.message = message;
    this.name = 'MyError';
  }
}

There is no need for this.stack = (new Error()).stack; trick thanks to super() call.

However, I test it under Babel

class MyError extends Error {
  constructor(message) {
    super(message);
    this.message = message;
    this.name = 'MyError';
    //this.stack = (new Error()).stack;
    //Error.captureStackTrace(this, this.constructor.name);
  }
}

var myerror = new MyError("test");
console.log(myerror.stack)

There is NO stack information unless the code this.stack = (new Error()).stack; or Error.captureStackTrace(this, this.constructor.name); is invoked.

But I test the above code snippet without this.stack = (new Error()).stack; or Error.captureStackTrace(this, this.constructor.name); under Chrome console.

Output:

MyError: test
    at MyError (<anonymous>:3:28)
    at <anonymous>:12:19
    at Object.InjectedScript._evaluateOn (<anonymous>:875:140)
    at Object.InjectedScript._evaluateAndWrap (<anonymous>:808:34)
    at Object.InjectedScript.evaluate (<anonymous>:664:21)

Should I consider this is one defect on Babel or Chrome issue? Or miss understanding the super()?

Update

According to V8 codes, the stack of Error

captureStackTrace = function captureStackTrace(obj, cons_opt) {
  // Define accessors first, as this may fail and throw.
  ObjectDefineProperty(obj, 'stack', { get: StackTraceGetter,
                                       set: StackTraceSetter,
                                       configurable: true });

Base on my understanding, since the stack is one property of Error, after supper() is called, then it is not necessary to invoke captureStackTrace in MyError class. Am I missing something?

zangw
  • 43,869
  • 19
  • 177
  • 214
  • Duplicate of http://stackoverflow.com/questions/31089801/extending-error-in-javascript-with-es6-syntax ? – CodingIntrigue Nov 24 '15 at 11:57
  • 1
    Extending built in classes is not very well supported yet in browsers. Babel can't do anything about this. – Felix Kling Nov 24 '15 at 14:37
  • Are you actually chrome-only? If so, you can use native ES6 classes and tell Babel not to transpile them. Then extending error will work. – loganfsmyth Nov 24 '15 at 17:59

1 Answers1

3

As far as I know, in order to properly extend Error class in V8 you should call

Error.captureStackTrace(this, this.constructor)

in it's constructor, e.g.:

class MyError extends Error {
  constructor (message) {
    super()
    Error.captureStackTrace(this, this.constructor)
    Object.assign(this, {name: 'MyError', message})
  }
}

N.B.: Bear in mind that not all browsers support Error.captureStackTrace, so you may have to make it optional.

Alternatively, you could use es6-error npm module to deal with all this stuff automatically:

import ExtendableError from 'es6-error';

class MyError extends ExtendableError {
  // everything is taken care of
}
Leonid Beschastny
  • 50,364
  • 10
  • 118
  • 122
  • Since `super()` is invoked in `MyError` subclass, I think it is not necessary to invoke `captureStackTrace`. Please see my question update. – zangw Nov 24 '15 at 10:23
  • 1
    @zangw `Error.captureStackTrace` is a part of [V8 Stack Trace API](https://github.com/v8/v8/wiki/Stack%20Trace%20API#stack-trace-collection-for-custom-exceptions) and can't be avoided. Calling `supper()` is not enough to properly extend V8 error class. – Leonid Beschastny Nov 24 '15 at 14:00