From 68cf9e8869da7a7333537cf6df6bc04b3dea9525 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Sun, 23 Feb 2020 17:28:28 -0500 Subject: [PATCH] Upon encountering an `Err`, dispose of the current AVM2 stack. In the future, the `unwrap_stack_frame` mechanism should be expanded upon to allow running exception handlers and recovering from a Rust error - but not today. --- core/src/avm2.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/core/src/avm2.rs b/core/src/avm2.rs index cc4d379e9..3b558497f 100644 --- a/core/src/avm2.rs +++ b/core/src/avm2.rs @@ -145,7 +145,7 @@ impl<'gc> Avm2<'gc> { Ok(()) } - /// Destroy the current stack frame (if there is one). + /// Destroy the current stack frame (if there is one) with a return value. /// /// The given return value will be pushed on the stack if there is a /// function to return it to. Otherwise, it will be discarded. @@ -175,6 +175,21 @@ impl<'gc> Avm2<'gc> { Ok(()) } + /// Destroy the current stack frame (if there is one) with an exception. + /// + /// TODO: This function should allow exception recovery at some point in + /// the future. + /// + /// NOTE: This means that if you are starting a brand new AVM stack just to + /// get it's return value, you won't get that value. Instead, retain a cell + /// referencing the oldest activation frame and use that to retrieve the + /// return value. + fn unwind_stack_frame(&mut self) { + if let Some(_frame) = self.current_stack_frame() { + self.stack_frames.pop(); + } + } + /// Perform some action with the current stack frame's reader. /// /// This function constructs a reader based off the current stack frame's @@ -449,6 +464,7 @@ impl<'gc> Avm2<'gc> { if let Err(ref e) = result { log::error!("AVM2 error: {}", e); + self.unwind_stack_frame(); return result; } }