Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Better stack trace parsing in the browser #658

Open
wants to merge 1 commit into
base: master
from

Conversation

@flimzy
Copy link
Member

@flimzy flimzy commented Jul 8, 2017

The current implementation of runtime.Caller() breaks in the browser, where the stack traces contain extra : characters in the URL. This PR corrects that deficiency, while also correcting for more complex stack traces such as this one, with two sets of parenthesis, as produced in the playground:

Error 
    at Caller (eval at $b (https://gopherjs.github.io/playground/playground.js:66:11713), <anonymous>:2297:67) 
    at foo (eval at $b (https://gopherjs.github.io/playground/playground.js:66:11713), <anonymous>:2281:10) 
    at main (eval at $b (https://gopherjs.github.io/playground/playground.js:66:11713), <anonymous>:2269:8) 
    at $init (eval at $b (https://gopherjs.github.io/playground/playground.js:66:11713), <anonymous>:2333:9) 
    at $goroutine (eval at $b (https://gopherjs.github.io/playground/playground.js:66:11713), <anonymous>:1472:19) 
    at $runScheduled (eval at $b (https://gopherjs.github.io/playground/playground.js:66:11713), <anonymous>:1512:7) 
    at $schedule (eval at $b (https://gopherjs.github.io/playground/playground.js:66:11713), <anonymous>:1528:5) 
    at $go (eval at $b (https://gopherjs.github.io/playground/playground.js:66:11713), <anonymous>:1504:3) 
    at eval (eval at $b (https://gopherjs.github.io/playground/playground.js:66:11713), <anonymous>:2344:1) 
    at eval (eval at $b (https://gopherjs.github.io/playground/playground.js:66:11713), <anonymous>:2347:4) 
    at eval (<anonymous>) 
    at $b (https://gopherjs.github.io/playground/playground.js:66:11713) 
    at k.v.$externalizeWrapper [as run] (https://gopherjs.github.io/playground/playground.js:4:37282) 
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js:175:190 
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js:192:165 
    at k.$eval (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js:112:32) 
    at k.$apply (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js:112:310) 
    at HTMLInputElement.<anonymous> (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js:192:147) 
    at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js:31:225 
    at Array.forEach (native) 
    at q (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js:7:280) 
    at HTMLInputElement.c (https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular.min.js:31:207) 

The output of the original and new implementations can be seen on the playground here:

https://gopherjs.github.io/playground/#/Mq8kuInSui

Old: eval at $b (https/0 
New: https://gopherjs.github.io/playground/playground.js/66 

Admittedly, knowing the filename and line number of the compiled JS isn't the most useful information, but it is still far more useful than the URL scheme and 0, when debugging :)

Copy link
Member

@neelance neelance left a comment

LGTM

@shurcooL ptal

@dmitshur
Copy link
Member

@dmitshur dmitshur commented Jul 9, 2017

Awesome, thanks @flimzy! This is really helpful.

A test would be quite nice, so this doesn't regress, and so that it's easier to fix this again if it doesn't work on some inputs. Would it be easy for you to add one?

As far as the implementation goes, LGTM if it works (which I understand it does). But it's not easy to debug without seeing sample input that it runs on.

@dmitshur
Copy link
Member

@dmitshur dmitshur commented Jul 9, 2017

Also, will it work if the URL has a colon like http://localhost:8080?

@flimzy
Copy link
Member Author

@flimzy flimzy commented Jul 10, 2017

Would it be easy for you to add one?

Sure, I'll try to add that (it may be the weekend before I have the time).

Also, will it work if the URL has a colon like http://localhost:8080?

Yes.

@flimzy
Copy link
Member Author

@flimzy flimzy commented Jul 21, 2017

What's the best way to test this functionality? I started by adding a test in the runtime package, but discovered we aren't running tests against that, presumably because the runtime package has a very bare implementation, and most tests fail.

Should I overwrite those failing tests with no-op tests, so that other package tests will run? Or is there some other mechanism I can utilize for this?

@dmitshur
Copy link
Member

@dmitshur dmitshur commented Jul 21, 2017

What's the best way to test this functionality?

Whatever is easiest. You don't need to place the test in runtime, especially if getting other runtime tests to skip/pass is a lot of overhead.

You can place a small test in github.com/gopherjs/gopherjs/tests package. Just, something that fails because this fix, and succeeds after.

If it's too hard to add a test, then it's likely easier to skip adding one and fix this if it regresses. I don't want to make you go out of the way and spend a disproportionately large amount of time figuring out how this can be tested.

@flimzy
Copy link
Member Author

@flimzy flimzy commented Sep 2, 2017

I'm finally looking at this again.

I would love to be able to create a simple stack-parsing method, which could be tested by passing in a string, the result of js.Global.Get("Error").New().Get("stack"). This would make it quite easy to test the stack traces from arbitrary runtime engines (V8, Firefox, IE, etc) regardless of the runtime actually executing the tests.

The trouble is: Where to put this function and its associated tests?

I tried putting them in compiler/natives/src/runtime, but running tests there is nearly, if not outright, impossible, in GopherJS.

My next try was to put them in compiler/natives/src/runtime/internal/sys/arch_js.go, but the compiler explicitly ignores runtime/internal, and changing that is probably even more difficult than running tests in runtime.

My next attempt was to create compiler/natives/src/runtime/jsinternal, which would house a ParseStack function, to be called by the runtime package. I expect I'd have to override that the runtime package is allowed to import this additional package, but that seems minor. However with this go test -v -race ./... has countless failures:

# go run run.go -- fixedbugs/issue9604.go
exit status 1
cannot find package "runtime/jsinternal" in any of:
        /usr/local/go/src/vendor/runtime/jsinternal (vendor tree)
        /usr/local/go/src/runtime/jsinternal (from $GOROOT)
        /home/jonhall/go/src/runtime/jsinternal (from $GOPATH)

FAIL    fixedbugs/issue9604.go  0.019s

I'm not sure where this leaves me.

One option would be to not write this function, or the tests, in Go at all. I could write it all in pure JS. But that doesn't seem like a very Go-friendly solution, either.

Any other suggestions? Or should we forgo tests on this change?

@flimzy flimzy force-pushed the flimzy:stack branch from b63651f to 004991c Sep 2, 2017
@dmitshur
Copy link
Member

@dmitshur dmitshur commented Sep 2, 2017

I would love to be able to create a simple stack-parsing method, which could be tested by passing in a string, the result of js.Global.Get("Error").New().Get("stack"). This would make it quite easy to test the stack traces from arbitrary runtime engines (V8, Firefox, IE, etc) regardless of the runtime actually executing the tests.

Indeed, that's what I was hoping for.

I tried putting them in compiler/natives/src/runtime, but running tests there is nearly, if not outright, impossible, in GopherJS.

Can you elaborate on this? This sounds like the best solution, so what's stopping it from working?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

3 participants
You can’t perform that action at this time.