Comment puis-je renvoyer une exception en Javascript, mais conserver la pile?

151

En Javascript, supposons que je veuille effectuer un nettoyage lorsqu'une exception se produit, mais que l'exception continue à se propager dans la pile, par exemple:

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

Le problème avec ce code est que la capture et la relance de l'exception entraîne la perte des informations de trace de la pile jusqu'à ce point, de sorte que si l'exception est à nouveau interceptée par la suite, plus haut sur la pile, la trace de la pile ne descend que vers le re -jeter. Cela craint car cela signifie qu'il ne contient pas la fonction qui a réellement levé l'exception.

En fin de compte, try..a finalement le même comportement, au moins dans Chrome (c'est-à-dire que ce n'est pas la relance qui est précisément le problème, mais la présence d'un bloc de gestionnaire d'exceptions.)

Quelqu'un connaît-il un moyen de renvoyer une exception en Javascript mais de conserver la trace de pile qui lui est associée? À défaut, que diriez-vous des suggestions pour d'autres moyens d'ajouter des gestionnaires de nettoyage sûrs pour les exceptions, tout en capturant des traces de pile complètes lorsqu'une exception se produit?

Merci pour tous les conseils :)

Geoff
la source

Réponses:

78

Il s'agit d'un bogue dans Chrome. La relance d'une exception doit conserver la trace des appels.

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

Je ne connais aucune solution de contournement.

Je ne vois pas le problème avec finalement. Je vois des exceptions qui n'apparaissent pas silencieusement sur la console d'erreur dans certains cas après un enfin, mais celle-ci semble être corrigée dans les versions de développement.

Glenn Maynard
la source
5
Ce problème a depuis été clos.
Zachary Burns
24

La propriété stack d'un objet Error est créée en même temps que l'objet Error lui-même, pas au moment où il est lancé. Ils sont souvent les mêmes à cause de l'idiome

   lancer une nouvelle erreur ("message");

et si vous utilisez le code comme vous l' avez écrit, la propriété de la pile sera pas être modifié lorsque vous réémettre l'erreur.

Mike Stay
la source
5
Ce n'est pas vrai (peut-être dépendant de la plate-forme). Le moteur js que j'utilise maintenant (Rhino) réinitialise la pile sur l'instruction throw, perdant la pile d'origine.
Ted Bigham
1
Peut-être, mais rhino-1.7.7.2.jar ne le change pas. Quelle version utilisez-vous?
Mike Stay