Jak mogę ponownie zgłosić wyjątek w JavaScript, ale zachować stos?

151

W Javascript załóżmy, że chcę wykonać pewne porządki, gdy wystąpi wyjątek, ale pozwól, aby wyjątek nadal propagował stos, np:

try {
  enterAwesomeMode();
  doRiskyStuff(); // might throw an exception
} catch (e) {
  leaveAwesomeMode();
  throw e;
}
doMoreStuff();
leaveAwesomeMode();

Problem z tym kodem polega na tym, że przechwycenie i ponowne zgłoszenie wyjątku powoduje utratę informacji o śladzie stosu do tego punktu, tak że jeśli wyjątek zostanie następnie przechwycony ponownie, wyżej na stosie, ślad stosu przechodzi tylko do re -rzucać. To jest do bani, ponieważ oznacza, że ​​nie zawiera funkcji, która faktycznie spowodowała odrzucenie wyjątku.

Jak się okazuje, try..w końcu zachowuje się tak samo, przynajmniej w Chrome (to znaczy, że to nie ponowne rzucenie jest problemem, ale obecność jakiegokolwiek bloku obsługi wyjątków).

Czy ktoś zna sposób na ponowne zgłoszenie wyjątku w Javascript, ale zachować skojarzony z nim ślad stosu? W przeciwnym razie co powiesz na sugestie dotyczące innych sposobów dodawania bezpiecznych dla wyjątków programów obsługi czyszczenia, a także przechwytywania pełnych śladów stosu, gdy wystąpi wyjątek?

Dzięki za wszelkie wskazówki :)

Geoff
źródło

Odpowiedzi:

78

To jest błąd w Chrome. Ponowne zgłoszenie wyjątku powinno zachować ślad wywołania.

http://code.google.com/p/chromium/issues/detail?id=60240

Nie znam żadnego obejścia.

Ostatecznie nie widzę problemu. Widzę wyjątki, które po cichu nie pojawiają się na konsoli błędów w niektórych przypadkach po zakończeniu, ale ten wydaje się być naprawiony w kompilacjach deweloperskich.

Glenn Maynard
źródło
5
Ta sprawa została już zamknięta.
Zachary Burns
24

Właściwość stack obiektu Error jest tworzona w tym samym czasie co sam obiekt Error, a nie w miejscu, w którym został zgłoszony. Często są takie same z powodu idiomu

   wrzuć nowy błąd („wiadomość”);

a jeśli użyjesz kodu tak, jak go napisałeś, właściwość stosu nie zostanie zmieniona po ponownym wyrzuceniu błędu.

Mike Zostań
źródło
5
To nieprawda (może zależne od platformy). Silnik js, którego teraz używam (Rhino) resetuje stos w instrukcji throw, tracąc oryginalny stos.
Ted Bigham
1
Być może tak, ale rhino-1.7.7.2.jar tego nie zmienia. Jakiej wersji używasz?
Mike Stay