Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Generate stack trace on the Error constructor #153

Closed
gbrail opened this issue Feb 26, 2015 · 11 comments
Closed

Generate stack trace on the Error constructor #153

gbrail opened this issue Feb 26, 2015 · 11 comments

Comments

@gbrail
Copy link
Collaborator

gbrail commented Feb 26, 2015

Today in Rhino, the "stack" property of an Error is generated when the Error is thrown, and derived from the Java stack trace.

In V8, however, the "stack" property is populated when the Error is constructed.

In other words, the code below:

var e = new Error();
throw e;

In V8, the line number on the stack trace will be the line where "new Error" was called. In Rhino, it is where "throw" was called.

Similarly, after the first line above, the "stack" property in V8 will show the stack trace, whereas in Rhino it will be undefined.

However, making this change will potentially slow down exception-handling code because the stack trace will be gathered on every error, and then Java will gather the stack trace again when it is thrown.

So, I propose adding a new feature flag to Context that is off by default. When the feature is enabled, Rhino will capture the stack trace when the Error object is first constructed.

@gbrail
Copy link
Collaborator Author

gbrail commented Feb 27, 2015

Thinking of making this change for V8 compatibility -- any comments would be appreciated.

@hrj
Copy link

hrj commented Jul 21, 2015

The stack property is not defined even after throwing the error.

$ java -jar js.jar
Rhino 1.7.7 2015 06 17
js> try {throw new Error() } catch (e) {print(e.stack)}
undefined

Apart from that, it seems like IE11 also behaves similar to your description. I found this code in web-platform tests:

        var stack = new Error().stack;
        // IE11 does not initialize 'Error.stack' until the object is thrown.
        if (!stack) {
            try {
                throw new Error();
            } catch (e) {
                stack = e.stack;
            }
        }

@gbrail
Copy link
Collaborator Author

gbrail commented Jul 21, 2015

Ah -- Rhino does not generate stack traces at all unless "debug" is
enabled. This is historical -- I have no idea why it is not the default but
perhaps 10 years ago it was a big performance drain (seriously)...

$ java -jar buildGradle/libs/rhino-1.7.8-SNAPSHOT.jar -debug
Rhino 1.7.8-SNAPSHOT 2015 07 02
js> try {throw new Error() } catch (e) {print(e.stack)}
at :2

On Tue, Jul 21, 2015 at 12:46 AM, hrj notifications@github.com wrote:

The stack property is not defined even after throwing the error.

$ java -jar js.jar
Rhino 1.7.7 2015 06 17
js> try {throw new Error() } catch (e) {print(e.stack)}
undefined


Apart from that, it seems like IE11 also behaves similar to your
description. I found this code in web-platform tests:

    var stack = new Error().stack;
    // IE11 does not initialize 'Error.stack' until the object is thrown.
    if (!stack) {
        try {
            throw new Error();
        } catch (e) {
            stack = e.stack;
        }
    }


Reply to this email directly or view it on GitHub
#153 (comment).

Greg Brail | apigee https://apigee.com/ | twitter @gbrail
http://twitter.com/gbrail @apigee https://twitter.com/apigee
http://iloveapis.com/

@hrj
Copy link

hrj commented Jul 22, 2015

Oh, thanks for the clarification @gbrail

What else does "debug" entail? Is it only about stack traces or are there other implications, especially when running untrusted code (such as in gngr)? I am being a bit lazy, but mostly, I want to ensure that I don't miss something important.

@jochenberger
Copy link

I stumbled upon this issue when I tried to run a node script that tries to parse new Error().stack. This seems to be a common practice in Node.js.

@jochenberger
Copy link

debug does not seem to affect this:

$ java -jar buildGradle/libs/rhino-1.7.8-SNAPSHOT.jar 
Rhino 1.7.8-SNAPSHOT 2015 11 05
js> new Error().stack
js> 
$ java -jar buildGradle/libs/rhino-1.7.8-SNAPSHOT.jar -debug
Rhino 1.7.8-SNAPSHOT 2015 11 05
js> new Error().stack
js>

@gbrail
Copy link
Collaborator Author

gbrail commented Nov 5, 2015

Yes -- this would help with Node compatibility. However it'd have to be
optional since it's likely to break other stuff.

On Thu, Nov 5, 2015 at 5:06 AM, jochenberger notifications@github.com
wrote:

debug does not seem to affect this:

$ java -jar buildGradle/libs/rhino-1.7.8-SNAPSHOT.jar
Rhino 1.7.8-SNAPSHOT 2015 11 05
js> new Error().stack
js>
$ java -jar buildGradle/libs/rhino-1.7.8-SNAPSHOT.jar -debug
Rhino 1.7.8-SNAPSHOT 2015 11 05
js> new Error().stack
js>


Reply to this email directly or view it on GitHub
#153 (comment).

Greg Brail | apigee https://apigee.com/ | twitter @gbrail
http://twitter.com/gbrail @apigee https://twitter.com/apigee

@kpetroski
Copy link

Hate to bring this back from the dead, but is there any word or updates available on this exact issue?

@ghost
Copy link

ghost commented Jun 29, 2018

@ascendancy05

You can work around this by using a descendant class instead of the original Error class:

var UserError = function (messsage){
    this.message = message;
    if (Error.captureStackTrace)
        Error.captureStackTrace(this, UserError);
    else
        try {
            throw new Error();
        } catch(e){
            this.stack = e.stack || e.stacktrace;
        }
};
UserError.prototype = Object.create(Error.prototype);
UserError.prototype.constructor = UserError;
UserError.prototype.name = "UserError";
function main(){
    throw new UserError("blabla");
}

I guess it will add an extra frame to the stack string in your environment. I am working on a framework currently, which will return the same stack in every js environment, but it is a very hard problem if you want to solve it properly.

@d-oderbolz
Copy link

According to the release documentation, the V8 Implementation was added in version 1.7.6 (April 2015):
https://github.com/mozilla/rhino/releases/tag/Rhino1_7_6_RELEASE

@sebasmoyano
Copy link

Any workaround for this?

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants