Add support for calling bare functions and returning from them.

This commit is contained in:
David Wendt 2019-09-16 19:15:22 -04:00 committed by Mike Welsh
parent 00b5d9ecf5
commit edc37dee5d
2 changed files with 31 additions and 14 deletions

View File

@ -563,22 +563,24 @@ impl<'gc> Avm1<'gc> {
Err("Unimplemented action: Call".into())
}
fn action_call_function(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
let _fn_name = self.pop()?.as_string()?;
fn action_call_function(&mut self, context: &mut ActionContext<'_, 'gc, '_>) -> Result<(), Error> {
let fn_name = self.pop()?;
let mut args = Vec::new();
let num_args = self.pop()?.as_i64()?; // TODO(Herschel): max arg count?
for _ in 0..num_args {
self.pop()?;
args.push(self.pop()?);
}
let target_fn = self.current_stack_frame_mut().unwrap().locals_mut().get(fn_name.as_string()?).unwrap_or_else(|| &Value::Undefined).clone();
let return_value = target_fn.call(self, context, self.globals, &args)?;
if let Some(instant_return) = return_value {
self.current_stack_frame_mut().unwrap().stack_mut().push(instant_return);
}
self.current_stack_frame_mut().unwrap().stack_mut().push(Value::Undefined);
// TODO(Herschel)
Err("Unimplemented action: CallFunction".into())
Ok(())
}
fn action_call_method(
&mut self,
context: &mut ActionContext<'_, 'gc, '_>,
) -> Result<(), Error> {
fn action_call_method(&mut self, context: &mut ActionContext<'_, 'gc, '_>) -> Result<(), Error> {
let method_name = self.pop()?;
let object = self.pop()?;
let num_args = self.pop()?.as_i64()?; // TODO(Herschel): max arg count?
@ -1247,9 +1249,14 @@ impl<'gc> Avm1<'gc> {
}
fn action_return(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
let _result = self.pop()?;
// TODO(Herschel)
Err("Unimplemented action: Return".into())
let result = self.pop()?;
if self.stack_frames.len() > 1 {
self.retire_stack_frame();
self.current_stack_frame_mut().unwrap().stack_mut().push(result);
}
Ok(())
}
fn action_set_member(&mut self, _context: &mut ActionContext) -> Result<(), Error> {

View File

@ -67,7 +67,17 @@ impl<'gc> Executable<'gc> {
pub fn exec(&self, avm: &mut Avm1<'gc>, ac: &mut ActionContext<'_, 'gc, '_>, this: GcCell<'gc, Object<'gc>>, args: &[Value<'gc>]) -> Option<Value<'gc>> {
match self {
Executable::Native(nf) => Some(nf(avm, ac, this, args)),
Executable::Action(af) => None
Executable::Action(af) => {
avm.insert_stack_frame_from_action(af.swf_version, af.data.clone());
for arg in args {
avm.current_stack_frame_mut().unwrap().stack_mut().push(arg.clone());
}
avm.current_stack_frame_mut().unwrap().locals_mut().insert("this".to_string(), Value::Object(this));
None
}
}
}
}