2016-08-27 8 views
0

Errorを継承するカスタム例外を作成しようとしていますが、webpackがそれを気に入らないようです。このコードは、ノードREPLとchromeのコンソール[1]で直接動作しますが、webpack(バージョン:[email protected]β17)によってコンパイルされたノードまたはブラウザでは正常に動作しません。`Error` w/webpackを拡張するときに` toString`をオーバーライドできません

コンパイルされていないコード:

export default class Exception extends Error { 
    constructor(message, inner) { 
    super(message); 

    this.name = 'Exception'; 
    this.message = message; 
    this.inner = inner; 
    if (typeof super.constructor.captureStackTrace === 'function') { 
     super.constructor.captureStackTrace(this, this.constructor); 
    } else { 
     const stack = (new super.constructor(message)).stack; 
     this.stack = stack.split('\n').slice(1).map(l => l.trim()).join('\n'); 
    } 
    } 

    toString() { 
    let string = this.stack; 

    if (this.inner) { 
     const innerLines = this.inner.toString().split('\n'); 
     const inner = innerLines.map(line => { 
     return line.replace(/^(\s+)/g, function($0, $1) { 
      return ` ${$1}`; 
     }); 
     }).join('\n'); 
     // eslint-disable-next-line prefer-template 
     string = (string + '\n' + 
     ' Inner ' + inner); 
    } 

    return string; 
    } 
} 

関連試験:

describe('Exception',() => { 

    describe('toString',() => { 
    it('should return the `name`: `message` + `stack` (recursively if there are inner exceptions)',() => { 
     const innerMessage = 'foo bar!'; 
     const outerMessage = 'bar foo!'; 
     const inner = new Exception(innerMessage); 
     const outer = new Exception(outerMessage, inner); 

     expect(inner.toString()) 
     .to.match(new RegExp(`Exception: ${innerMessage}`)); 
     expect(outer.toString()) 
     .to.match(new RegExp(`Exception: ${outerMessage}`)) 
     .and.to.match(new RegExp(`Inner Exception: ${innerMessage}`)); 
    }); 
    }); 
}); 

失敗:

コンパイル
1) Exception toString should return the `name`: `message` + `stack` (recursively if there are inner exceptions): 
    AssertionError: expected 'Exception: bar foo!' to match /Inner Exception: foo bar!/ 
     at Context.<anonymous> (.test/test/unit/shared/lib/exceptions/exception.compiledtest:178:90) 

https://gist.github.com/dwick/4d29c679f5a1c8260f22d619c3167524

すべてが期待私として働きますf私はErrorから継承しませんが、実際にはe instanceof Errorが好きです。

それは、コンストラクタ自体対ExceptiontoStringインスタンスをログインするときに何が起こっているかはかなり明らかだ:

> console.log('instance:', outer.toString.toString()); 
instance: function toString() { [native code] } 
> console.log('prototype:', Exception.prototype.toString.toString()); 
prototype: function toString() { 
     var string = this.stack; 

     if (this.inner) { 
     var innerLines = this.inner.toString().split('\n'); 
     var inner = innerLines.map(function (line) { 
      return line.replace(/^(\s+)/g, function ($0, $1) { 
      return ' ' + $1; 
      }); 
     }).join('\n'); 
     // eslint-disable-next-line prefer-template 
     string = string + '\n' + ' Inner ' + inner; 
     } 

     return string; 
    } 

なぜ、どのようにこの問題を解決するにとしてだけ混乱し。 FWIW私はまた、同じ結果を試してみました:

class Exception extends Error { ... } 
Exception.prototype.toString = ... 
+0

実際にはバベルの不具合が考えられる:https://babeljs.io/docs/usage/caveats/#classes。 https://github.com/loganfsmyth/babel-plugin-transform-b​​uiltin-extend –

+0

古典的なプロトタイプ継承で再実装することができます:https://github.com/addyosmani/es6-equivalents -in-es5#classes –

答えて

0

問題はバベルであることが判明しました。 https://babeljs.io/docs/usage/caveats/#classesから:そのような日付、Arrayなど

ビルトインクラス、DOMなどが適切に起因する(es2015-クラスのプラグイン用)ES5での制限のためにサブクラス化することはできません。 Object.setPrototypeOfとReflect.constructに基づいてbabel-plugin-transform-b​​uiltin-extendを使用することもできますが、いくつかの制限もあります。

+0

これによりエラーがスローされないように修正されますが、 'instanceof'は期待どおりに動作しません。 –

関連する問題