core: implement isNaN and Number functions. Involves updating to_number function in Value. Note: this varies a little from the ECMA spec such as not allowing spaces in numbers (i.e. ' 5' => NaN). No definitive reference for this but was found experimentally. Same with not supporting 'Infinity'
This commit is contained in:
parent
38c66b5b8d
commit
463d0fc352
|
@ -63,9 +63,36 @@ pub fn boolean<'gc>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn number<'gc>(
|
||||
_avm: &mut Avm1<'gc>,
|
||||
_action_context: &mut ActionContext<'_, 'gc, '_>,
|
||||
_this: GcCell<'gc, Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Value<'gc> {
|
||||
if let Some(val) = args.get(0) {
|
||||
Value::Number(val.as_number())
|
||||
} else {
|
||||
Value::Number(0.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_nan<'gc>(
|
||||
_avm: &mut Avm1<'gc>,
|
||||
_action_context: &mut ActionContext<'_, 'gc, '_>,
|
||||
_this: GcCell<'gc, Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Value<'gc> {
|
||||
if let Some(val) = args.get(0) {
|
||||
Value::Bool(val.as_number().is_nan())
|
||||
} else {
|
||||
Value::Bool(true)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_globals<'gc>(gc_context: MutationContext<'gc, '_>) -> Object<'gc> {
|
||||
let mut globals = Object::object(gc_context);
|
||||
|
||||
globals.force_set_function("isNaN", is_nan, gc_context, EnumSet::empty());
|
||||
globals.force_set_function("Boolean", boolean, gc_context, EnumSet::empty());
|
||||
globals.force_set(
|
||||
"Math",
|
||||
|
@ -73,7 +100,9 @@ pub fn create_globals<'gc>(gc_context: MutationContext<'gc, '_>) -> Object<'gc>
|
|||
EnumSet::empty(),
|
||||
);
|
||||
globals.force_set_function("getURL", getURL, gc_context, EnumSet::empty());
|
||||
globals.force_set_function("Number", number, gc_context, EnumSet::empty());
|
||||
globals.force_set_function("random", random, gc_context, EnumSet::empty());
|
||||
|
||||
globals.force_set("NaN", Value::Number(std::f64::NAN), EnumSet::empty());
|
||||
globals.force_set(
|
||||
"Infinity",
|
||||
|
@ -178,4 +207,48 @@ mod tests {
|
|||
&[] => Value::Bool(false)
|
||||
);
|
||||
|
||||
test_std!(is_nan_function, is_nan, 19,
|
||||
&[Value::Bool(true)] => Value::Bool(false),
|
||||
&[Value::Bool(false)] => Value::Bool(false),
|
||||
&[Value::Number(10.0)] => Value::Bool(false),
|
||||
&[Value::Number(-10.0)] => Value::Bool(false),
|
||||
&[Value::Number(0.0)] => Value::Bool(false),
|
||||
&[Value::Number(std::f64::INFINITY)] => Value::Bool(false),
|
||||
&[Value::Number(std::f64::NAN)] => Value::Bool(true),
|
||||
&[Value::String("".to_string())] => Value::Bool(false),
|
||||
&[Value::String("Hello".to_string())] => Value::Bool(true),
|
||||
&[Value::String(" ".to_string())] => Value::Bool(true),
|
||||
&[Value::String(" 5 ".to_string())] => Value::Bool(true),
|
||||
&[Value::String("0".to_string())] => Value::Bool(false),
|
||||
&[Value::String("1".to_string())] => Value::Bool(false),
|
||||
&[Value::String("Infinity".to_string())] => Value::Bool(true),
|
||||
&[Value::String("100a".to_string())] => Value::Bool(true),
|
||||
&[Value::String("0x10".to_string())] => Value::Bool(false),
|
||||
&[Value::String("0xhello".to_string())] => Value::Bool(true),
|
||||
&[Value::String("123e-1".to_string())] => Value::Bool(false),
|
||||
&[] => Value::Bool(true)
|
||||
);
|
||||
|
||||
test_std!(number_function, number, 19,
|
||||
&[Value::Bool(true)] => Value::Number(1.0),
|
||||
&[Value::Bool(false)] => Value::Number(0.0),
|
||||
&[Value::Number(10.0)] => Value::Number(10.0),
|
||||
&[Value::Number(-10.0)] => Value::Number(-10.0),
|
||||
&[Value::Number(0.0)] => Value::Number(0.0),
|
||||
&[Value::Number(std::f64::INFINITY)] => Value::Number(std::f64::INFINITY),
|
||||
&[Value::Number(std::f64::NAN)] => Value::Number(std::f64::NAN),
|
||||
&[Value::String("".to_string())] => Value::Number(0.0),
|
||||
&[Value::String("Hello".to_string())] => Value::Number(std::f64::NAN),
|
||||
&[Value::String(" ".to_string())] => Value::Number(std::f64::NAN),
|
||||
&[Value::String(" 5 ".to_string())] => Value::Number(std::f64::NAN),
|
||||
&[Value::String("0".to_string())] => Value::Number(0.0),
|
||||
&[Value::String("1".to_string())] => Value::Number(1.0),
|
||||
&[Value::String("Infinity".to_string())] => Value::Number(std::f64::NAN),
|
||||
&[Value::String("100a".to_string())] => Value::Number(std::f64::NAN),
|
||||
&[Value::String("0x10".to_string())] => Value::Number(16.0),
|
||||
&[Value::String("0xhello".to_string())] => Value::Number(std::f64::NAN),
|
||||
&[Value::String("123e-1".to_string())] => Value::Number(12.3),
|
||||
&[] => Value::Number(0.0)
|
||||
);
|
||||
|
||||
}
|
||||
|
|
|
@ -73,7 +73,18 @@ impl<'gc> Value<'gc> {
|
|||
Value::Bool(false) => 0.0,
|
||||
Value::Bool(true) => 1.0,
|
||||
Value::Number(v) => *v,
|
||||
Value::String(v) => v.parse().unwrap_or(NAN), // TODO(Herschel): Handle Infinity/etc.?
|
||||
Value::String(v) => match v.as_str() {
|
||||
v if v.starts_with("0x") => {
|
||||
let parsed = i64::from_str_radix(&v[2..], 16);
|
||||
if parsed.is_ok() {
|
||||
parsed.unwrap_or_default() as f64
|
||||
} else {
|
||||
std::f64::NAN
|
||||
}
|
||||
}
|
||||
"" => 0.0,
|
||||
_ => v.parse().unwrap_or(NAN),
|
||||
},
|
||||
Value::Object(_object) => {
|
||||
log::error!("Unimplemented: Object ToNumber");
|
||||
0.0
|
||||
|
|
Loading…
Reference in New Issue