Como posso relançar uma exceção em Javascript, mas preservar a pilha?

151

Em Javascript, suponha que eu queira executar alguma limpeza quando uma exceção acontecer, mas deixe a exceção continuar propagando a pilha, por exemplo:

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

O problema com esse código é que capturar e repetir a exceção faz com que as informações de rastreamento de pilha sejam perdidas até esse ponto, de modo que, se a exceção for capturada novamente novamente, mais alto na pilha, o rastreamento de pilha será reduzido apenas para o re -lançar. Isso é péssimo porque significa que não contém a função que realmente lançou a exceção.

Como se vê, try..finally tem o mesmo comportamento, pelo menos no Chrome (ou seja, não é exatamente o relançamento que é o problema, mas a presença de qualquer bloco de manipulador de exceção).

Alguém sabe como refazer uma exceção em Javascript, mas preservar o rastreamento de pilha associado a ela? Na falta disso, que tal sugestões de outras maneiras de adicionar manipuladores de limpeza com exceção de segurança, além de capturar rastreamentos de pilha completos quando uma exceção acontece?

Obrigado por qualquer ponteiro :)

Geoff
fonte

Respostas:

78

Este é um erro no Chrome. A repetição de uma exceção deve preservar o rastreamento de chamadas.

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

Não conheço nenhuma solução alternativa.

Não vejo o problema com finalmente. Eu vejo exceções silenciosamente que não aparecem no console de erros em alguns casos após um finalmente, mas essa parece estar corrigida nas compilações de desenvolvimento.

Glenn Maynard
fonte
5
Este problema foi encerrado.
Zachary Burns
24

A propriedade de pilha de um objeto Error é criada ao mesmo tempo que o próprio objeto Error, não no momento em que é lançada. Eles geralmente são os mesmos por causa do idioma

   lançar novo erro ("mensagem");

e se você usar o código exatamente como o escreveu, a propriedade da pilha não será alterada quando você repetir o erro.

Mike Stay
fonte
5
Isso não é verdade (talvez dependente da plataforma). O mecanismo js que estou usando agora (Rhino) redefine a pilha na instrução throw, perdendo a pilha original.
Ted Bigham
1
Talvez sim, mas o rhino-1.7.7.2.jar não o altera. Qual versão você está usando?
Mike Stay