Add a method to force resolve a `ReturnValue` on the Rust stack via recursion.
This commit is contained in:
parent
bc74b2fc4a
commit
e2dcf47c56
|
@ -301,23 +301,32 @@ impl<'gc> Avm1<'gc> {
|
|||
pub fn run_current_frame(
|
||||
&mut self,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
stop_frame: GcCell<'gc, Activation<'gc>>,
|
||||
) -> Result<(), Error> {
|
||||
let stop_frame = *self.stack_frames.last().unwrap();
|
||||
let stop_frame_id = self.stack_frames.len() - 1;
|
||||
|
||||
while self
|
||||
.stack_frames
|
||||
.get(stop_frame_id)
|
||||
.map(|fr| GcCell::ptr_eq(stop_frame, *fr))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
self.with_current_reader_mut(context, |this, r, context| {
|
||||
this.do_next_action(context, r)
|
||||
})
|
||||
.unwrap()?;
|
||||
let mut stop_frame_id = None;
|
||||
for (index, frame) in self.stack_frames.iter().enumerate() {
|
||||
if GcCell::ptr_eq(stop_frame, *frame) {
|
||||
stop_frame_id = Some(index);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
if let Some(stop_frame_id) = stop_frame_id {
|
||||
while self
|
||||
.stack_frames
|
||||
.get(stop_frame_id)
|
||||
.map(|fr| GcCell::ptr_eq(stop_frame, *fr))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
self.with_current_reader_mut(context, |this, r, context| {
|
||||
this.do_next_action(context, r)
|
||||
})
|
||||
.unwrap()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err("Attempted to run a frame not on the current interpreter stack".into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Run a single action from a given action reader.
|
||||
|
|
|
@ -109,6 +109,26 @@ impl<'gc> ReturnValue<'gc> {
|
|||
};
|
||||
}
|
||||
|
||||
/// Force a return value to resolve on the Rust stack by recursing back
|
||||
/// into the AVM.
|
||||
pub fn resolve(
|
||||
self,
|
||||
avm: &mut Avm1<'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
use ReturnValue::*;
|
||||
|
||||
match self {
|
||||
Immediate(val) => Ok(val),
|
||||
ResultOf(frame) => {
|
||||
avm.run_current_frame(context, frame)?;
|
||||
|
||||
avm.pop()
|
||||
}
|
||||
NoResult => Err("Attempted to resolve a no-result return value".into()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes the given return value.
|
||||
///
|
||||
/// This exists primarily so that users of return values can indicate that
|
||||
|
|
Loading…
Reference in New Issue