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(
|
pub fn run_current_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
|
stop_frame: GcCell<'gc, Activation<'gc>>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let stop_frame = *self.stack_frames.last().unwrap();
|
let mut stop_frame_id = None;
|
||||||
let stop_frame_id = self.stack_frames.len() - 1;
|
for (index, frame) in self.stack_frames.iter().enumerate() {
|
||||||
|
if GcCell::ptr_eq(stop_frame, *frame) {
|
||||||
while self
|
stop_frame_id = Some(index);
|
||||||
.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(())
|
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.
|
/// 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.
|
/// Consumes the given return value.
|
||||||
///
|
///
|
||||||
/// This exists primarily so that users of return values can indicate that
|
/// This exists primarily so that users of return values can indicate that
|
||||||
|
|
Loading…
Reference in New Issue