Scala.js stacktraces
Asked Answered
F

1

6

I'm frustrated by unintelligible stacktraces when my Scala.js code throws an exception. I thought I had a solution using a Javascript library (see Getting a scala stacktrace) but it breaks too often.

How do you extract meaning (where the program broke; how it got there -- in terms of the Scala code) from a stacktrace like the following. Or am I doing something wrong to even get an untranslated stacktrace?

Sample Scala.js stacktrace

Forme answered 7/9, 2017 at 18:34 Comment(0)
N
6

Take a look at this code I wrote a while back in my youi framework: https://github.com/outr/youi/tree/e66dc36a12780fa8941152d07de9c3a52d28fc10/app/js/src/main/scala/io/youi/app/sourceMap

It is used to reverse JS stack traces to Scala stack traces. In youi I send the errors to the server so I can monitor browser errors that occur with the complete traceback.

Brief Overview

  1. source-map.js

You need source-map.js to parse the js.map file that Scala.js generated when it compiled your code. See: https://github.com/mozilla/source-map

  1. Load the js.map file via Ajax

The SourceMapConsumer needs a js.Object (JSON) of the js.map file. See https://github.com/outr/youi/blob/e66dc36a12780fa8941152d07de9c3a52d28fc10/app/js/src/main/scala/io/youi/app/sourceMap/ErrorTrace.scala#L58 for an example of loading via youi's Ajax features.

  1. Process the Throwable

The trace represents line and columns in the JS file and you can pass that information to SourceMapConsumer to get the original Scala line numbers back (see SourceMapConsumer.originalPositionFor). See ErrorTrace.toCause (https://github.com/outr/youi/blob/e66dc36a12780fa8941152d07de9c3a52d28fc10/app/js/src/main/scala/io/youi/app/sourceMap/ErrorTrace.scala#L98) for an example iterating over the Throwable's trace elements.

  1. Handling Errors

Now that you have the capacity to process JavaScript errors and convert them back to Scala traces, you need to actually receive the errors. If you want to globally handle uncaught errors set a function to window.onerror to capture errors. As of this writing, the function signature in Scala.js isn't ideal for handling all information, so in youi I use js.Dynamic to set it to what I need (see: https://github.com/outr/youi/blob/e66dc36a12780fa8941152d07de9c3a52d28fc10/app/js/src/main/scala/io/youi/app/ClientApplication.scala#L35). Also, notice that in ErrorTrace it supports multiple incoming types of errors (ErrorEvent, Throwable, and a more generic scenario). This is because in JavaScript the errors come in different ways based on what's happening. This is a fairly complex topic, and why I created this functionality in youi to simplify things.

Not nearly as brief an overview as I would have liked, but this isn't a simple problem to solve. The source-map GitHub project (https://github.com/mozilla/source-map) has decent documentation and is what I used originally to write my solution (with some added trial and error). If the information I've provided is incomplete I'd recommend reading more there as it should provide the majority of information, and probably better explained.

Nut answered 11/9, 2017 at 15:38 Comment(2)
Thanks. At a high level, the code makes sense to me. I'll enjoy digging into it as soon as I finish my current task. For those that follow me, finding the installation of the error handler in ClientApplication at line 35 was helpful.Forme
Could you consolidate this answer with more stable links, please? Pointers to master are likely to break in the future. Ideally the most important snippets should even be reproduced here to follow SO's recommendations, unless they are really too long.Wallack

© 2022 - 2024 — McMap. All rights reserved.