Add tests for SWF6 numerical coercions.
This commit is contained in:
parent
f856243247
commit
9ec85c3892
|
@ -171,7 +171,7 @@ pub fn create_globals<'gc>(
|
||||||
Some(movie_clip_proto),
|
Some(movie_clip_proto),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut globals = ScriptObject::object(gc_context, Some(object_proto));
|
let mut globals = ScriptObject::bare_object();
|
||||||
globals.define_value("Object", object.into(), EnumSet::empty());
|
globals.define_value("Object", object.into(), EnumSet::empty());
|
||||||
globals.define_value("Function", function.into(), EnumSet::empty());
|
globals.define_value("Function", function.into(), EnumSet::empty());
|
||||||
globals.define_value("MovieClip", movie_clip.into(), EnumSet::empty());
|
globals.define_value("MovieClip", movie_clip.into(), EnumSet::empty());
|
||||||
|
|
|
@ -142,10 +142,10 @@ mod tests {
|
||||||
use crate::avm1::Error;
|
use crate::avm1::Error;
|
||||||
|
|
||||||
macro_rules! test_std {
|
macro_rules! test_std {
|
||||||
( $test: ident, $name: expr, $([$($arg: expr),*] => $out: expr),* ) => {
|
( $test: ident, $avm_ver: expr, $name: expr, $([$($arg: expr),*] => $out: expr),* ) => {
|
||||||
#[test]
|
#[test]
|
||||||
fn $test() -> Result<(), Error> {
|
fn $test() -> Result<(), Error> {
|
||||||
with_avm(19, |avm, context, _root| {
|
with_avm($avm_ver, |avm, context, _root| {
|
||||||
let math = create(context.gc_context, Some(avm.prototypes().object), Some(avm.prototypes().function));
|
let math = create(context.gc_context, Some(avm.prototypes().object), Some(avm.prototypes().function));
|
||||||
let function = math.read().get($name, avm, context, math)?.unwrap_immediate();
|
let function = math.read().get($name, avm, context, math)?.unwrap_immediate();
|
||||||
|
|
||||||
|
@ -164,14 +164,14 @@ mod tests {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
test_std!(test_abs, "abs",
|
test_std!(test_abs, 19, "abs",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
[-50.0] => 50.0,
|
[-50.0] => 50.0,
|
||||||
[25.0] => 25.0
|
[25.0] => 25.0
|
||||||
);
|
);
|
||||||
|
|
||||||
test_std!(test_acos, "acos",
|
test_std!(test_acos, 19, "acos",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
[-1.0] => f64::acos(-1.0),
|
[-1.0] => f64::acos(-1.0),
|
||||||
|
@ -179,7 +179,7 @@ mod tests {
|
||||||
[1.0] => f64::acos(1.0)
|
[1.0] => f64::acos(1.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
test_std!(test_asin, "asin",
|
test_std!(test_asin, 19, "asin",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
[-1.0] => f64::asin(-1.0),
|
[-1.0] => f64::asin(-1.0),
|
||||||
|
@ -187,7 +187,7 @@ mod tests {
|
||||||
[1.0] => f64::asin(1.0)
|
[1.0] => f64::asin(1.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
test_std!(test_atan, "atan",
|
test_std!(test_atan, 19, "atan",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
[-1.0] => f64::atan(-1.0),
|
[-1.0] => f64::atan(-1.0),
|
||||||
|
@ -195,54 +195,66 @@ mod tests {
|
||||||
[1.0] => f64::atan(1.0)
|
[1.0] => f64::atan(1.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
test_std!(test_ceil, "ceil",
|
test_std!(test_ceil, 19, "ceil",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
[12.5] => 13.0
|
[12.5] => 13.0
|
||||||
);
|
);
|
||||||
|
|
||||||
test_std!(test_cos, "cos",
|
test_std!(test_cos, 19, "cos",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
[0.0] => 1.0,
|
[0.0] => 1.0,
|
||||||
[std::f64::consts::PI] => f64::cos(std::f64::consts::PI)
|
[std::f64::consts::PI] => f64::cos(std::f64::consts::PI)
|
||||||
);
|
);
|
||||||
|
|
||||||
test_std!(test_exp, "exp",
|
test_std!(test_exp, 19, "exp",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
[1.0] => f64::exp(1.0),
|
[1.0] => f64::exp(1.0),
|
||||||
[2.0] => f64::exp(2.0)
|
[2.0] => f64::exp(2.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
test_std!(test_floor, "floor",
|
test_std!(test_floor, 19, "floor",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
|
[Value::Undefined] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
|
[Value::Bool(false)] => 0.0,
|
||||||
|
[Value::Bool(true)] => 1.0,
|
||||||
[12.5] => 12.0
|
[12.5] => 12.0
|
||||||
);
|
);
|
||||||
|
|
||||||
test_std!(test_round, "round",
|
test_std!(test_floor_swf6, 6, "floor",
|
||||||
|
[] => NAN,
|
||||||
|
[Value::Undefined] => 0.0,
|
||||||
|
[Value::Null] => 0.0,
|
||||||
|
[Value::Bool(false)] => 0.0,
|
||||||
|
[Value::Bool(true)] => 1.0,
|
||||||
|
[12.5] => 12.0
|
||||||
|
);
|
||||||
|
|
||||||
|
test_std!(test_round, 19, "round",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
[12.5] => 13.0,
|
[12.5] => 13.0,
|
||||||
[23.2] => 23.0
|
[23.2] => 23.0
|
||||||
);
|
);
|
||||||
|
|
||||||
test_std!(test_sin, "sin",
|
test_std!(test_sin, 19, "sin",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
[0.0] => f64::sin(0.0),
|
[0.0] => f64::sin(0.0),
|
||||||
[std::f64::consts::PI / 2.0] => f64::sin(std::f64::consts::PI / 2.0)
|
[std::f64::consts::PI / 2.0] => f64::sin(std::f64::consts::PI / 2.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
test_std!(test_sqrt, "sqrt",
|
test_std!(test_sqrt, 19, "sqrt",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
[0.0] => f64::sqrt(0.0),
|
[0.0] => f64::sqrt(0.0),
|
||||||
[5.0] => f64::sqrt(5.0)
|
[5.0] => f64::sqrt(5.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
test_std!(test_tan, "tan",
|
test_std!(test_tan, 19, "tan",
|
||||||
[] => NAN,
|
[] => NAN,
|
||||||
[Value::Null] => NAN,
|
[Value::Null] => NAN,
|
||||||
[0.0] => f64::tan(0.0),
|
[0.0] => f64::tan(0.0),
|
||||||
|
|
|
@ -490,10 +490,109 @@ impl<'gc> Value<'gc> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use crate::avm1::function::Executable;
|
||||||
|
use crate::avm1::globals::create_globals;
|
||||||
|
use crate::avm1::object::ObjectCell;
|
||||||
|
use crate::avm1::return_value::ReturnValue;
|
||||||
|
use crate::avm1::script_object::ScriptObject;
|
||||||
use crate::avm1::test_utils::with_avm;
|
use crate::avm1::test_utils::with_avm;
|
||||||
use crate::avm1::Value;
|
use crate::avm1::{Avm1, Error, Value};
|
||||||
|
use crate::context::UpdateContext;
|
||||||
|
use enumset::EnumSet;
|
||||||
|
use gc_arena::GcCell;
|
||||||
use std::f64::{INFINITY, NAN, NEG_INFINITY};
|
use std::f64::{INFINITY, NAN, NEG_INFINITY};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn to_primitive_num() {
|
||||||
|
with_avm(6, |avm, context, _this| {
|
||||||
|
let t = Value::Bool(true);
|
||||||
|
let u = Value::Undefined;
|
||||||
|
let f = Value::Bool(false);
|
||||||
|
let n = Value::Null;
|
||||||
|
|
||||||
|
assert_eq!(t.to_primitive_num(avm, context).unwrap(), t);
|
||||||
|
assert_eq!(u.to_primitive_num(avm, context).unwrap(), u);
|
||||||
|
assert_eq!(f.to_primitive_num(avm, context).unwrap(), f);
|
||||||
|
assert_eq!(n.to_primitive_num(avm, context).unwrap(), n);
|
||||||
|
|
||||||
|
let (protos, global) = create_globals(context.gc_context);
|
||||||
|
let vglobal = Value::Object(GcCell::allocate(context.gc_context, global));
|
||||||
|
|
||||||
|
assert_eq!(vglobal.to_primitive_num(avm, context).unwrap(), u);
|
||||||
|
|
||||||
|
fn value_of_impl<'gc>(
|
||||||
|
_: &mut Avm1<'gc>,
|
||||||
|
_: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
|
_: ObjectCell<'gc>,
|
||||||
|
_: &[Value<'gc>],
|
||||||
|
) -> Result<ReturnValue<'gc>, Error> {
|
||||||
|
Ok(5.0.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
let valueof = ScriptObject::function(
|
||||||
|
context.gc_context,
|
||||||
|
Executable::Native(value_of_impl),
|
||||||
|
Some(protos.function),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
let o = ScriptObject::object_cell(context.gc_context, Some(protos.object));
|
||||||
|
o.write(context.gc_context)
|
||||||
|
.define_value("valueOf", valueof.into(), EnumSet::empty());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
Value::Object(o).to_primitive_num(avm, context).unwrap(),
|
||||||
|
Value::Number(5.0)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(clippy::float_cmp)]
|
||||||
|
fn to_number_swf7() {
|
||||||
|
with_avm(7, |avm, context, _this| {
|
||||||
|
let t = Value::Bool(true);
|
||||||
|
let u = Value::Undefined;
|
||||||
|
let f = Value::Bool(false);
|
||||||
|
let n = Value::Null;
|
||||||
|
|
||||||
|
assert_eq!(t.as_number(avm, context).unwrap(), 1.0);
|
||||||
|
assert!(u.as_number(avm, context).unwrap().is_nan());
|
||||||
|
assert_eq!(f.as_number(avm, context).unwrap(), 0.0);
|
||||||
|
assert!(n.as_number(avm, context).unwrap().is_nan());
|
||||||
|
|
||||||
|
let bo = Value::Object(GcCell::allocate(
|
||||||
|
context.gc_context,
|
||||||
|
Box::new(ScriptObject::bare_object()),
|
||||||
|
));
|
||||||
|
|
||||||
|
assert!(bo.as_number(avm, context).unwrap().is_nan());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[allow(clippy::float_cmp)]
|
||||||
|
fn to_number_swf6() {
|
||||||
|
with_avm(6, |avm, context, _this| {
|
||||||
|
let t = Value::Bool(true);
|
||||||
|
let u = Value::Undefined;
|
||||||
|
let f = Value::Bool(false);
|
||||||
|
let n = Value::Null;
|
||||||
|
|
||||||
|
assert_eq!(t.as_number(avm, context).unwrap(), 1.0);
|
||||||
|
assert_eq!(u.as_number(avm, context).unwrap(), 0.0);
|
||||||
|
assert_eq!(f.as_number(avm, context).unwrap(), 0.0);
|
||||||
|
assert_eq!(n.as_number(avm, context).unwrap(), 0.0);
|
||||||
|
|
||||||
|
let bo = Value::Object(GcCell::allocate(
|
||||||
|
context.gc_context,
|
||||||
|
Box::new(ScriptObject::bare_object()),
|
||||||
|
));
|
||||||
|
|
||||||
|
assert_eq!(bo.as_number(avm, context).unwrap(), 0.0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn abstract_lt_num() {
|
fn abstract_lt_num() {
|
||||||
with_avm(8, |avm, context, _this| {
|
with_avm(8, |avm, context, _this| {
|
||||||
|
|
Loading…
Reference in New Issue