@@ -3066,8 +3066,10 @@ describe('Raven (public API)', function() {
3066
3066
var error = new ErrorEvent ( 'pickleRick' , { error : new Error ( 'pickleRick' ) } ) ;
3067
3067
this . sinon . stub ( Raven , 'isSetup' ) . returns ( true ) ;
3068
3068
this . sinon . stub ( Raven , '_handleStackInfo' ) ;
3069
+ this . sinon . spy ( Raven , '_getCaptureExceptionOptionsFromPlainObject' ) ;
3069
3070
Raven . captureException ( error , { foo : 'bar' } ) ;
3070
3071
assert . isTrue ( Raven . _handleStackInfo . calledOnce ) ;
3072
+ assert . isFalse ( Raven . _getCaptureExceptionOptionsFromPlainObject . called ) ;
3071
3073
} ) ;
3072
3074
3073
3075
it ( 'should send ErrorEvents without Errors as messages' , function ( ) {
@@ -3079,6 +3081,44 @@ describe('Raven (public API)', function() {
3079
3081
} ) ;
3080
3082
}
3081
3083
3084
+ it ( "should treat Schrodinger's Error in the same way as regular Error" , function ( ) {
3085
+ // Schrodinger's Error is an object that is and is not an Error at the same time
3086
+ // Like... error, but not really.
3087
+ // But error.
3088
+ //
3089
+ // To be more exact, it's an object literal or an instance of constructor function
3090
+ // that has it's prototype set to the Error object itself.
3091
+ // When using `isPlanObject`, which makes a call to `Object.prototype.toString`,
3092
+ // it returns `[object Object]`, because any instance created with `new X`
3093
+ // where X is a custom constructor like `function X () {}`, it's return value
3094
+ // is an object literal.
3095
+ // However, because it has it's prototype set to an Error object,
3096
+ // when using `instanceof Error` check, it returns `true`, because calls
3097
+ // like this, are always going up the prototype chain and will verify
3098
+ // all possible constructors. For example:
3099
+ //
3100
+ // class Foo extends Bar {}
3101
+ // class Bar extends Error {}
3102
+ //
3103
+ // var foo = new Foo();
3104
+ //
3105
+ // and now `foo` is instance of every "extension" ever created in the chain
3106
+ //
3107
+ // foo instanceof Foo; // true
3108
+ // foo instanceof Bar; // true (because Foo extends Bar)
3109
+ // foo instanceof Error; // true (because Foo extends Bar that extends Error)
3110
+
3111
+ function SchrodingersError ( ) { }
3112
+ SchrodingersError . prototype = new Error ( "Schrödinger's cat was here" ) ;
3113
+ var error = new SchrodingersError ( ) ;
3114
+ this . sinon . stub ( Raven , 'isSetup' ) . returns ( true ) ;
3115
+ this . sinon . stub ( Raven , '_handleStackInfo' ) ;
3116
+ this . sinon . spy ( Raven , '_getCaptureExceptionOptionsFromPlainObject' ) ;
3117
+ Raven . captureException ( error , { foo : 'bar' } ) ;
3118
+ assert . isTrue ( Raven . _handleStackInfo . calledOnce ) ;
3119
+ assert . isFalse ( Raven . _getCaptureExceptionOptionsFromPlainObject . called ) ;
3120
+ } ) ;
3121
+
3082
3122
it ( 'should call handleStackInfo' , function ( ) {
3083
3123
var error = new Error ( 'pickleRick' ) ;
3084
3124
this . sinon . stub ( Raven , 'isSetup' ) . returns ( true ) ;
0 commit comments