¿Cómo puedo volver a lanzar una excepción en Javascript, pero preservar la pila?

151

En Javascript, suponga que quiero realizar una limpieza cuando ocurre una excepción, pero deje que la excepción continúe propagándose en la pila, por ejemplo:

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

El problema con este código es que capturar y volver a lanzar la excepción hace que se pierda la información de rastreo de la pila hasta ese punto, de modo que si la excepción se captura nuevamente, más arriba en la pila, la traza de la pila solo baja a la re -lanzar. Esto apesta porque significa que no contiene la función que realmente arrojó la excepción.

Como resultado, intentar ... finalmente tiene el mismo comportamiento, al menos en Chrome (es decir, no es el relanzamiento el problema precisamente, sino la presencia de cualquier bloqueo de controlador de excepción).

¿Alguien sabe de una manera de volver a lanzar una excepción en Javascript pero preservar el seguimiento de la pila asociada a él? De lo contrario, ¿qué tal sugerencias para otras formas de agregar controladores de limpieza seguros para excepciones, mientras que también captura rastros completos de la pila cuando ocurre una excepción?

Gracias por cualquier puntero :)

Geoff
fuente

Respuestas:

78

Este es un error en Chrome. Volver a lanzar una excepción debería preservar el seguimiento de la llamada.

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

No conozco ninguna solución alternativa.

No veo el problema con finalmente. Veo excepciones silenciosamente que no aparecen en la consola de error en algunos casos después de un finalmente, pero parece que eso se solucionó en las compilaciones de desarrollo.

Glenn Maynard
fuente
55
Este problema ha sido cerrado desde entonces.
Zachary quema el
24

La propiedad de pila de un objeto Error se crea al mismo tiempo que el objeto Error en sí, no en el punto en que se arroja. A menudo son los mismos por el idioma

   lanzar un nuevo error ("mensaje");

y si usa el código tal como lo escribió, la propiedad de pila no cambiará cuando vuelva a lanzar el error.

Mike Stay
fuente
55
Esto no es cierto (tal vez depende de la plataforma). El motor js que estoy usando ahora (Rhino) restablece la pila en la declaración de lanzamiento, perdiendo la pila original.
Ted Bigham
1
Quizás sea así, pero rhino-1.7.7.2.jar no lo cambia. Qué versión estás usando?
Mike Stay