avm1: Only perform stack-frame adjustments in one place, not scattered throughout actions
This commit is contained in:
parent
9109d89daa
commit
84a5fae43f
|
@ -95,10 +95,7 @@ impl<'gc> ReturnValue<'gc> {
|
||||||
Immediate(val) => Ok(val),
|
Immediate(val) => Ok(val),
|
||||||
ResultOf(frame) => match avm.run_current_frame(context, frame) {
|
ResultOf(frame) => match avm.run_current_frame(context, frame) {
|
||||||
Ok(_) => Ok(avm.pop()),
|
Ok(_) => Ok(avm.pop()),
|
||||||
Err(e) => {
|
Err(e) => Err(e),
|
||||||
avm.retire_stack_frame(context, Value::Undefined);
|
|
||||||
Err(e)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,16 @@ macro_rules! avm_debug {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FrameControl {
|
#[derive(Debug, Clone)]
|
||||||
|
enum ReturnType<'gc> {
|
||||||
|
Implicit,
|
||||||
|
Explicit(Value<'gc>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum FrameControl<'gc> {
|
||||||
Continue,
|
Continue,
|
||||||
Return,
|
Return(ReturnType<'gc>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Collect)]
|
#[derive(Collect)]
|
||||||
|
@ -55,7 +62,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
let result = loop {
|
let result = loop {
|
||||||
let result = self.do_action(&data, context, &mut read);
|
let result = self.do_action(&data, context, &mut read);
|
||||||
match result {
|
match result {
|
||||||
Ok(FrameControl::Return) => break Ok(()),
|
Ok(FrameControl::Return(return_type)) => break Ok(return_type),
|
||||||
Ok(FrameControl::Continue) => {}
|
Ok(FrameControl::Continue) => {}
|
||||||
Err(e) => break Err(e),
|
Err(e) => break Err(e),
|
||||||
}
|
}
|
||||||
|
@ -66,13 +73,23 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
activation.set_pc(read.pos());
|
activation.set_pc(read.pos());
|
||||||
drop(activation);
|
drop(activation);
|
||||||
|
|
||||||
if let Err(error) = &result {
|
match result {
|
||||||
if error.is_halting() {
|
Ok(ReturnType::Explicit(value)) => {
|
||||||
self.avm.halt();
|
self.avm.retire_stack_frame(context, value);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Ok(ReturnType::Implicit) => {
|
||||||
|
self.avm.retire_stack_frame(context, Value::Undefined);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
if error.is_halting() {
|
||||||
|
self.avm.halt();
|
||||||
|
}
|
||||||
|
self.avm.retire_stack_frame(context, Value::Undefined);
|
||||||
|
Err(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Run a single action from a given action reader.
|
/// Run a single action from a given action reader.
|
||||||
|
@ -81,11 +98,10 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
data: &SwfSlice,
|
data: &SwfSlice,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
reader: &mut Reader<'_>,
|
reader: &mut Reader<'_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
if reader.pos() >= (data.end - data.start) {
|
if reader.pos() >= (data.end - data.start) {
|
||||||
//Executing beyond the end of a function constitutes an implicit return.
|
//Executing beyond the end of a function constitutes an implicit return.
|
||||||
self.avm.retire_stack_frame(context, Value::Undefined);
|
Ok(FrameControl::Return(ReturnType::Implicit))
|
||||||
Ok(FrameControl::Return)
|
|
||||||
} else if let Some(action) = reader.read_action()? {
|
} else if let Some(action) = reader.read_action()? {
|
||||||
avm_debug!("Action: {:?}", action);
|
avm_debug!("Action: {:?}", action);
|
||||||
|
|
||||||
|
@ -173,7 +189,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
Action::PushDuplicate => self.action_push_duplicate(context),
|
Action::PushDuplicate => self.action_push_duplicate(context),
|
||||||
Action::RandomNumber => self.action_random_number(context),
|
Action::RandomNumber => self.action_random_number(context),
|
||||||
Action::RemoveSprite => self.action_remove_sprite(context),
|
Action::RemoveSprite => self.action_remove_sprite(context),
|
||||||
Action::Return => self.action_return(context),
|
Action::Return => self.action_return(),
|
||||||
Action::SetMember => self.action_set_member(context),
|
Action::SetMember => self.action_set_member(context),
|
||||||
Action::SetProperty => self.action_set_property(context),
|
Action::SetProperty => self.action_set_property(context),
|
||||||
Action::SetTarget(target) => self.action_set_target(context, &target),
|
Action::SetTarget(target) => self.action_set_target(context, &target),
|
||||||
|
@ -223,8 +239,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
result
|
result
|
||||||
} else {
|
} else {
|
||||||
//The explicit end opcode was encountered so return here
|
//The explicit end opcode was encountered so return here
|
||||||
self.avm.retire_stack_frame(context, Value::Undefined);
|
Ok(FrameControl::Return(ReturnType::Implicit))
|
||||||
Ok(FrameControl::Return)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,12 +247,15 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext,
|
_context: &mut UpdateContext,
|
||||||
action: swf::avm1::types::Action,
|
action: swf::avm1::types::Action,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
log::error!("Unknown AVM1 opcode: {:?}", action);
|
log::error!("Unknown AVM1 opcode: {:?}", action);
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_add(&mut self, _context: &mut UpdateContext) -> Result<FrameControl, Error<'gc>> {
|
fn action_add(
|
||||||
|
&mut self,
|
||||||
|
_context: &mut UpdateContext,
|
||||||
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
self.avm.push(b.into_number_v1() + a.into_number_v1());
|
self.avm.push(b.into_number_v1() + a.into_number_v1());
|
||||||
|
@ -247,7 +265,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_add_2(
|
fn action_add_2(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// ECMA-262 s. 11.6.1
|
// ECMA-262 s. 11.6.1
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -271,7 +289,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_and(
|
fn action_and(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// AS1 logical and
|
// AS1 logical and
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -285,7 +303,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_ascii_to_char(
|
fn action_ascii_to_char(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO(Herschel): Results on incorrect operands?
|
// TODO(Herschel): Results on incorrect operands?
|
||||||
let val = (self.avm.pop().coerce_to_f64(self.avm, context)? as u8) as char;
|
let val = (self.avm.pop().coerce_to_f64(self.avm, context)? as u8) as char;
|
||||||
self.avm.push(val.to_string());
|
self.avm.push(val.to_string());
|
||||||
|
@ -295,7 +313,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_char_to_ascii(
|
fn action_char_to_ascii(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO(Herschel): Results on incorrect operands?
|
// TODO(Herschel): Results on incorrect operands?
|
||||||
let val = self.avm.pop();
|
let val = self.avm.pop();
|
||||||
let string = val.coerce_to_string(self.avm, context)?;
|
let string = val.coerce_to_string(self.avm, context)?;
|
||||||
|
@ -307,7 +325,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_clone_sprite(
|
fn action_clone_sprite(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let depth = self.avm.pop();
|
let depth = self.avm.pop();
|
||||||
let target = self.avm.pop();
|
let target = self.avm.pop();
|
||||||
let source = self.avm.pop();
|
let source = self.avm.pop();
|
||||||
|
@ -334,7 +352,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_bit_and(
|
fn action_bit_and(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
let a = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
||||||
let b = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
let b = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
||||||
let result = a & b;
|
let result = a & b;
|
||||||
|
@ -345,7 +363,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_bit_lshift(
|
fn action_bit_lshift(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop().coerce_to_i32(self.avm, context)? & 0b11111; // Only 5 bits used for shift count
|
let a = self.avm.pop().coerce_to_i32(self.avm, context)? & 0b11111; // Only 5 bits used for shift count
|
||||||
let b = self.avm.pop().coerce_to_i32(self.avm, context)?;
|
let b = self.avm.pop().coerce_to_i32(self.avm, context)?;
|
||||||
let result = b << a;
|
let result = b << a;
|
||||||
|
@ -356,7 +374,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_bit_or(
|
fn action_bit_or(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
let a = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
||||||
let b = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
let b = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
||||||
let result = a | b;
|
let result = a | b;
|
||||||
|
@ -367,7 +385,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_bit_rshift(
|
fn action_bit_rshift(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop().coerce_to_i32(self.avm, context)? & 0b11111; // Only 5 bits used for shift count
|
let a = self.avm.pop().coerce_to_i32(self.avm, context)? & 0b11111; // Only 5 bits used for shift count
|
||||||
let b = self.avm.pop().coerce_to_i32(self.avm, context)?;
|
let b = self.avm.pop().coerce_to_i32(self.avm, context)?;
|
||||||
let result = b >> a;
|
let result = b >> a;
|
||||||
|
@ -378,7 +396,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_bit_urshift(
|
fn action_bit_urshift(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop().coerce_to_u32(self.avm, context)? & 0b11111; // Only 5 bits used for shift count
|
let a = self.avm.pop().coerce_to_u32(self.avm, context)? & 0b11111; // Only 5 bits used for shift count
|
||||||
let b = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
let b = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
||||||
let result = b >> a;
|
let result = b >> a;
|
||||||
|
@ -389,7 +407,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_bit_xor(
|
fn action_bit_xor(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
let a = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
||||||
let b = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
let b = self.avm.pop().coerce_to_u32(self.avm, context)?;
|
||||||
let result = b ^ a;
|
let result = b ^ a;
|
||||||
|
@ -400,7 +418,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_call(
|
fn action_call(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// Runs any actions on the given frame.
|
// Runs any actions on the given frame.
|
||||||
let frame = self.avm.pop();
|
let frame = self.avm.pop();
|
||||||
let clip = self.avm.target_clip_or_root();
|
let clip = self.avm.target_clip_or_root();
|
||||||
|
@ -441,7 +459,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_call_function(
|
fn action_call_function(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let fn_name_value = self.avm.pop();
|
let fn_name_value = self.avm.pop();
|
||||||
let fn_name = fn_name_value.coerce_to_string(self.avm, context)?;
|
let fn_name = fn_name_value.coerce_to_string(self.avm, context)?;
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
|
@ -469,7 +487,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_call_method(
|
fn action_call_method(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let method_name = self.avm.pop();
|
let method_name = self.avm.pop();
|
||||||
let object_val = self.avm.pop();
|
let object_val = self.avm.pop();
|
||||||
let object = value_object::ValueObject::boxed(self.avm, context, object_val);
|
let object = value_object::ValueObject::boxed(self.avm, context, object_val);
|
||||||
|
@ -513,7 +531,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_cast_op(
|
fn action_cast_op(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let obj = self.avm.pop().coerce_to_object(self.avm, context);
|
let obj = self.avm.pop().coerce_to_object(self.avm, context);
|
||||||
let constr = self.avm.pop().coerce_to_object(self.avm, context);
|
let constr = self.avm.pop().coerce_to_object(self.avm, context);
|
||||||
|
|
||||||
|
@ -534,7 +552,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
constant_pool: &[&str],
|
constant_pool: &[&str],
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
self.avm.constant_pool = GcCell::allocate(
|
self.avm.constant_pool = GcCell::allocate(
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
constant_pool.iter().map(|s| (*s).to_string()).collect(),
|
constant_pool.iter().map(|s| (*s).to_string()).collect(),
|
||||||
|
@ -549,7 +567,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_decrement(
|
fn action_decrement(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
self.avm.push(a - 1.0);
|
self.avm.push(a - 1.0);
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
|
@ -561,7 +579,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
name: &str,
|
name: &str,
|
||||||
params: &[&str],
|
params: &[&str],
|
||||||
actions: &[u8],
|
actions: &[u8],
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let swf_version = self.activation.read().swf_version();
|
let swf_version = self.activation.read().swf_version();
|
||||||
let func_data = self.activation.read().data().to_subslice(actions).unwrap();
|
let func_data = self.activation.read().data().to_subslice(actions).unwrap();
|
||||||
let scope =
|
let scope =
|
||||||
|
@ -599,7 +617,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
action_func: &Function,
|
action_func: &Function,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let swf_version = self.activation.read().swf_version();
|
let swf_version = self.activation.read().swf_version();
|
||||||
let func_data = self
|
let func_data = self
|
||||||
.activation
|
.activation
|
||||||
|
@ -640,7 +658,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_define_local(
|
fn action_define_local(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// If the property does not exist on the local object's prototype chain, it is created on the local object.
|
// If the property does not exist on the local object's prototype chain, it is created on the local object.
|
||||||
// Otherwise, the property is set (including calling virtual setters).
|
// Otherwise, the property is set (including calling virtual setters).
|
||||||
let value = self.avm.pop();
|
let value = self.avm.pop();
|
||||||
|
@ -655,7 +673,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_define_local_2(
|
fn action_define_local_2(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// If the property does not exist on the local object's prototype chain, it is created on the local object.
|
// If the property does not exist on the local object's prototype chain, it is created on the local object.
|
||||||
// Otherwise, the property is unchanged.
|
// Otherwise, the property is unchanged.
|
||||||
let name_val = self.avm.pop();
|
let name_val = self.avm.pop();
|
||||||
|
@ -673,7 +691,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_delete(
|
fn action_delete(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let name_val = self.avm.pop();
|
let name_val = self.avm.pop();
|
||||||
let name = name_val.coerce_to_string(self.avm, context)?;
|
let name = name_val.coerce_to_string(self.avm, context)?;
|
||||||
let object = self.avm.pop();
|
let object = self.avm.pop();
|
||||||
|
@ -692,7 +710,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_delete_2(
|
fn action_delete_2(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let name_val = self.avm.pop();
|
let name_val = self.avm.pop();
|
||||||
let name = name_val.coerce_to_string(self.avm, context)?;
|
let name = name_val.coerce_to_string(self.avm, context)?;
|
||||||
|
|
||||||
|
@ -712,7 +730,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_divide(
|
fn action_divide(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// AS1 divide
|
// AS1 divide
|
||||||
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
let b = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let b = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
|
@ -725,7 +743,10 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_end_drag(&mut self, context: &mut UpdateContext) -> Result<FrameControl, Error<'gc>> {
|
fn action_end_drag(
|
||||||
|
&mut self,
|
||||||
|
context: &mut UpdateContext,
|
||||||
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
*context.drag_object = None;
|
*context.drag_object = None;
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
@ -733,7 +754,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_enumerate(
|
fn action_enumerate(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let name_value = self.avm.pop();
|
let name_value = self.avm.pop();
|
||||||
let name = name_value.coerce_to_string(self.avm, context)?;
|
let name = name_value.coerce_to_string(self.avm, context)?;
|
||||||
self.avm.push(Value::Null); // Sentinel that indicates end of enumeration
|
self.avm.push(Value::Null); // Sentinel that indicates end of enumeration
|
||||||
|
@ -758,7 +779,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_enumerate_2(
|
fn action_enumerate_2(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let value = self.avm.pop();
|
let value = self.avm.pop();
|
||||||
|
|
||||||
self.avm.push(Value::Null); // Sentinel that indicates end of enumeration
|
self.avm.push(Value::Null); // Sentinel that indicates end of enumeration
|
||||||
|
@ -778,7 +799,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_equals(
|
fn action_equals(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// AS1 equality
|
// AS1 equality
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -792,7 +813,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_equals_2(
|
fn action_equals_2(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// Version >=5 equality
|
// Version >=5 equality
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -804,7 +825,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_extends(
|
fn action_extends(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let superclass = self.avm.pop().coerce_to_object(self.avm, context);
|
let superclass = self.avm.pop().coerce_to_object(self.avm, context);
|
||||||
let subclass = self.avm.pop().coerce_to_object(self.avm, context);
|
let subclass = self.avm.pop().coerce_to_object(self.avm, context);
|
||||||
|
|
||||||
|
@ -841,7 +862,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_get_member(
|
fn action_get_member(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let name_val = self.avm.pop();
|
let name_val = self.avm.pop();
|
||||||
let name = name_val.coerce_to_string(self.avm, context)?;
|
let name = name_val.coerce_to_string(self.avm, context)?;
|
||||||
let object_val = self.avm.pop();
|
let object_val = self.avm.pop();
|
||||||
|
@ -856,7 +877,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_get_property(
|
fn action_get_property(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let prop_index = self.avm.pop().into_number_v1() as usize;
|
let prop_index = self.avm.pop().into_number_v1() as usize;
|
||||||
let path = self.avm.pop();
|
let path = self.avm.pop();
|
||||||
let ret = if let Some(target) = self.avm.target_clip() {
|
let ret = if let Some(target) = self.avm.target_clip() {
|
||||||
|
@ -884,7 +905,10 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_get_time(&mut self, context: &mut UpdateContext) -> Result<FrameControl, Error<'gc>> {
|
fn action_get_time(
|
||||||
|
&mut self,
|
||||||
|
context: &mut UpdateContext,
|
||||||
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let time = context.navigator.time_since_launch().as_millis() as u32;
|
let time = context.navigator.time_since_launch().as_millis() as u32;
|
||||||
self.avm.push(time);
|
self.avm.push(time);
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
|
@ -893,7 +917,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_get_variable(
|
fn action_get_variable(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let var_path = self.avm.pop();
|
let var_path = self.avm.pop();
|
||||||
let path = var_path.coerce_to_string(self.avm, context)?;
|
let path = var_path.coerce_to_string(self.avm, context)?;
|
||||||
|
|
||||||
|
@ -907,7 +931,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
url: &str,
|
url: &str,
|
||||||
target: &str,
|
target: &str,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
if target.starts_with("_level") && target.len() > 6 {
|
if target.starts_with("_level") && target.len() > 6 {
|
||||||
let url = url.to_string();
|
let url = url.to_string();
|
||||||
match target[6..].parse::<u32>() {
|
match target[6..].parse::<u32>() {
|
||||||
|
@ -950,7 +974,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
swf_method: swf::avm1::types::SendVarsMethod,
|
swf_method: swf::avm1::types::SendVarsMethod,
|
||||||
is_target_sprite: bool,
|
is_target_sprite: bool,
|
||||||
is_load_vars: bool,
|
is_load_vars: bool,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO: Support `LoadVariablesFlag`, `LoadTargetFlag`
|
// TODO: Support `LoadVariablesFlag`, `LoadTargetFlag`
|
||||||
// TODO: What happens if there's only one string?
|
// TODO: What happens if there's only one string?
|
||||||
let target = self.avm.pop();
|
let target = self.avm.pop();
|
||||||
|
@ -1036,7 +1060,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
frame: u16,
|
frame: u16,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
if let Some(clip) = self.avm.target_clip() {
|
if let Some(clip) = self.avm.target_clip() {
|
||||||
if let Some(clip) = clip.as_movie_clip() {
|
if let Some(clip) = clip.as_movie_clip() {
|
||||||
// The frame on the stack is 0-based, not 1-based.
|
// The frame on the stack is 0-based, not 1-based.
|
||||||
|
@ -1055,7 +1079,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
set_playing: bool,
|
set_playing: bool,
|
||||||
scene_offset: u16,
|
scene_offset: u16,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// Version 4+ gotoAndPlay/gotoAndStop
|
// Version 4+ gotoAndPlay/gotoAndStop
|
||||||
// Param can either be a frame number or a frame label.
|
// Param can either be a frame number or a frame label.
|
||||||
if let Some(clip) = self.avm.target_clip() {
|
if let Some(clip) = self.avm.target_clip() {
|
||||||
|
@ -1082,7 +1106,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
label: &str,
|
label: &str,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
if let Some(clip) = self.avm.target_clip() {
|
if let Some(clip) = self.avm.target_clip() {
|
||||||
if let Some(clip) = clip.as_movie_clip() {
|
if let Some(clip) = clip.as_movie_clip() {
|
||||||
if let Some(frame) = clip.frame_label_to_number(label) {
|
if let Some(frame) = clip.frame_label_to_number(label) {
|
||||||
|
@ -1104,7 +1128,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
_context: &mut UpdateContext,
|
_context: &mut UpdateContext,
|
||||||
jump_offset: i16,
|
jump_offset: i16,
|
||||||
reader: &mut Reader<'_>,
|
reader: &mut Reader<'_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let val = self.avm.pop();
|
let val = self.avm.pop();
|
||||||
if val.as_bool(self.avm.current_swf_version()) {
|
if val.as_bool(self.avm.current_swf_version()) {
|
||||||
reader.seek(jump_offset.into());
|
reader.seek(jump_offset.into());
|
||||||
|
@ -1115,7 +1139,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_increment(
|
fn action_increment(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
self.avm.push(a + 1.0);
|
self.avm.push(a + 1.0);
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
|
@ -1124,7 +1148,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_init_array(
|
fn action_init_array(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let num_elements = self.avm.pop().coerce_to_f64(self.avm, context)? as i64;
|
let num_elements = self.avm.pop().coerce_to_f64(self.avm, context)? as i64;
|
||||||
let array = ScriptObject::array(context.gc_context, Some(self.avm.prototypes.array));
|
let array = ScriptObject::array(context.gc_context, Some(self.avm.prototypes.array));
|
||||||
|
|
||||||
|
@ -1139,7 +1163,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_init_object(
|
fn action_init_object(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let num_props = self.avm.pop().coerce_to_f64(self.avm, context)? as i64;
|
let num_props = self.avm.pop().coerce_to_f64(self.avm, context)? as i64;
|
||||||
let object = ScriptObject::object(context.gc_context, Some(self.avm.prototypes.object));
|
let object = ScriptObject::object(context.gc_context, Some(self.avm.prototypes.object));
|
||||||
for _ in 0..num_props {
|
for _ in 0..num_props {
|
||||||
|
@ -1157,7 +1181,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_implements_op(
|
fn action_implements_op(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let constr = self.avm.pop().coerce_to_object(self.avm, context);
|
let constr = self.avm.pop().coerce_to_object(self.avm, context);
|
||||||
let count = self.avm.pop().coerce_to_f64(self.avm, context)? as i64; //TODO: Is this coercion actually performed by Flash?
|
let count = self.avm.pop().coerce_to_f64(self.avm, context)? as i64; //TODO: Is this coercion actually performed by Flash?
|
||||||
let mut interfaces = vec![];
|
let mut interfaces = vec![];
|
||||||
|
@ -1180,7 +1204,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_instance_of(
|
fn action_instance_of(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let constr = self.avm.pop().coerce_to_object(self.avm, context);
|
let constr = self.avm.pop().coerce_to_object(self.avm, context);
|
||||||
let obj = self.avm.pop().coerce_to_object(self.avm, context);
|
let obj = self.avm.pop().coerce_to_object(self.avm, context);
|
||||||
|
|
||||||
|
@ -1198,7 +1222,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
_context: &mut UpdateContext,
|
_context: &mut UpdateContext,
|
||||||
jump_offset: i16,
|
jump_offset: i16,
|
||||||
reader: &mut Reader<'_>,
|
reader: &mut Reader<'_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO(Herschel): Handle out-of-bounds.
|
// TODO(Herschel): Handle out-of-bounds.
|
||||||
reader.seek(jump_offset.into());
|
reader.seek(jump_offset.into());
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
|
@ -1207,7 +1231,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_less(
|
fn action_less(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// AS1 less than
|
// AS1 less than
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -1220,7 +1244,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_less_2(
|
fn action_less_2(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// ECMA-262 s. 11.8.1
|
// ECMA-262 s. 11.8.1
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -1234,7 +1258,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_greater(
|
fn action_greater(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// ECMA-262 s. 11.8.2
|
// ECMA-262 s. 11.8.2
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -1248,7 +1272,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_mb_ascii_to_char(
|
fn action_mb_ascii_to_char(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO(Herschel): Results on incorrect operands?
|
// TODO(Herschel): Results on incorrect operands?
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
let result = char::try_from(self.avm.pop().coerce_to_f64(self.avm, context)? as u32);
|
let result = char::try_from(self.avm.pop().coerce_to_f64(self.avm, context)? as u32);
|
||||||
|
@ -1262,7 +1286,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_mb_char_to_ascii(
|
fn action_mb_char_to_ascii(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO(Herschel): Results on incorrect operands?
|
// TODO(Herschel): Results on incorrect operands?
|
||||||
let val = self.avm.pop();
|
let val = self.avm.pop();
|
||||||
let s = val.coerce_to_string(self.avm, context)?;
|
let s = val.coerce_to_string(self.avm, context)?;
|
||||||
|
@ -1274,7 +1298,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_mb_string_extract(
|
fn action_mb_string_extract(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO(Herschel): Result with incorrect operands?
|
// TODO(Herschel): Result with incorrect operands?
|
||||||
let len = self.avm.pop().coerce_to_f64(self.avm, context)? as usize;
|
let len = self.avm.pop().coerce_to_f64(self.avm, context)? as usize;
|
||||||
let start = self.avm.pop().coerce_to_f64(self.avm, context)? as usize;
|
let start = self.avm.pop().coerce_to_f64(self.avm, context)? as usize;
|
||||||
|
@ -1288,7 +1312,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_mb_string_length(
|
fn action_mb_string_length(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO(Herschel): Result with non-string operands?
|
// TODO(Herschel): Result with non-string operands?
|
||||||
let val = self.avm.pop();
|
let val = self.avm.pop();
|
||||||
let len = val.coerce_to_string(self.avm, context)?.len();
|
let len = val.coerce_to_string(self.avm, context)?.len();
|
||||||
|
@ -1299,7 +1323,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_multiply(
|
fn action_multiply(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
let b = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let b = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
self.avm.push(a * b);
|
self.avm.push(a * b);
|
||||||
|
@ -1309,7 +1333,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_modulo(
|
fn action_modulo(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO: Wrong operands?
|
// TODO: Wrong operands?
|
||||||
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
let b = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let b = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
|
@ -1320,7 +1344,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_not(
|
fn action_not(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let version = self.avm.current_swf_version();
|
let version = self.avm.current_swf_version();
|
||||||
let val = !self.avm.pop().as_bool(version);
|
let val = !self.avm.pop().as_bool(version);
|
||||||
self.avm.push(Value::from_bool(val, version));
|
self.avm.push(Value::from_bool(val, version));
|
||||||
|
@ -1330,7 +1354,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_next_frame(
|
fn action_next_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
if let Some(clip) = self.avm.target_clip() {
|
if let Some(clip) = self.avm.target_clip() {
|
||||||
if let Some(clip) = clip.as_movie_clip() {
|
if let Some(clip) = clip.as_movie_clip() {
|
||||||
clip.next_frame(self.avm, context);
|
clip.next_frame(self.avm, context);
|
||||||
|
@ -1346,7 +1370,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_new_method(
|
fn action_new_method(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let method_name = self.avm.pop();
|
let method_name = self.avm.pop();
|
||||||
let object_val = self.avm.pop();
|
let object_val = self.avm.pop();
|
||||||
let num_args = self.avm.pop().coerce_to_f64(self.avm, context)? as i64;
|
let num_args = self.avm.pop().coerce_to_f64(self.avm, context)? as i64;
|
||||||
|
@ -1402,7 +1426,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_new_object(
|
fn action_new_object(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let fn_name_val = self.avm.pop();
|
let fn_name_val = self.avm.pop();
|
||||||
let fn_name = fn_name_val.coerce_to_string(self.avm, context)?;
|
let fn_name = fn_name_val.coerce_to_string(self.avm, context)?;
|
||||||
let num_args = self.avm.pop().coerce_to_f64(self.avm, context)? as i64;
|
let num_args = self.avm.pop().coerce_to_f64(self.avm, context)? as i64;
|
||||||
|
@ -1453,7 +1477,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_or(
|
fn action_or(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext<'_, 'gc, '_>,
|
_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// AS1 logical or
|
// AS1 logical or
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -1466,7 +1490,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_play(
|
fn action_play(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
if let Some(clip) = self.avm.target_clip() {
|
if let Some(clip) = self.avm.target_clip() {
|
||||||
if let Some(clip) = clip.as_movie_clip() {
|
if let Some(clip) = clip.as_movie_clip() {
|
||||||
clip.play(context)
|
clip.play(context)
|
||||||
|
@ -1482,7 +1506,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_prev_frame(
|
fn action_prev_frame(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
if let Some(clip) = self.avm.target_clip() {
|
if let Some(clip) = self.avm.target_clip() {
|
||||||
if let Some(clip) = clip.as_movie_clip() {
|
if let Some(clip) = clip.as_movie_clip() {
|
||||||
clip.prev_frame(self.avm, context);
|
clip.prev_frame(self.avm, context);
|
||||||
|
@ -1495,7 +1519,10 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_pop(&mut self, _context: &mut UpdateContext) -> Result<FrameControl, Error<'gc>> {
|
fn action_pop(
|
||||||
|
&mut self,
|
||||||
|
_context: &mut UpdateContext,
|
||||||
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
self.avm.pop();
|
self.avm.pop();
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
@ -1504,7 +1531,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext,
|
_context: &mut UpdateContext,
|
||||||
values: &[swf::avm1::types::Value],
|
values: &[swf::avm1::types::Value],
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
for value in values {
|
for value in values {
|
||||||
use swf::avm1::types::Value as SwfValue;
|
use swf::avm1::types::Value as SwfValue;
|
||||||
let value = match value {
|
let value = match value {
|
||||||
|
@ -1543,7 +1570,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_push_duplicate(
|
fn action_push_duplicate(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext,
|
_context: &mut UpdateContext,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let val = self.avm.pop();
|
let val = self.avm.pop();
|
||||||
self.avm.push(val.clone());
|
self.avm.push(val.clone());
|
||||||
self.avm.push(val);
|
self.avm.push(val);
|
||||||
|
@ -1553,7 +1580,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_random_number(
|
fn action_random_number(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext,
|
context: &mut UpdateContext,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// A max value < 0 will always return 0,
|
// A max value < 0 will always return 0,
|
||||||
// and the max value gets converted into an i32, so any number > 2^31 - 1 will return 0.
|
// and the max value gets converted into an i32, so any number > 2^31 - 1 will return 0.
|
||||||
let max = self.avm.pop().into_number_v1() as i32;
|
let max = self.avm.pop().into_number_v1() as i32;
|
||||||
|
@ -1569,7 +1596,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_remove_sprite(
|
fn action_remove_sprite(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let target = self.avm.pop();
|
let target = self.avm.pop();
|
||||||
let start_clip = self.avm.target_clip_or_root();
|
let start_clip = self.avm.target_clip_or_root();
|
||||||
let target_clip = self
|
let target_clip = self
|
||||||
|
@ -1584,20 +1611,16 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_return(
|
fn action_return(&mut self) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
&mut self,
|
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
|
||||||
let return_value = self.avm.pop();
|
let return_value = self.avm.pop();
|
||||||
self.avm.retire_stack_frame(context, return_value);
|
|
||||||
|
|
||||||
Ok(FrameControl::Return)
|
Ok(FrameControl::Return(ReturnType::Explicit(return_value)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_set_member(
|
fn action_set_member(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let value = self.avm.pop();
|
let value = self.avm.pop();
|
||||||
let name_val = self.avm.pop();
|
let name_val = self.avm.pop();
|
||||||
let name = name_val.coerce_to_string(self.avm, context)?;
|
let name = name_val.coerce_to_string(self.avm, context)?;
|
||||||
|
@ -1611,7 +1634,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_set_property(
|
fn action_set_property(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let value = self.avm.pop();
|
let value = self.avm.pop();
|
||||||
let prop_index = self.avm.pop().coerce_to_u32(self.avm, context)? as usize;
|
let prop_index = self.avm.pop().coerce_to_u32(self.avm, context)? as usize;
|
||||||
let path = self.avm.pop();
|
let path = self.avm.pop();
|
||||||
|
@ -1637,7 +1660,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_set_variable(
|
fn action_set_variable(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// Flash 4-style variable
|
// Flash 4-style variable
|
||||||
let value = self.avm.pop();
|
let value = self.avm.pop();
|
||||||
let var_path_val = self.avm.pop();
|
let var_path_val = self.avm.pop();
|
||||||
|
@ -1650,7 +1673,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_strict_equals(
|
fn action_strict_equals(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext,
|
_context: &mut UpdateContext,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// The same as normal equality but types must match
|
// The same as normal equality but types must match
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -1663,7 +1686,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
target: &str,
|
target: &str,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let base_clip = self.avm.base_clip();
|
let base_clip = self.avm.base_clip();
|
||||||
let new_target_clip;
|
let new_target_clip;
|
||||||
let root = base_clip.root();
|
let root = base_clip.root();
|
||||||
|
@ -1704,7 +1727,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_set_target2(
|
fn action_set_target2(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let target = self.avm.pop();
|
let target = self.avm.pop();
|
||||||
match target {
|
match target {
|
||||||
Value::String(target) => {
|
Value::String(target) => {
|
||||||
|
@ -1747,7 +1770,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_stack_swap(
|
fn action_stack_swap(
|
||||||
&mut self,
|
&mut self,
|
||||||
_context: &mut UpdateContext,
|
_context: &mut UpdateContext,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
self.avm.push(a);
|
self.avm.push(a);
|
||||||
|
@ -1758,7 +1781,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_start_drag(
|
fn action_start_drag(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let target = self.avm.pop();
|
let target = self.avm.pop();
|
||||||
let start_clip = self.avm.target_clip_or_root();
|
let start_clip = self.avm.target_clip_or_root();
|
||||||
let display_object = self
|
let display_object = self
|
||||||
|
@ -1790,7 +1813,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_stop(
|
fn action_stop(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
if let Some(clip) = self.avm.target_clip() {
|
if let Some(clip) = self.avm.target_clip() {
|
||||||
if let Some(clip) = clip.as_movie_clip() {
|
if let Some(clip) = clip.as_movie_clip() {
|
||||||
clip.stop(context);
|
clip.stop(context);
|
||||||
|
@ -1806,7 +1829,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_stop_sounds(
|
fn action_stop_sounds(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext,
|
context: &mut UpdateContext,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
context.audio.stop_all_sounds();
|
context.audio.stop_all_sounds();
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
@ -1815,7 +1838,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
register: u8,
|
register: u8,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// The value must remain on the stack.
|
// The value must remain on the stack.
|
||||||
let val = self.avm.pop();
|
let val = self.avm.pop();
|
||||||
self.avm.push(val.clone());
|
self.avm.push(val.clone());
|
||||||
|
@ -1827,7 +1850,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_string_add(
|
fn action_string_add(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// SWFv4 string concatenation
|
// SWFv4 string concatenation
|
||||||
// TODO(Herschel): Result with non-string operands?
|
// TODO(Herschel): Result with non-string operands?
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
|
@ -1844,7 +1867,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_string_equals(
|
fn action_string_equals(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// AS1 strcmp
|
// AS1 strcmp
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -1858,7 +1881,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_string_extract(
|
fn action_string_extract(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// SWFv4 substring
|
// SWFv4 substring
|
||||||
// TODO(Herschel): Result with incorrect operands?
|
// TODO(Herschel): Result with incorrect operands?
|
||||||
let len = self.avm.pop().coerce_to_f64(self.avm, context)? as usize;
|
let len = self.avm.pop().coerce_to_f64(self.avm, context)? as usize;
|
||||||
|
@ -1880,7 +1903,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_string_greater(
|
fn action_string_greater(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// AS1 strcmp
|
// AS1 strcmp
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -1897,7 +1920,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_string_length(
|
fn action_string_length(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// AS1 strlen
|
// AS1 strlen
|
||||||
// Only returns byte length.
|
// Only returns byte length.
|
||||||
// TODO(Herschel): Result with non-string operands?
|
// TODO(Herschel): Result with non-string operands?
|
||||||
|
@ -1910,7 +1933,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_string_less(
|
fn action_string_less(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// AS1 strcmp
|
// AS1 strcmp
|
||||||
let a = self.avm.pop();
|
let a = self.avm.pop();
|
||||||
let b = self.avm.pop();
|
let b = self.avm.pop();
|
||||||
|
@ -1927,7 +1950,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_subtract(
|
fn action_subtract(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let a = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
let b = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let b = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
self.avm.push(b - a);
|
self.avm.push(b - a);
|
||||||
|
@ -1937,7 +1960,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_target_path(
|
fn action_target_path(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO(Herschel)
|
// TODO(Herschel)
|
||||||
let _clip = self.avm.pop().coerce_to_object(self.avm, context);
|
let _clip = self.avm.pop().coerce_to_object(self.avm, context);
|
||||||
self.avm.push(Value::Undefined);
|
self.avm.push(Value::Undefined);
|
||||||
|
@ -1945,7 +1968,10 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_quality(&mut self, _context: &mut UpdateContext) -> Result<FrameControl, Error<'gc>> {
|
fn toggle_quality(
|
||||||
|
&mut self,
|
||||||
|
_context: &mut UpdateContext,
|
||||||
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO(Herschel): Noop for now? Could chang anti-aliasing on render backend.
|
// TODO(Herschel): Noop for now? Could chang anti-aliasing on render backend.
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
@ -1953,7 +1979,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_to_integer(
|
fn action_to_integer(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let val = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let val = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
self.avm.push(val.trunc());
|
self.avm.push(val.trunc());
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
|
@ -1962,7 +1988,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_to_number(
|
fn action_to_number(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let val = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
let val = self.avm.pop().coerce_to_f64(self.avm, context)?;
|
||||||
self.avm.push(val);
|
self.avm.push(val);
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
|
@ -1971,7 +1997,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_to_string(
|
fn action_to_string(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let val = self.avm.pop();
|
let val = self.avm.pop();
|
||||||
let string = val.coerce_to_string(self.avm, context)?;
|
let string = val.coerce_to_string(self.avm, context)?;
|
||||||
self.avm.push(string);
|
self.avm.push(string);
|
||||||
|
@ -1981,7 +2007,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
fn action_trace(
|
fn action_trace(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let val = self.avm.pop();
|
let val = self.avm.pop();
|
||||||
// trace always prints "undefined" even though SWF6 and below normally
|
// trace always prints "undefined" even though SWF6 and below normally
|
||||||
// coerce undefined to "".
|
// coerce undefined to "".
|
||||||
|
@ -1994,7 +2020,10 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn action_type_of(&mut self, _context: &mut UpdateContext) -> Result<FrameControl, Error<'gc>> {
|
fn action_type_of(
|
||||||
|
&mut self,
|
||||||
|
_context: &mut UpdateContext,
|
||||||
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let type_of = self.avm.pop().type_of();
|
let type_of = self.avm.pop().type_of();
|
||||||
self.avm.push(type_of);
|
self.avm.push(type_of);
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
|
@ -2006,7 +2035,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
_frame: u16,
|
_frame: u16,
|
||||||
num_actions_to_skip: u8,
|
num_actions_to_skip: u8,
|
||||||
r: &mut Reader<'_>,
|
r: &mut Reader<'_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO(Herschel): Always true for now.
|
// TODO(Herschel): Always true for now.
|
||||||
let loaded = true;
|
let loaded = true;
|
||||||
if !loaded {
|
if !loaded {
|
||||||
|
@ -2022,7 +2051,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
num_actions_to_skip: u8,
|
num_actions_to_skip: u8,
|
||||||
r: &mut Reader<'_>,
|
r: &mut Reader<'_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
// TODO(Herschel): Always true for now.
|
// TODO(Herschel): Always true for now.
|
||||||
let _frame_num = self.avm.pop().coerce_to_f64(self.avm, context)? as u16;
|
let _frame_num = self.avm.pop().coerce_to_f64(self.avm, context)? as u16;
|
||||||
let loaded = true;
|
let loaded = true;
|
||||||
|
@ -2034,10 +2063,11 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused_variables)]
|
||||||
fn action_throw(
|
fn action_throw(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let value = self.avm.pop();
|
let value = self.avm.pop();
|
||||||
avm_debug!(
|
avm_debug!(
|
||||||
"Thrown exception: {}",
|
"Thrown exception: {}",
|
||||||
|
@ -2045,7 +2075,6 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
.coerce_to_string(self.avm, context)
|
.coerce_to_string(self.avm, context)
|
||||||
.unwrap_or_else(|_| Cow::Borrowed("undefined"))
|
.unwrap_or_else(|_| Cow::Borrowed("undefined"))
|
||||||
);
|
);
|
||||||
self.avm.retire_stack_frame(context, Value::Undefined);
|
|
||||||
Err(Error::ThrownValue(value))
|
Err(Error::ThrownValue(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2053,7 +2082,7 @@ impl<'a, 'gc: 'a> StackFrame<'a, 'gc> {
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
actions: &[u8],
|
actions: &[u8],
|
||||||
) -> Result<FrameControl, Error<'gc>> {
|
) -> Result<FrameControl<'gc>, Error<'gc>> {
|
||||||
let object = self.avm.pop().coerce_to_object(self.avm, context);
|
let object = self.avm.pop().coerce_to_object(self.avm, context);
|
||||||
let block = self.activation.read().data().to_subslice(actions).unwrap();
|
let block = self.activation.read().data().to_subslice(actions).unwrap();
|
||||||
let with_scope = Scope::new_with_scope(
|
let with_scope = Scope::new_with_scope(
|
||||||
|
|
Loading…
Reference in New Issue