avm1: Merge #83, add better support for comparison ops
Enhanced comparison support
This commit is contained in:
commit
8063d9e55c
|
@ -319,6 +319,7 @@ impl<'gc> Avm1<'gc> {
|
||||||
set_playing,
|
set_playing,
|
||||||
scene_offset,
|
scene_offset,
|
||||||
} => self.action_goto_frame_2(context, set_playing, scene_offset),
|
} => self.action_goto_frame_2(context, set_playing, scene_offset),
|
||||||
|
Action::Greater => self.action_greater(context),
|
||||||
Action::GotoLabel(label) => self.action_goto_label(context, &label),
|
Action::GotoLabel(label) => self.action_goto_label(context, &label),
|
||||||
Action::If { offset } => self.action_if(context, offset, reader),
|
Action::If { offset } => self.action_if(context, offset, reader),
|
||||||
Action::Increment => self.action_increment(context),
|
Action::Increment => self.action_increment(context),
|
||||||
|
@ -356,9 +357,11 @@ impl<'gc> Avm1<'gc> {
|
||||||
Action::Stop => self.action_stop(context),
|
Action::Stop => self.action_stop(context),
|
||||||
Action::StopSounds => self.action_stop_sounds(context),
|
Action::StopSounds => self.action_stop_sounds(context),
|
||||||
Action::StoreRegister(register) => self.action_store_register(context, register),
|
Action::StoreRegister(register) => self.action_store_register(context, register),
|
||||||
|
Action::StrictEquals => self.action_strict_equals(context),
|
||||||
Action::StringAdd => self.action_string_add(context),
|
Action::StringAdd => self.action_string_add(context),
|
||||||
Action::StringEquals => self.action_string_equals(context),
|
Action::StringEquals => self.action_string_equals(context),
|
||||||
Action::StringExtract => self.action_string_extract(context),
|
Action::StringExtract => self.action_string_extract(context),
|
||||||
|
Action::StringGreater => self.action_string_greater(context),
|
||||||
Action::StringLength => self.action_string_length(context),
|
Action::StringLength => self.action_string_length(context),
|
||||||
Action::StringLess => self.action_string_less(context),
|
Action::StringLess => self.action_string_less(context),
|
||||||
Action::Subtract => self.action_subtract(context),
|
Action::Subtract => self.action_subtract(context),
|
||||||
|
@ -910,7 +913,9 @@ impl<'gc> Avm1<'gc> {
|
||||||
(Value::Null, Value::Null) => true,
|
(Value::Null, Value::Null) => true,
|
||||||
(Value::Null, Value::Undefined) => true,
|
(Value::Null, Value::Undefined) => true,
|
||||||
(Value::Undefined, Value::Null) => true,
|
(Value::Undefined, Value::Null) => true,
|
||||||
(Value::Number(a), Value::Number(b)) => a == b,
|
// The result of NaN equality appears to change depending on flash player version (not swf version).
|
||||||
|
// This comparison might need to be conditional on targeted version.
|
||||||
|
(Value::Number(a), Value::Number(b)) => a == b || (a.is_nan() && b.is_nan()),
|
||||||
(Value::String(a), Value::String(b)) => a == b,
|
(Value::String(a), Value::String(b)) => a == b,
|
||||||
(Value::Object(_a), Value::Object(_b)) => false, // TODO(Herschel)
|
(Value::Object(_a), Value::Object(_b)) => false, // TODO(Herschel)
|
||||||
(Value::String(a), Value::Number(b)) => a.parse().unwrap_or(std::f64::NAN) == b,
|
(Value::String(a), Value::Number(b)) => a.parse().unwrap_or(std::f64::NAN) == b,
|
||||||
|
@ -1246,6 +1251,18 @@ impl<'gc> Avm1<'gc> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn action_greater(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
// AS1 less than
|
||||||
|
let a = self.pop()?;
|
||||||
|
let b = self.pop()?;
|
||||||
|
let result = b.into_number_v1() > a.into_number_v1();
|
||||||
|
self.push(Value::from_bool_v1(
|
||||||
|
result,
|
||||||
|
self.current_swf_version().unwrap(),
|
||||||
|
));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn action_mb_ascii_to_char(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_mb_ascii_to_char(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
// TODO(Herschel): Results on incorrect operands?
|
// TODO(Herschel): Results on incorrect operands?
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
@ -1503,6 +1520,16 @@ impl<'gc> Avm1<'gc> {
|
||||||
self.set_variable(context, var_path.as_string()?, value)
|
self.set_variable(context, var_path.as_string()?, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::float_cmp)]
|
||||||
|
fn action_strict_equals(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
// The same as normal equality but types must match
|
||||||
|
let a = self.pop()?;
|
||||||
|
let b = self.pop()?;
|
||||||
|
let result = a == b;
|
||||||
|
self.push(Value::Bool(result));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_variable(
|
pub fn set_variable(
|
||||||
&mut self,
|
&mut self,
|
||||||
context: &mut ActionContext<'_, 'gc, '_>,
|
context: &mut ActionContext<'_, 'gc, '_>,
|
||||||
|
@ -1689,6 +1716,19 @@ impl<'gc> Avm1<'gc> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn action_string_greater(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
|
// AS1 strcmp
|
||||||
|
let a = self.pop()?;
|
||||||
|
let b = self.pop()?;
|
||||||
|
// This is specifically a non-UTF8 aware comparison.
|
||||||
|
let result = b.into_string().bytes().gt(a.into_string().bytes());
|
||||||
|
self.push(Value::from_bool_v1(
|
||||||
|
result,
|
||||||
|
self.current_swf_version().unwrap(),
|
||||||
|
));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn action_string_length(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
fn action_string_length(&mut self, _context: &mut ActionContext) -> Result<(), Error> {
|
||||||
// AS1 strlen
|
// AS1 strlen
|
||||||
// Only returns byte length.
|
// Only returns byte length.
|
||||||
|
|
|
@ -41,6 +41,9 @@ swf_tests! {
|
||||||
(goto_rewind1, "avm1/goto_rewind1", 10),
|
(goto_rewind1, "avm1/goto_rewind1", 10),
|
||||||
(goto_rewind2, "avm1/goto_rewind2", 10),
|
(goto_rewind2, "avm1/goto_rewind2", 10),
|
||||||
(goto_rewind3, "avm1/goto_rewind3", 10),
|
(goto_rewind3, "avm1/goto_rewind3", 10),
|
||||||
|
(greaterthan_swf5, "avm1/greaterthan_swf5", 1),
|
||||||
|
(greaterthan_swf8, "avm1/greaterthan_swf8", 1),
|
||||||
|
(strictly_equals, "avm1/strictly_equals", 1),
|
||||||
(tell_target, "avm1/tell_target", 3),
|
(tell_target, "avm1/tell_target", 3),
|
||||||
(typeofs, "avm1/typeof", 1),
|
(typeofs, "avm1/typeof", 1),
|
||||||
(typeof_globals, "avm1/typeof_globals", 1),
|
(typeof_globals, "avm1/typeof_globals", 1),
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
fail
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
success
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,7 @@
|
||||||
|
2 === 2
|
||||||
|
true === true
|
||||||
|
false === false
|
||||||
|
"abc" === "abc"
|
||||||
|
undefined === undefined
|
||||||
|
NaN === NaN
|
||||||
|
null === null
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue