Bug 167934 - Rethrowing error resets stack trace making debugging hard
Summary: Rethrowing error resets stack trace making debugging hard
Status: RESOLVED DUPLICATE of bug 174380
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: Safari 10
Hardware: All All
: P2 Normal
Assignee: Saam Barati
URL:
Keywords: InRadar
Depends on: 174380
Blocks:
  Show dependency treegraph
 
Reported: 2017-02-07 07:12 PST by Malte Ubl
Modified: 2017-09-14 22:39 PDT (History)
6 users (show)

See Also:


Attachments
Testcase (console output) (430 bytes, text/html)
2017-07-06 00:26 PDT, Frédéric Wang (:fredw)
no flags Details
Testcase (print stack trace) (588 bytes, text/html)
2017-07-06 00:27 PDT, Frédéric Wang (:fredw)
no flags Details
Testcase (to run in JSC) (408 bytes, application/javascript)
2017-07-06 00:27 PDT, Frédéric Wang (:fredw)
no flags Details
Testcase (console output, only the rethrown error) (312 bytes, text/html)
2017-07-06 00:42 PDT, Frédéric Wang (:fredw)
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Malte Ubl 2017-02-07 07:12:16 PST
In JavaScript it is common to rethrow errors when they cannot immediately be handled. Here is some example code:

try {
  mayThrow();
} catch (e) {
  if (e.message == 'something I can handle') {
    handleError(e);
  } else {
    throw e;
  }
}

When executed in JavaScriptCore the error object created in the try block gets a new stack trace when it is rethrown. While there are situations when that might be desirable in the vast majority of cases it is not. Especially in this common pattern:

try {
  mayThrow();
} catch (e) {
  // Don't interrupt execution flow, but do report error.
  setTimeout(function() {
    throw e;
  });
}

Java solves this my making stack traces a linked list of places an exception haa been thrown. Since this is not available in JS, one must choose, and choosing the original location is better in the vast majority of cases.

Here is a full repro case:
http://output.jsbin.com/lufeqe/quiet

Compare the console output between V8 and JavaScriptCore. In V8 it is immediately obvious what happened, while JSC provides no useful information for 2 of the 3 errors.
Comment 1 Radar WebKit Bug Importer 2017-02-08 17:21:52 PST
<rdar://problem/30433531>
Comment 2 Frédéric Wang (:fredw) 2017-07-05 08:11:57 PDT
Testing in Firefox, it seems that SpiderMonkey behaves the same as V8.
Comment 3 Frédéric Wang (:fredw) 2017-07-06 00:26:18 PDT
Created attachment 314702 [details]
Testcase (console output)
Comment 4 Frédéric Wang (:fredw) 2017-07-06 00:27:19 PDT
Created attachment 314703 [details]
Testcase (print stack trace)
Comment 5 Frédéric Wang (:fredw) 2017-07-06 00:27:47 PDT
Created attachment 314704 [details]
Testcase (to run in JSC)
Comment 6 Frédéric Wang (:fredw) 2017-07-06 00:38:07 PDT
The stack trace of attachment 314704 [details] seems correct using JSC (TOT):

WebKitBuild/Release/bin/jsc -e "`curl https://bug-167934-attachments.webkit.org/attachment.cgi?id=314704`"
Stack of an exception:
throwError@[Command Line]:2:18
caller@[Command Line]:6:13
invokee@[Command Line]:10:9
root@[Command Line]:14:10
global code@[Command Line]:19:7

Stack of a rethrown exception:
throwError@[Command Line]:2:18
caller@[Command Line]:6:13
invokee@[Command Line]:10:9
root@[Command Line]:14:10
global code@[Command Line]:28:9

Similarly, opening attachment 314703 [details] in MiniBrowser (TOT) the exception stack trace are correctly printed in the textarea.

Attachment 314702 [details] is similar to the original test case (i.e. using separate script tags and checking the console) and indeed shows that the stack incorrect for the rethrown exception. Again, using TOT.
Comment 7 Frédéric Wang (:fredw) 2017-07-06 00:42:11 PDT
Created attachment 314706 [details]
Testcase (console output, only the rethrown error)

This is a simplified version of attachment 314702 [details] with only the rethrown exception and using only one <script> tag. It still exhibits the issue in MiniBrowser.
Comment 8 Caitlin Potter (:caitp) 2017-07-10 19:39:09 PDT
Quick design for a fix:

1. In `JSC::Exception::create(VM&, JSValue);`:
If thrownValue inherits ErrorInstance, and does not have a captured stacktrace already, store the captured stacktrace on it (private symbol, or member of ErrorInstance).

2. In createScriptCallStackFromException() (ScriptCallStackFactory.cpp):
If exception->value() is an instance of ErrorInstance, load the stacktrace symbol,
and use it to assemble the ScriptCallStack

Console API adds the message like usual, and it should include the originally thrown stacktrace (provided the thrown object inherits(ErrorInstance::class())).

---

This seems to more or less match the behaviour of Chromium, so although there are caveats, I don't know that anyone has found that behaviour problematic in Chromium yet.
Comment 9 Caitlin Potter (:caitp) 2017-07-11 13:10:24 PDT
Prototype patch in bug 174380
Comment 10 Frédéric Wang (:fredw) 2017-07-11 23:41:10 PDT
(In reply to Frédéric Wang (:fredw) from comment #6)
> The stack trace of attachment 314704 [details] seems correct using JSC (TOT):
> ...
> Similarly, opening attachment 314703 [details] in MiniBrowser (TOT) the
> exception stack trace are correctly printed in the textarea.

Just to follow-up here. These test cases print Error.stack which is indeed the one requested in this bug report. Hence they can not exhibit the issue, contrary to the test cases requiring the use of the Web Inspector.

It turns out that the Web Inspector prints the Exception object's stack (and does it on purpose), which indicates the location of when that exception was last (re)thrown and hence does not correspond to the behavior Chromium or Firefox's console.

For details and ideas see the discussion on bug 174380.
Comment 11 Frédéric Wang (:fredw) 2017-07-11 23:42:06 PDT
Comment on attachment 314703 [details]
Testcase (print stack trace)

This testcase won't allow to reproduce the issue per comment 10.
Comment 12 Frédéric Wang (:fredw) 2017-07-11 23:42:18 PDT
Comment on attachment 314704 [details]
Testcase (to run in JSC)

This testcase won't allow to reproduce the issue per comment 10.
Comment 13 Saam Barati 2017-09-14 21:54:03 PDT
Looking into this now
Comment 14 Saam Barati 2017-09-14 22:38:23 PDT
It seems like all action is in https://bugs.webkit.org/show_bug.cgi?id=174380

Do we need two bugs for the same thing?
Comment 15 Saam Barati 2017-09-14 22:39:48 PDT

*** This bug has been marked as a duplicate of bug 174380 ***