Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Proper way to subclass Error

456 views
Skip to first unread message

Jeff Watkins

unread,
Jan 1, 2008, 9:38:57 PM1/1/08
to SpiderMonkey Dev List
I'm implementing a JS unit testing library for my project, and I'd
like to be able to capture uncaught exceptions and display the correct
stack trace. However, for my custom exceptions, the stack trace is
showing the point at which I create the prototype Error rather than
the instance.

1 coherent.defineError= function( errorName )
2 {
3 constructor= function( message )
4 {
5 this.message= message;
6 }
7
8 constructor.prototype= new Error;
9 constructor.prototype.constructor= constructor;
10 constructor.prototype.name= errorName;
11 return constructor;
12 }
13
14 var InvalidArgumentError=
coherent.defineError( "InvalidArgumentError" );

When I create a new InvalidArgumentError instance, the stack indicates
that the error was created on line 8 rather than where ever it was in
the actual code.

What's the proper way to do this?


--
Jeff Watkins
http://metrocat.org

Computers, they're just a fad.


Ash Berlin

unread,
Jan 3, 2008, 7:26:34 AM1/3/08
to SpiderMonkey Dev List

There's 2 ways of doing this:

constructor= function( message ) {
this.stack = (new Error).stack
}

Or if you dont mind it not being portable with other JS implementations

constructor.prototype = Error.__proto__

I *think* something like that should work.

Ash

Ash Berlin

unread,
Jan 3, 2008, 5:11:38 PM1/3/08
to Jeff Watkins, SpiderMonkey Dev List


On Jan 3, 2008, at 6:27 PM, Jeff Watkins wrote:

> Unfortunately, the first way leads to the stack listing the
> constructor as the place where the error was thrown. And the second
> way just simply didn't seem to work – the custom error didn't seem
> to work correctly.
>
> It's not the end of the world, because I really need these tests to
> run in the browser and the stack doesn't work there unless you're
> running FF.


>
> On 3 Jan, 2008, at 4:26 AM, Ash Berlin wrote:
>
>> There's 2 ways of doing this:
>>
>> constructor= function( message ) {
>> this.stack = (new Error).stack
>> }
>>
>> Or if you dont mind it not being portable with other JS
>> implementations
>>
>> constructor.prototype = Error.__proto__
>>
>> I *think* something like that should work.

Okay then...

metis:~ ash$ cat test.js
var coherent = {};

coherent.defineError = function(errorName)
{
constructor = function() {
stack = (new Error).stack.split("\n").slice(1);
[undef, undef, this.fileName, this.lineNumber] =
/^(.*?)@(.*?):(.*?)$/.exec( stack[1] );
this.stack = stack.join("\n");

};
constructor.prototype = {
__proto__: Error.prototype,
name: errorName,
};
return constructor;
}

var InvalidArgumentError =
coherent.defineError( "InvalidArgumentError" );
var err = (new InvalidArgumentError('abc'));
var err2 = new Error("an error");

print(err.lineNumber);
print(err2.lineNumber);

metis:~ ash$ ./code/js/mozilla/dist/bin/js -f test.js
20
21

That might do what you want....

Jeff Watkins

unread,
Jan 5, 2008, 10:06:50 PM1/5/08
to Ash Berlin, SpiderMonkey Dev List
Wow. Just, wow.
0 new messages