From 796c641b3b6b19c50c95a12c27125e36501e0555 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Mon, 21 Oct 2019 12:30:59 +0200 Subject: [PATCH 1/8] chore: Impl From for Value, better dev ergonomics --- core/src/avm1.rs | 26 +++++++-------- core/src/avm1/globals.rs | 72 ++++++++++++++++++++-------------------- core/src/avm1/object.rs | 48 +++++++++++++-------------- core/src/avm1/value.rs | 6 ++++ 4 files changed, 79 insertions(+), 73 deletions(-) diff --git a/core/src/avm1.rs b/core/src/avm1.rs index eac6d6841..17ca77e61 100644 --- a/core/src/avm1.rs +++ b/core/src/avm1.rs @@ -559,10 +559,10 @@ impl<'gc> Avm1<'gc> { if let Value::String(a) = a { let mut s = b.into_string(); s.push_str(&a); - self.push(Value::String(s)); + self.push(s); } else if let Value::String(mut b) = b { b.push_str(&a.into_string()); - self.push(Value::String(b)); + self.push(b); } else { self.push(Value::Number(b.as_number() + a.as_number())); } @@ -581,7 +581,7 @@ impl<'gc> Avm1<'gc> { fn action_ascii_to_char(&mut self, _context: &mut ActionContext) -> Result<(), Error> { // TODO(Herschel): Results on incorrect operands? let val = (self.pop()?.as_f64()? as u8) as char; - self.push(Value::String(val.to_string())); + self.push(val.to_string()); Ok(()) } @@ -919,7 +919,7 @@ impl<'gc> Avm1<'gc> { }; for k in ob.read().get_keys() { - self.push(Value::String(k)); + self.push(k); } Ok(()) @@ -1289,7 +1289,7 @@ impl<'gc> Avm1<'gc> { // TODO(Herschel): Results on incorrect operands? use std::convert::TryFrom; let val = char::try_from(self.pop()?.as_f64()? as u32)?; - self.push(Value::String(val.to_string())); + self.push(val.to_string()); Ok(()) } @@ -1307,7 +1307,7 @@ impl<'gc> Avm1<'gc> { let start = self.pop()?.as_f64()? as usize; let s = self.pop()?.into_string(); let result = s[len..len + start].to_string(); // TODO(Herschel): Flash uses UTF-16 internally. - self.push(Value::String(result)); + self.push(result); Ok(()) } @@ -1432,11 +1432,11 @@ impl<'gc> Avm1<'gc> { SwfValue::Int(v) => Value::Number(f64::from(*v)), SwfValue::Float(v) => Value::Number(f64::from(*v)), SwfValue::Double(v) => Value::Number(*v), - SwfValue::Str(v) => Value::String(v.to_string()), + SwfValue::Str(v) => v.to_string().into(), SwfValue::Register(v) => self.current_register(*v), SwfValue::ConstantPool(i) => { if let Some(value) = self.constant_pool.get(*i as usize) { - Value::String(value.to_string()) + value.to_string().into() } else { log::warn!( "ActionPush: Constant pool index {} out of range (len = {})", @@ -1593,13 +1593,13 @@ impl<'gc> Avm1<'gc> { if target.is_empty() { context.active_clip = context.start_clip; context.target_clip = Some(context.start_clip); - context.target_path = Value::String(target.to_string()); + context.target_path = target.to_string().into(); } else if let Some(clip) = Avm1::resolve_slash_path(context.start_clip, context.root, target) { context.target_clip = Some(clip); context.active_clip = clip; - context.target_path = Value::String(target.to_string()); + context.target_path = target.to_string().into(); } else { log::warn!("SetTarget failed: {} not found", target); // TODO: Emulate AVM1 trace error message. @@ -1701,7 +1701,7 @@ impl<'gc> Avm1<'gc> { let a = self.pop()?.into_string(); let mut b = self.pop()?.into_string(); b.push_str(&a); - self.push(Value::String(b)); + self.push(b); Ok(()) } @@ -1731,7 +1731,7 @@ impl<'gc> Avm1<'gc> { .take(len) .map(|c| c as char) .collect::(); - self.push(Value::String(result)); + self.push(result); Ok(()) } @@ -1806,7 +1806,7 @@ impl<'gc> Avm1<'gc> { fn action_to_string(&mut self, _context: &mut ActionContext) -> Result<(), Error> { let val = self.pop()?; - self.push(Value::String(val.into_string())); + self.push(val.into_string()); Ok(()) } diff --git a/core/src/avm1/globals.rs b/core/src/avm1/globals.rs index e9fd750f8..2dab56910 100644 --- a/core/src/avm1/globals.rs +++ b/core/src/avm1/globals.rs @@ -144,11 +144,11 @@ mod tests { &[Value::Number(0.0)] => Value::Bool(false), &[Value::Number(std::f64::INFINITY)] => Value::Bool(true), &[Value::Number(std::f64::NAN)] => Value::Bool(false), - &[Value::String("".to_string())] => Value::Bool(false), - &[Value::String("Hello".to_string())] => Value::Bool(true), - &[Value::String(" ".to_string())] => Value::Bool(true), - &[Value::String("0".to_string())] => Value::Bool(true), - &[Value::String("1".to_string())] => Value::Bool(true), + &["".to_string().into()] => Value::Bool(false), + &["Hello".to_string().into()] => Value::Bool(true), + &[" ".to_string().into()] => Value::Bool(true), + &["0".to_string().into()] => Value::Bool(true), + &["1".to_string().into()] => Value::Bool(true), &[] => Value::Bool(false) ); @@ -160,11 +160,11 @@ mod tests { &[Value::Number(0.0)] => Value::Bool(false), &[Value::Number(std::f64::INFINITY)] => Value::Bool(true), &[Value::Number(std::f64::NAN)] => Value::Bool(false), - &[Value::String("".to_string())] => Value::Bool(false), - &[Value::String("Hello".to_string())] => Value::Bool(false), - &[Value::String(" ".to_string())] => Value::Bool(false), - &[Value::String("0".to_string())] => Value::Bool(false), - &[Value::String("1".to_string())] => Value::Bool(true), + &["".to_string().into()] => Value::Bool(false), + &["Hello".to_string().into()] => Value::Bool(false), + &[" ".to_string().into()] => Value::Bool(false), + &["0".to_string().into()] => Value::Bool(false), + &["1".to_string().into()] => Value::Bool(true), &[] => Value::Bool(false) ); @@ -176,19 +176,19 @@ mod tests { &[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("0x1999999981ffffff".to_string())] => Value::Bool(false), - &[Value::String("0xUIXUIDFKHJDF012345678".to_string())] => Value::Bool(true), - &[Value::String("123e-1".to_string())] => Value::Bool(false), + &["".to_string().into()] => Value::Bool(false), + &["Hello".to_string().into()] => Value::Bool(true), + &[" ".to_string().into()] => Value::Bool(true), + &[" 5 ".to_string().into()] => Value::Bool(true), + &["0".to_string().into()] => Value::Bool(false), + &["1".to_string().into()] => Value::Bool(false), + &["Infinity".to_string().into()] => Value::Bool(true), + &["100a".to_string().into()] => Value::Bool(true), + &["0x10".to_string().into()] => Value::Bool(false), + &["0xhello".to_string().into()] => Value::Bool(true), + &["0x1999999981ffffff".to_string().into()] => Value::Bool(false), + &["0xUIXUIDFKHJDF012345678".to_string().into()] => Value::Bool(true), + &["123e-1".to_string().into()] => Value::Bool(false), &[] => Value::Bool(true) ); @@ -200,19 +200,19 @@ mod tests { &[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::String("0x1999999981ffffff".to_string())] => Value::Number(-2113929217.0), - &[Value::String("0xUIXUIDFKHJDF012345678".to_string())] => Value::Number(std::f64::NAN), + &["".to_string().into()] => Value::Number(0.0), + &["Hello".to_string().into()] => Value::Number(std::f64::NAN), + &[" ".to_string().into()] => Value::Number(std::f64::NAN), + &[" 5 ".to_string().into()] => Value::Number(std::f64::NAN), + &["0".to_string().into()] => Value::Number(0.0), + &["1".to_string().into()] => Value::Number(1.0), + &["Infinity".to_string().into()] => Value::Number(std::f64::NAN), + &["100a".to_string().into()] => Value::Number(std::f64::NAN), + &["0x10".to_string().into()] => Value::Number(16.0), + &["0xhello".to_string().into()] => Value::Number(std::f64::NAN), + &["123e-1".to_string().into()] => Value::Number(12.3), + &["0x1999999981ffffff".to_string().into()] => Value::Number(-2113929217.0), + &["0xUIXUIDFKHJDF012345678".to_string().into()] => Value::Number(std::f64::NAN), &[] => Value::Number(0.0) ); } diff --git a/core/src/avm1/object.rs b/core/src/avm1/object.rs index bfe141543..9b22ea57c 100644 --- a/core/src/avm1/object.rs +++ b/core/src/avm1/object.rs @@ -19,7 +19,7 @@ fn default_to_string<'gc>( _: GcCell<'gc, Object<'gc>>, _: &[Value<'gc>], ) -> Value<'gc> { - Value::String("[Object object]".to_string()) + "[Object object]".to_string().into() } #[derive(EnumSetType, Debug)] @@ -434,12 +434,12 @@ mod tests { with_object(0, |avm, context, object| { object.write(context.gc_context).force_set( "forced", - Value::String("forced".to_string()), + "forced".to_string().into(), EnumSet::empty(), ); object.write(context.gc_context).set( "natural", - Value::String("natural".to_string()), + "natural".to_string().into(), avm, context, object, @@ -447,11 +447,11 @@ mod tests { assert_eq!( object.read().get("forced", avm, context, object), - Value::String("forced".to_string()) + "forced".to_string().into() ); assert_eq!( object.read().get("natural", avm, context, object), - Value::String("natural".to_string()) + "natural".to_string().into() ); }) } @@ -461,25 +461,25 @@ mod tests { with_object(0, |avm, context, object| { object.write(context.gc_context).force_set( "normal", - Value::String("initial".to_string()), + "initial".to_string().into(), EnumSet::empty(), ); object.write(context.gc_context).force_set( "readonly", - Value::String("initial".to_string()), + "initial".to_string().into(), ReadOnly, ); object.write(context.gc_context).set( "normal", - Value::String("replaced".to_string()), + "replaced".to_string().into(), avm, context, object, ); object.write(context.gc_context).set( "readonly", - Value::String("replaced".to_string()), + "replaced".to_string().into(), avm, context, object, @@ -487,11 +487,11 @@ mod tests { assert_eq!( object.read().get("normal", avm, context, object), - Value::String("replaced".to_string()) + "replaced".to_string().into() ); assert_eq!( object.read().get("readonly", avm, context, object), - Value::String("initial".to_string()) + "initial".to_string().into() ); }) } @@ -501,19 +501,19 @@ mod tests { with_object(0, |avm, context, object| { object.write(context.gc_context).force_set( "test", - Value::String("initial".to_string()), + "initial".to_string().into(), DontDelete, ); assert_eq!(object.write(context.gc_context).delete("test"), false); assert_eq!( object.read().get("test", avm, context, object), - Value::String("initial".to_string()) + "initial".to_string().into() ); object.write(context.gc_context).set( "test", - Value::String("replaced".to_string()), + "replaced".to_string().into(), avm, context, object, @@ -522,7 +522,7 @@ mod tests { assert_eq!(object.write(context.gc_context).delete("test"), false); assert_eq!( object.read().get("test", avm, context, object), - Value::String("replaced".to_string()) + "replaced".to_string().into() ); }) } @@ -531,7 +531,7 @@ mod tests { fn test_virtual_get() { with_object(0, |avm, context, object| { let getter: NativeFunction = - |_avm, _context, _this, _args| Value::String("Virtual!".to_string()); + |_avm, _context, _this, _args| "Virtual!".to_string().into(); object.write(context.gc_context).force_set_virtual( "test", getter, @@ -541,20 +541,20 @@ mod tests { assert_eq!( object.read().get("test", avm, context, object), - Value::String("Virtual!".to_string()) + "Virtual!".to_string().into() ); // This set should do nothing object.write(context.gc_context).set( "test", - Value::String("Ignored!".to_string()), + "Ignored!".to_string().into(), avm, context, object, ); assert_eq!( object.read().get("test", avm, context, object), - Value::String("Virtual!".to_string()) + "Virtual!".to_string().into() ); }) } @@ -563,7 +563,7 @@ mod tests { fn test_delete() { with_object(0, |avm, context, object| { let getter: NativeFunction = - |_avm, _context, _this, _args| Value::String("Virtual!".to_string()); + |_avm, _context, _this, _args| "Virtual!".to_string().into(); object.write(context.gc_context).force_set_virtual( "virtual", @@ -579,12 +579,12 @@ mod tests { ); object.write(context.gc_context).force_set( "stored", - Value::String("Stored!".to_string()), + "Stored!".to_string().into(), EnumSet::empty(), ); object.write(context.gc_context).force_set( "stored_un", - Value::String("Stored!".to_string()), + "Stored!".to_string().into(), DontDelete, ); @@ -603,7 +603,7 @@ mod tests { ); assert_eq!( object.read().get("virtual_un", avm, context, object), - Value::String("Virtual!".to_string()) + "Virtual!".to_string().into() ); assert_eq!( object.read().get("stored", avm, context, object), @@ -611,7 +611,7 @@ mod tests { ); assert_eq!( object.read().get("stored_un", avm, context, object), - Value::String("Stored!".to_string()) + "Stored!".to_string().into() ); }) } diff --git a/core/src/avm1/value.rs b/core/src/avm1/value.rs index 35ba66360..67fa11ed8 100644 --- a/core/src/avm1/value.rs +++ b/core/src/avm1/value.rs @@ -13,6 +13,12 @@ pub enum Value<'gc> { Object(GcCell<'gc, Object<'gc>>), } +impl<'gc> From for Value<'gc> { + fn from(string: String) -> Self { + Value::String(string) + } +} + unsafe impl<'gc> gc_arena::Collect for Value<'gc> { fn trace(&self, cc: gc_arena::CollectionContext) { if let Value::Object(object) = self { From f24ab37810e25b05d24dd5284e4e1abd8e0cb886 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Mon, 21 Oct 2019 12:33:49 +0200 Subject: [PATCH 2/8] chore: Impl From<&str> for Value, better dev ergonomics --- core/src/avm1.rs | 4 +-- core/src/avm1/globals.rs | 72 ++++++++++++++++++++-------------------- core/src/avm1/object.rs | 48 +++++++++++++-------------- core/src/avm1/value.rs | 6 ++++ 4 files changed, 68 insertions(+), 62 deletions(-) diff --git a/core/src/avm1.rs b/core/src/avm1.rs index 17ca77e61..857217e3b 100644 --- a/core/src/avm1.rs +++ b/core/src/avm1.rs @@ -1593,13 +1593,13 @@ impl<'gc> Avm1<'gc> { if target.is_empty() { context.active_clip = context.start_clip; context.target_clip = Some(context.start_clip); - context.target_path = target.to_string().into(); + context.target_path = target.into(); } else if let Some(clip) = Avm1::resolve_slash_path(context.start_clip, context.root, target) { context.target_clip = Some(clip); context.active_clip = clip; - context.target_path = target.to_string().into(); + context.target_path = target.into(); } else { log::warn!("SetTarget failed: {} not found", target); // TODO: Emulate AVM1 trace error message. diff --git a/core/src/avm1/globals.rs b/core/src/avm1/globals.rs index 2dab56910..c5050552c 100644 --- a/core/src/avm1/globals.rs +++ b/core/src/avm1/globals.rs @@ -144,11 +144,11 @@ mod tests { &[Value::Number(0.0)] => Value::Bool(false), &[Value::Number(std::f64::INFINITY)] => Value::Bool(true), &[Value::Number(std::f64::NAN)] => Value::Bool(false), - &["".to_string().into()] => Value::Bool(false), - &["Hello".to_string().into()] => Value::Bool(true), - &[" ".to_string().into()] => Value::Bool(true), - &["0".to_string().into()] => Value::Bool(true), - &["1".to_string().into()] => Value::Bool(true), + &["".into()] => Value::Bool(false), + &["Hello".into()] => Value::Bool(true), + &[" ".into()] => Value::Bool(true), + &["0".into()] => Value::Bool(true), + &["1".into()] => Value::Bool(true), &[] => Value::Bool(false) ); @@ -160,11 +160,11 @@ mod tests { &[Value::Number(0.0)] => Value::Bool(false), &[Value::Number(std::f64::INFINITY)] => Value::Bool(true), &[Value::Number(std::f64::NAN)] => Value::Bool(false), - &["".to_string().into()] => Value::Bool(false), - &["Hello".to_string().into()] => Value::Bool(false), - &[" ".to_string().into()] => Value::Bool(false), - &["0".to_string().into()] => Value::Bool(false), - &["1".to_string().into()] => Value::Bool(true), + &["".into()] => Value::Bool(false), + &["Hello".into()] => Value::Bool(false), + &[" ".into()] => Value::Bool(false), + &["0".into()] => Value::Bool(false), + &["1".into()] => Value::Bool(true), &[] => Value::Bool(false) ); @@ -176,19 +176,19 @@ mod tests { &[Value::Number(0.0)] => Value::Bool(false), &[Value::Number(std::f64::INFINITY)] => Value::Bool(false), &[Value::Number(std::f64::NAN)] => Value::Bool(true), - &["".to_string().into()] => Value::Bool(false), - &["Hello".to_string().into()] => Value::Bool(true), - &[" ".to_string().into()] => Value::Bool(true), - &[" 5 ".to_string().into()] => Value::Bool(true), - &["0".to_string().into()] => Value::Bool(false), - &["1".to_string().into()] => Value::Bool(false), - &["Infinity".to_string().into()] => Value::Bool(true), - &["100a".to_string().into()] => Value::Bool(true), - &["0x10".to_string().into()] => Value::Bool(false), - &["0xhello".to_string().into()] => Value::Bool(true), - &["0x1999999981ffffff".to_string().into()] => Value::Bool(false), - &["0xUIXUIDFKHJDF012345678".to_string().into()] => Value::Bool(true), - &["123e-1".to_string().into()] => Value::Bool(false), + &["".into()] => Value::Bool(false), + &["Hello".into()] => Value::Bool(true), + &[" ".into()] => Value::Bool(true), + &[" 5 ".into()] => Value::Bool(true), + &["0".into()] => Value::Bool(false), + &["1".into()] => Value::Bool(false), + &["Infinity".into()] => Value::Bool(true), + &["100a".into()] => Value::Bool(true), + &["0x10".into()] => Value::Bool(false), + &["0xhello".into()] => Value::Bool(true), + &["0x1999999981ffffff".into()] => Value::Bool(false), + &["0xUIXUIDFKHJDF012345678".into()] => Value::Bool(true), + &["123e-1".into()] => Value::Bool(false), &[] => Value::Bool(true) ); @@ -200,19 +200,19 @@ mod tests { &[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), - &["".to_string().into()] => Value::Number(0.0), - &["Hello".to_string().into()] => Value::Number(std::f64::NAN), - &[" ".to_string().into()] => Value::Number(std::f64::NAN), - &[" 5 ".to_string().into()] => Value::Number(std::f64::NAN), - &["0".to_string().into()] => Value::Number(0.0), - &["1".to_string().into()] => Value::Number(1.0), - &["Infinity".to_string().into()] => Value::Number(std::f64::NAN), - &["100a".to_string().into()] => Value::Number(std::f64::NAN), - &["0x10".to_string().into()] => Value::Number(16.0), - &["0xhello".to_string().into()] => Value::Number(std::f64::NAN), - &["123e-1".to_string().into()] => Value::Number(12.3), - &["0x1999999981ffffff".to_string().into()] => Value::Number(-2113929217.0), - &["0xUIXUIDFKHJDF012345678".to_string().into()] => Value::Number(std::f64::NAN), + &["".into()] => Value::Number(0.0), + &["Hello".into()] => Value::Number(std::f64::NAN), + &[" ".into()] => Value::Number(std::f64::NAN), + &[" 5 ".into()] => Value::Number(std::f64::NAN), + &["0".into()] => Value::Number(0.0), + &["1".into()] => Value::Number(1.0), + &["Infinity".into()] => Value::Number(std::f64::NAN), + &["100a".into()] => Value::Number(std::f64::NAN), + &["0x10".into()] => Value::Number(16.0), + &["0xhello".into()] => Value::Number(std::f64::NAN), + &["123e-1".into()] => Value::Number(12.3), + &["0x1999999981ffffff".into()] => Value::Number(-2113929217.0), + &["0xUIXUIDFKHJDF012345678".into()] => Value::Number(std::f64::NAN), &[] => Value::Number(0.0) ); } diff --git a/core/src/avm1/object.rs b/core/src/avm1/object.rs index 9b22ea57c..1cfe700cc 100644 --- a/core/src/avm1/object.rs +++ b/core/src/avm1/object.rs @@ -19,7 +19,7 @@ fn default_to_string<'gc>( _: GcCell<'gc, Object<'gc>>, _: &[Value<'gc>], ) -> Value<'gc> { - "[Object object]".to_string().into() + "[Object object]".into() } #[derive(EnumSetType, Debug)] @@ -434,12 +434,12 @@ mod tests { with_object(0, |avm, context, object| { object.write(context.gc_context).force_set( "forced", - "forced".to_string().into(), + "forced".into(), EnumSet::empty(), ); object.write(context.gc_context).set( "natural", - "natural".to_string().into(), + "natural".into(), avm, context, object, @@ -447,11 +447,11 @@ mod tests { assert_eq!( object.read().get("forced", avm, context, object), - "forced".to_string().into() + "forced".into() ); assert_eq!( object.read().get("natural", avm, context, object), - "natural".to_string().into() + "natural".into() ); }) } @@ -461,25 +461,25 @@ mod tests { with_object(0, |avm, context, object| { object.write(context.gc_context).force_set( "normal", - "initial".to_string().into(), + "initial".into(), EnumSet::empty(), ); object.write(context.gc_context).force_set( "readonly", - "initial".to_string().into(), + "initial".into(), ReadOnly, ); object.write(context.gc_context).set( "normal", - "replaced".to_string().into(), + "replaced".into(), avm, context, object, ); object.write(context.gc_context).set( "readonly", - "replaced".to_string().into(), + "replaced".into(), avm, context, object, @@ -487,11 +487,11 @@ mod tests { assert_eq!( object.read().get("normal", avm, context, object), - "replaced".to_string().into() + "replaced".into() ); assert_eq!( object.read().get("readonly", avm, context, object), - "initial".to_string().into() + "initial".into() ); }) } @@ -501,19 +501,19 @@ mod tests { with_object(0, |avm, context, object| { object.write(context.gc_context).force_set( "test", - "initial".to_string().into(), + "initial".into(), DontDelete, ); assert_eq!(object.write(context.gc_context).delete("test"), false); assert_eq!( object.read().get("test", avm, context, object), - "initial".to_string().into() + "initial".into() ); object.write(context.gc_context).set( "test", - "replaced".to_string().into(), + "replaced".into(), avm, context, object, @@ -522,7 +522,7 @@ mod tests { assert_eq!(object.write(context.gc_context).delete("test"), false); assert_eq!( object.read().get("test", avm, context, object), - "replaced".to_string().into() + "replaced".into() ); }) } @@ -531,7 +531,7 @@ mod tests { fn test_virtual_get() { with_object(0, |avm, context, object| { let getter: NativeFunction = - |_avm, _context, _this, _args| "Virtual!".to_string().into(); + |_avm, _context, _this, _args| "Virtual!".into(); object.write(context.gc_context).force_set_virtual( "test", getter, @@ -541,20 +541,20 @@ mod tests { assert_eq!( object.read().get("test", avm, context, object), - "Virtual!".to_string().into() + "Virtual!".into() ); // This set should do nothing object.write(context.gc_context).set( "test", - "Ignored!".to_string().into(), + "Ignored!".into(), avm, context, object, ); assert_eq!( object.read().get("test", avm, context, object), - "Virtual!".to_string().into() + "Virtual!".into() ); }) } @@ -563,7 +563,7 @@ mod tests { fn test_delete() { with_object(0, |avm, context, object| { let getter: NativeFunction = - |_avm, _context, _this, _args| "Virtual!".to_string().into(); + |_avm, _context, _this, _args| "Virtual!".into(); object.write(context.gc_context).force_set_virtual( "virtual", @@ -579,12 +579,12 @@ mod tests { ); object.write(context.gc_context).force_set( "stored", - "Stored!".to_string().into(), + "Stored!".into(), EnumSet::empty(), ); object.write(context.gc_context).force_set( "stored_un", - "Stored!".to_string().into(), + "Stored!".into(), DontDelete, ); @@ -603,7 +603,7 @@ mod tests { ); assert_eq!( object.read().get("virtual_un", avm, context, object), - "Virtual!".to_string().into() + "Virtual!".into() ); assert_eq!( object.read().get("stored", avm, context, object), @@ -611,7 +611,7 @@ mod tests { ); assert_eq!( object.read().get("stored_un", avm, context, object), - "Stored!".to_string().into() + "Stored!".into() ); }) } diff --git a/core/src/avm1/value.rs b/core/src/avm1/value.rs index 67fa11ed8..9696bbef4 100644 --- a/core/src/avm1/value.rs +++ b/core/src/avm1/value.rs @@ -19,6 +19,12 @@ impl<'gc> From for Value<'gc> { } } +impl<'gc> From<&str> for Value<'gc> { + fn from(string: &str) -> Self { + Value::String(string.to_owned()) + } +} + unsafe impl<'gc> gc_arena::Collect for Value<'gc> { fn trace(&self, cc: gc_arena::CollectionContext) { if let Value::Object(object) = self { From 0ba9cef2f0de2e0eca2801cdba193cf02d08fb1a Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Mon, 21 Oct 2019 12:44:21 +0200 Subject: [PATCH 3/8] chore: Take Into for tests --- core/src/avm1/globals.rs | 145 ++++++++++++++++++---------------- core/src/avm1/globals/math.rs | 107 +++++++++++++------------ 2 files changed, 131 insertions(+), 121 deletions(-) diff --git a/core/src/avm1/globals.rs b/core/src/avm1/globals.rs index c5050552c..22a072d1f 100644 --- a/core/src/avm1/globals.rs +++ b/core/src/avm1/globals.rs @@ -121,13 +121,18 @@ mod tests { use crate::avm1::Error; macro_rules! test_std { - ( $test: ident, $fun: expr, $version: expr, $($args: expr => $out: expr),* ) => { + ( $test: ident, $fun: expr, $version: expr, $([$($arg: expr),*] => $out: expr),* ) => { #[test] fn $test() -> Result<(), Error> { with_avm($version, |avm, context, this| { $( - assert_eq!($fun(avm, context, this, $args), $out); + #[allow(unused_mut)] + let mut args: Vec = Vec::new(); + $( + args.push($arg.into()); + )* + assert_eq!($fun(avm, context, this, &args), $out); )* Ok(()) @@ -137,82 +142,82 @@ mod tests { } test_std!(boolean_function, boolean, 19, - &[Value::Bool(true)] => Value::Bool(true), - &[Value::Bool(false)] => Value::Bool(false), - &[Value::Number(10.0)] => Value::Bool(true), - &[Value::Number(-10.0)] => Value::Bool(true), - &[Value::Number(0.0)] => Value::Bool(false), - &[Value::Number(std::f64::INFINITY)] => Value::Bool(true), - &[Value::Number(std::f64::NAN)] => Value::Bool(false), - &["".into()] => Value::Bool(false), - &["Hello".into()] => Value::Bool(true), - &[" ".into()] => Value::Bool(true), - &["0".into()] => Value::Bool(true), - &["1".into()] => Value::Bool(true), - &[] => Value::Bool(false) + [Value::Bool(true)] => Value::Bool(true), + [Value::Bool(false)] => Value::Bool(false), + [Value::Number(10.0)] => Value::Bool(true), + [Value::Number(-10.0)] => Value::Bool(true), + [Value::Number(0.0)] => Value::Bool(false), + [Value::Number(std::f64::INFINITY)] => Value::Bool(true), + [Value::Number(std::f64::NAN)] => Value::Bool(false), + [""] => Value::Bool(false), + ["Hello"] => Value::Bool(true), + [" "] => Value::Bool(true), + ["0"] => Value::Bool(true), + ["1"] => Value::Bool(true), + [] => Value::Bool(false) ); test_std!(boolean_function_swf6, boolean, 6, - &[Value::Bool(true)] => Value::Bool(true), - &[Value::Bool(false)] => Value::Bool(false), - &[Value::Number(10.0)] => Value::Bool(true), - &[Value::Number(-10.0)] => Value::Bool(true), - &[Value::Number(0.0)] => Value::Bool(false), - &[Value::Number(std::f64::INFINITY)] => Value::Bool(true), - &[Value::Number(std::f64::NAN)] => Value::Bool(false), - &["".into()] => Value::Bool(false), - &["Hello".into()] => Value::Bool(false), - &[" ".into()] => Value::Bool(false), - &["0".into()] => Value::Bool(false), - &["1".into()] => Value::Bool(true), - &[] => Value::Bool(false) + [Value::Bool(true)] => Value::Bool(true), + [Value::Bool(false)] => Value::Bool(false), + [Value::Number(10.0)] => Value::Bool(true), + [Value::Number(-10.0)] => Value::Bool(true), + [Value::Number(0.0)] => Value::Bool(false), + [Value::Number(std::f64::INFINITY)] => Value::Bool(true), + [Value::Number(std::f64::NAN)] => Value::Bool(false), + [""] => Value::Bool(false), + ["Hello"] => Value::Bool(false), + [" "] => Value::Bool(false), + ["0"] => Value::Bool(false), + ["1"] => Value::Bool(true), + [] => 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), - &["".into()] => Value::Bool(false), - &["Hello".into()] => Value::Bool(true), - &[" ".into()] => Value::Bool(true), - &[" 5 ".into()] => Value::Bool(true), - &["0".into()] => Value::Bool(false), - &["1".into()] => Value::Bool(false), - &["Infinity".into()] => Value::Bool(true), - &["100a".into()] => Value::Bool(true), - &["0x10".into()] => Value::Bool(false), - &["0xhello".into()] => Value::Bool(true), - &["0x1999999981ffffff".into()] => Value::Bool(false), - &["0xUIXUIDFKHJDF012345678".into()] => Value::Bool(true), - &["123e-1".into()] => Value::Bool(false), - &[] => Value::Bool(true) + [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::Bool(false), + ["Hello"] => Value::Bool(true), + [" "] => Value::Bool(true), + [" 5 "] => Value::Bool(true), + ["0"] => Value::Bool(false), + ["1"] => Value::Bool(false), + ["Infinity"] => Value::Bool(true), + ["100a"] => Value::Bool(true), + ["0x10"] => Value::Bool(false), + ["0xhello"] => Value::Bool(true), + ["0x1999999981ffffff"] => Value::Bool(false), + ["0xUIXUIDFKHJDF012345678"] => Value::Bool(true), + ["123e-1"] => 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), - &["".into()] => Value::Number(0.0), - &["Hello".into()] => Value::Number(std::f64::NAN), - &[" ".into()] => Value::Number(std::f64::NAN), - &[" 5 ".into()] => Value::Number(std::f64::NAN), - &["0".into()] => Value::Number(0.0), - &["1".into()] => Value::Number(1.0), - &["Infinity".into()] => Value::Number(std::f64::NAN), - &["100a".into()] => Value::Number(std::f64::NAN), - &["0x10".into()] => Value::Number(16.0), - &["0xhello".into()] => Value::Number(std::f64::NAN), - &["123e-1".into()] => Value::Number(12.3), - &["0x1999999981ffffff".into()] => Value::Number(-2113929217.0), - &["0xUIXUIDFKHJDF012345678".into()] => Value::Number(std::f64::NAN), - &[] => Value::Number(0.0) + [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::Number(0.0), + ["Hello"] => Value::Number(std::f64::NAN), + [" "] => Value::Number(std::f64::NAN), + [" 5 "] => Value::Number(std::f64::NAN), + ["0"] => Value::Number(0.0), + ["1"] => Value::Number(1.0), + ["Infinity"] => Value::Number(std::f64::NAN), + ["100a"] => Value::Number(std::f64::NAN), + ["0x10"] => Value::Number(16.0), + ["0xhello"] => Value::Number(std::f64::NAN), + ["123e-1"] => Value::Number(12.3), + ["0x1999999981ffffff"] => Value::Number(-2113929217.0), + ["0xUIXUIDFKHJDF012345678"] => Value::Number(std::f64::NAN), + [] => Value::Number(0.0) ); } diff --git a/core/src/avm1/globals/math.rs b/core/src/avm1/globals/math.rs index dc8ca5b9e..781c15879 100644 --- a/core/src/avm1/globals/math.rs +++ b/core/src/avm1/globals/math.rs @@ -125,7 +125,7 @@ mod tests { use crate::avm1::Error; macro_rules! test_std { - ( $test: ident, $name: expr, $($args: expr => $out: expr),* ) => { + ( $test: ident, $name: expr, $([$($arg: expr),*] => $out: expr),* ) => { #[test] fn $test() -> Result<(), Error> { with_avm(19, |avm, context, _root| { @@ -133,7 +133,12 @@ mod tests { let function = math.read().get($name, avm, context, math); $( - assert_eq!(function.call(avm, context, math, $args)?, Some($out)); + #[allow(unused_mut)] + let mut args: Vec = Vec::new(); + $( + args.push($arg.into()); + )* + assert_eq!(function.call(avm, context, math, &args)?, Some($out)); )* Ok(()) @@ -143,88 +148,88 @@ mod tests { } test_std!(test_abs, "abs", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(-50.0)] => Value::Number(50.0), - &[Value::Number(25.0)] => Value::Number(25.0) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(-50.0)] => Value::Number(50.0), + [Value::Number(25.0)] => Value::Number(25.0) ); test_std!(test_acos, "acos", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(-1.0)] => Value::Number(f64::acos(-1.0)), - &[Value::Number(0.0)] => Value::Number(f64::acos(0.0)), - &[Value::Number(1.0)] => Value::Number(f64::acos(1.0)) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(-1.0)] => Value::Number(f64::acos(-1.0)), + [Value::Number(0.0)] => Value::Number(f64::acos(0.0)), + [Value::Number(1.0)] => Value::Number(f64::acos(1.0)) ); test_std!(test_asin, "asin", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(-1.0)] => Value::Number(f64::asin(-1.0)), - &[Value::Number(0.0)] => Value::Number(f64::asin(0.0)), - &[Value::Number(1.0)] => Value::Number(f64::asin(1.0)) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(-1.0)] => Value::Number(f64::asin(-1.0)), + [Value::Number(0.0)] => Value::Number(f64::asin(0.0)), + [Value::Number(1.0)] => Value::Number(f64::asin(1.0)) ); test_std!(test_atan, "atan", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(-1.0)] => Value::Number(f64::atan(-1.0)), - &[Value::Number(0.0)] => Value::Number(f64::atan(0.0)), - &[Value::Number(1.0)] => Value::Number(f64::atan(1.0)) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(-1.0)] => Value::Number(f64::atan(-1.0)), + [Value::Number(0.0)] => Value::Number(f64::atan(0.0)), + [Value::Number(1.0)] => Value::Number(f64::atan(1.0)) ); test_std!(test_ceil, "ceil", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(12.5)] => Value::Number(13.0) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(12.5)] => Value::Number(13.0) ); test_std!(test_cos, "cos", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(0.0)] => Value::Number(1.0), - &[Value::Number(std::f64::consts::PI)] => Value::Number(f64::cos(std::f64::consts::PI)) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(0.0)] => Value::Number(1.0), + [Value::Number(std::f64::consts::PI)] => Value::Number(f64::cos(std::f64::consts::PI)) ); test_std!(test_exp, "exp", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(1.0)] => Value::Number(f64::exp(1.0)), - &[Value::Number(2.0)] => Value::Number(f64::exp(2.0)) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(1.0)] => Value::Number(f64::exp(1.0)), + [Value::Number(2.0)] => Value::Number(f64::exp(2.0)) ); test_std!(test_floor, "floor", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(12.5)] => Value::Number(12.0) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(12.5)] => Value::Number(12.0) ); test_std!(test_round, "round", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(12.5)] => Value::Number(13.0), - &[Value::Number(23.2)] => Value::Number(23.0) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(12.5)] => Value::Number(13.0), + [Value::Number(23.2)] => Value::Number(23.0) ); test_std!(test_sin, "sin", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(0.0)] => Value::Number(f64::sin(0.0)), - &[Value::Number(std::f64::consts::PI / 2.0)] => Value::Number(f64::sin(std::f64::consts::PI / 2.0)) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(0.0)] => Value::Number(f64::sin(0.0)), + [Value::Number(std::f64::consts::PI / 2.0)] => Value::Number(f64::sin(std::f64::consts::PI / 2.0)) ); test_std!(test_sqrt, "sqrt", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(0.0)] => Value::Number(f64::sqrt(0.0)), - &[Value::Number(5.0)] => Value::Number(f64::sqrt(5.0)) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(0.0)] => Value::Number(f64::sqrt(0.0)), + [Value::Number(5.0)] => Value::Number(f64::sqrt(5.0)) ); test_std!(test_tan, "tan", - &[] => Value::Number(NAN), - &[Value::Null] => Value::Number(NAN), - &[Value::Number(0.0)] => Value::Number(f64::tan(0.0)), - &[Value::Number(1.0)] => Value::Number(f64::tan(1.0)) + [] => Value::Number(NAN), + [Value::Null] => Value::Number(NAN), + [Value::Number(0.0)] => Value::Number(f64::tan(0.0)), + [Value::Number(1.0)] => Value::Number(f64::tan(1.0)) ); #[test] From 4c81ac8a6d8a2807c536bf55c313a27b83689c87 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Mon, 21 Oct 2019 12:48:18 +0200 Subject: [PATCH 4/8] chore: Take Into for Object.(force_)set --- core/src/avm1/object.rs | 118 ++++++++++++++-------------------------- 1 file changed, 42 insertions(+), 76 deletions(-) diff --git a/core/src/avm1/object.rs b/core/src/avm1/object.rs index 1cfe700cc..aeb01762e 100644 --- a/core/src/avm1/object.rs +++ b/core/src/avm1/object.rs @@ -60,19 +60,19 @@ impl<'gc> Property<'gc> { avm: &mut Avm1<'gc>, context: &mut ActionContext<'_, 'gc, '_>, this: GcCell<'gc, Object<'gc>>, - new_value: Value<'gc>, + new_value: impl Into>, ) { match self { Property::Virtual { set, .. } => { if let Some(function) = set { - function(avm, context, this, &[new_value]); + function(avm, context, this, &[new_value.into()]); } } Property::Stored { value, attributes, .. } => { if !attributes.contains(ReadOnly) { - replace::>(value, new_value); + replace::>(value, new_value.into()); } } } @@ -214,7 +214,7 @@ impl<'gc> Object<'gc> { pub fn set( &mut self, name: &str, - value: Value<'gc>, + value: impl Into>, avm: &mut Avm1<'gc>, context: &mut ActionContext<'_, 'gc, '_>, this: GcCell<'gc, Object<'gc>>, @@ -225,7 +225,7 @@ impl<'gc> Object<'gc> { } Entry::Vacant(entry) => { entry.insert(Property::Stored { - value, + value: value.into(), attributes: Default::default(), }); } @@ -251,14 +251,14 @@ impl<'gc> Object<'gc> { ); } - pub fn force_set(&mut self, name: &str, value: Value<'gc>, attributes: A) + pub fn force_set(&mut self, name: &str, value: impl Into>, attributes: A) where A: Into>, { self.values.insert( name.to_string(), Property::Stored { - value, + value: value.into(), attributes: attributes.into(), }, ); @@ -432,18 +432,12 @@ mod tests { #[test] fn test_set_get() { with_object(0, |avm, context, object| { - object.write(context.gc_context).force_set( - "forced", - "forced".into(), - EnumSet::empty(), - ); - object.write(context.gc_context).set( - "natural", - "natural".into(), - avm, - context, - object, - ); + object + .write(context.gc_context) + .force_set("forced", "forced", EnumSet::empty()); + object + .write(context.gc_context) + .set("natural", "natural", avm, context, object); assert_eq!( object.read().get("forced", avm, context, object), @@ -459,31 +453,19 @@ mod tests { #[test] fn test_set_readonly() { with_object(0, |avm, context, object| { - object.write(context.gc_context).force_set( - "normal", - "initial".into(), - EnumSet::empty(), - ); - object.write(context.gc_context).force_set( - "readonly", - "initial".into(), - ReadOnly, - ); + object + .write(context.gc_context) + .force_set("normal", "initial", EnumSet::empty()); + object + .write(context.gc_context) + .force_set("readonly", "initial", ReadOnly); - object.write(context.gc_context).set( - "normal", - "replaced".into(), - avm, - context, - object, - ); - object.write(context.gc_context).set( - "readonly", - "replaced".into(), - avm, - context, - object, - ); + object + .write(context.gc_context) + .set("normal", "replaced", avm, context, object); + object + .write(context.gc_context) + .set("readonly", "replaced", avm, context, object); assert_eq!( object.read().get("normal", avm, context, object), @@ -499,11 +481,9 @@ mod tests { #[test] fn test_deletable_not_readonly() { with_object(0, |avm, context, object| { - object.write(context.gc_context).force_set( - "test", - "initial".into(), - DontDelete, - ); + object + .write(context.gc_context) + .force_set("test", "initial", DontDelete); assert_eq!(object.write(context.gc_context).delete("test"), false); assert_eq!( @@ -511,13 +491,9 @@ mod tests { "initial".into() ); - object.write(context.gc_context).set( - "test", - "replaced".into(), - avm, - context, - object, - ); + object + .write(context.gc_context) + .set("test", "replaced", avm, context, object); assert_eq!(object.write(context.gc_context).delete("test"), false); assert_eq!( @@ -530,8 +506,7 @@ mod tests { #[test] fn test_virtual_get() { with_object(0, |avm, context, object| { - let getter: NativeFunction = - |_avm, _context, _this, _args| "Virtual!".into(); + let getter: NativeFunction = |_avm, _context, _this, _args| "Virtual!".into(); object.write(context.gc_context).force_set_virtual( "test", getter, @@ -545,13 +520,9 @@ mod tests { ); // This set should do nothing - object.write(context.gc_context).set( - "test", - "Ignored!".into(), - avm, - context, - object, - ); + object + .write(context.gc_context) + .set("test", "Ignored!", avm, context, object); assert_eq!( object.read().get("test", avm, context, object), "Virtual!".into() @@ -562,8 +533,7 @@ mod tests { #[test] fn test_delete() { with_object(0, |avm, context, object| { - let getter: NativeFunction = - |_avm, _context, _this, _args| "Virtual!".into(); + let getter: NativeFunction = |_avm, _context, _this, _args| "Virtual!".into(); object.write(context.gc_context).force_set_virtual( "virtual", @@ -577,16 +547,12 @@ mod tests { None, DontDelete, ); - object.write(context.gc_context).force_set( - "stored", - "Stored!".into(), - EnumSet::empty(), - ); - object.write(context.gc_context).force_set( - "stored_un", - "Stored!".into(), - DontDelete, - ); + object + .write(context.gc_context) + .force_set("stored", "Stored!", EnumSet::empty()); + object + .write(context.gc_context) + .force_set("stored_un", "Stored!", DontDelete); assert_eq!(object.write(context.gc_context).delete("virtual"), true); assert_eq!(object.write(context.gc_context).delete("virtual_un"), false); From fa5616a4f9ebc36f12d840a19656df2a47b6b6e2 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Mon, 21 Oct 2019 12:55:17 +0200 Subject: [PATCH 5/8] chore: Impl From for Value, better dev ergonomics --- core/src/avm1.rs | 10 +++++----- core/src/avm1/globals.rs | 16 ++++++++-------- core/src/avm1/value.rs | 6 ++++++ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/core/src/avm1.rs b/core/src/avm1.rs index 857217e3b..6050185bf 100644 --- a/core/src/avm1.rs +++ b/core/src/avm1.rs @@ -858,7 +858,7 @@ impl<'gc> Avm1<'gc> { let object = self.pop()?.as_object()?; let success = object.write(context.gc_context).delete(name); - self.push(Value::Bool(success)); + self.push(success); Ok(()) } @@ -869,7 +869,7 @@ impl<'gc> Avm1<'gc> { //Fun fact: This isn't in the Adobe SWF19 spec, but this opcode returns //a boolean based on if the delete actually deleted something. - let did_exist = Value::Bool(self.current_stack_frame().unwrap().read().is_defined(name)); + let did_exist = self.current_stack_frame().unwrap().read().is_defined(name); self.current_stack_frame() .unwrap() @@ -954,7 +954,7 @@ impl<'gc> Avm1<'gc> { (Value::Number(a), Value::String(b)) => a == b.parse().unwrap_or(std::f64::NAN), _ => false, }; - self.push(Value::Bool(result)); + self.push(result); Ok(()) } @@ -1272,7 +1272,7 @@ impl<'gc> Avm1<'gc> { (a, b) => b.as_number() < a.as_number(), }; - self.push(Value::Bool(result)); + self.push(result); Ok(()) } @@ -1542,7 +1542,7 @@ impl<'gc> Avm1<'gc> { let a = self.pop()?; let b = self.pop()?; let result = a == b; - self.push(Value::Bool(result)); + self.push(result); Ok(()) } diff --git a/core/src/avm1/globals.rs b/core/src/avm1/globals.rs index 22a072d1f..a41009571 100644 --- a/core/src/avm1/globals.rs +++ b/core/src/avm1/globals.rs @@ -142,8 +142,8 @@ mod tests { } test_std!(boolean_function, boolean, 19, - [Value::Bool(true)] => Value::Bool(true), - [Value::Bool(false)] => Value::Bool(false), + [true] => Value::Bool(true), + [false] => Value::Bool(false), [Value::Number(10.0)] => Value::Bool(true), [Value::Number(-10.0)] => Value::Bool(true), [Value::Number(0.0)] => Value::Bool(false), @@ -158,8 +158,8 @@ mod tests { ); test_std!(boolean_function_swf6, boolean, 6, - [Value::Bool(true)] => Value::Bool(true), - [Value::Bool(false)] => Value::Bool(false), + [true] => Value::Bool(true), + [false] => Value::Bool(false), [Value::Number(10.0)] => Value::Bool(true), [Value::Number(-10.0)] => Value::Bool(true), [Value::Number(0.0)] => Value::Bool(false), @@ -174,8 +174,8 @@ mod tests { ); test_std!(is_nan_function, is_nan, 19, - [Value::Bool(true)] => Value::Bool(false), - [Value::Bool(false)] => Value::Bool(false), + [true] => Value::Bool(false), + [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), @@ -198,8 +198,8 @@ mod tests { ); test_std!(number_function, number, 19, - [Value::Bool(true)] => Value::Number(1.0), - [Value::Bool(false)] => Value::Number(0.0), + [true] => Value::Number(1.0), + [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), diff --git a/core/src/avm1/value.rs b/core/src/avm1/value.rs index 9696bbef4..ed10ee9fa 100644 --- a/core/src/avm1/value.rs +++ b/core/src/avm1/value.rs @@ -25,6 +25,12 @@ impl<'gc> From<&str> for Value<'gc> { } } +impl<'gc> From for Value<'gc> { + fn from(value: bool) -> Self { + Value::Bool(value) + } +} + unsafe impl<'gc> gc_arena::Collect for Value<'gc> { fn trace(&self, cc: gc_arena::CollectionContext) { if let Value::Object(object) = self { From 83b7d679ed18cbdd9a5b2b2be8a6d4d35bc59607 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Mon, 21 Oct 2019 13:00:28 +0200 Subject: [PATCH 6/8] chore: Impl From>> for Value, better dev ergonomics --- core/src/avm1.rs | 10 ++-------- core/src/avm1/activation.rs | 11 ++++++++--- core/src/avm1/function.rs | 4 ++-- core/src/avm1/globals.rs | 6 +----- core/src/avm1/object.rs | 5 +---- core/src/avm1/scope.rs | 2 +- core/src/avm1/value.rs | 6 ++++++ 7 files changed, 21 insertions(+), 23 deletions(-) diff --git a/core/src/avm1.rs b/core/src/avm1.rs index 6050185bf..336231610 100644 --- a/core/src/avm1.rs +++ b/core/src/avm1.rs @@ -774,10 +774,7 @@ impl<'gc> Avm1<'gc> { context.gc_context, ); let func = Avm1Function::from_df1(swf_version, func_data, name, params, scope); - let func_obj = Value::Object(GcCell::allocate( - context.gc_context, - Object::action_function(func), - )); + let func_obj = GcCell::allocate(context.gc_context, Object::action_function(func)); if name == "" { self.push(func_obj); } else { @@ -808,10 +805,7 @@ impl<'gc> Avm1<'gc> { context.gc_context, ); let func = Avm1Function::from_df2(swf_version, func_data, action_func, scope); - let func_obj = Value::Object(GcCell::allocate( - context.gc_context, - Object::action_function(func), - )); + let func_obj = GcCell::allocate(context.gc_context, Object::action_function(func)); if action_func.name == "" { self.push(func_obj); } else { diff --git a/core/src/avm1/activation.rs b/core/src/avm1/activation.rs index b346d449b..752b0576c 100644 --- a/core/src/avm1/activation.rs +++ b/core/src/avm1/activation.rs @@ -271,7 +271,7 @@ impl<'gc> Activation<'gc> { } /// Define a named local variable within this activation. - pub fn define(&self, name: &str, value: Value<'gc>, mc: MutationContext<'gc, '_>) { + pub fn define(&self, name: &str, value: impl Into>, mc: MutationContext<'gc, '_>) { self.scope().define(name, value, mc) } @@ -304,10 +304,15 @@ impl<'gc> Activation<'gc> { } /// Set a local register. - pub fn set_local_register(&mut self, id: u8, value: Value<'gc>, mc: MutationContext<'gc, '_>) { + pub fn set_local_register( + &mut self, + id: u8, + value: impl Into>, + mc: MutationContext<'gc, '_>, + ) { if let Some(ref mut local_registers) = self.local_registers { if let Some(r) = local_registers.write(mc).get_mut(id) { - *r = value; + *r = value.into(); } } } diff --git a/core/src/avm1/function.rs b/core/src/avm1/function.rs index 3522eb446..eb21fa2dd 100644 --- a/core/src/avm1/function.rs +++ b/core/src/avm1/function.rs @@ -219,14 +219,14 @@ impl<'gc> Executable<'gc> { if af.preload_this { //TODO: What happens if you specify both suppress and //preload for this? - frame.set_local_register(preload_r, Value::Object(this), ac.gc_context); + frame.set_local_register(preload_r, this, ac.gc_context); preload_r += 1; } if af.preload_arguments { //TODO: What happens if you specify both suppress and //preload for arguments? - frame.set_local_register(preload_r, Value::Object(argcell), ac.gc_context); + frame.set_local_register(preload_r, argcell, ac.gc_context); preload_r += 1; } diff --git a/core/src/avm1/globals.rs b/core/src/avm1/globals.rs index a41009571..05b31f0b4 100644 --- a/core/src/avm1/globals.rs +++ b/core/src/avm1/globals.rs @@ -94,11 +94,7 @@ pub fn create_globals<'gc>(gc_context: MutationContext<'gc, '_>) -> Object<'gc> 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", - Value::Object(math::create(gc_context)), - EnumSet::empty(), - ); + globals.force_set("Math", math::create(gc_context), 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()); diff --git a/core/src/avm1/object.rs b/core/src/avm1/object.rs index aeb01762e..b12f1a0c9 100644 --- a/core/src/avm1/object.rs +++ b/core/src/avm1/object.rs @@ -275,10 +275,7 @@ impl<'gc> Object<'gc> { { self.force_set( name, - Value::Object(GcCell::allocate( - gc_context, - Object::native_function(function), - )), + GcCell::allocate(gc_context, Object::native_function(function)), attributes, ) } diff --git a/core/src/avm1/scope.rs b/core/src/avm1/scope.rs index bac6de7ea..a02028ee4 100644 --- a/core/src/avm1/scope.rs +++ b/core/src/avm1/scope.rs @@ -301,7 +301,7 @@ impl<'gc> Scope<'gc> { /// stored (e.g. not virtual) properties on the lowest object in the scope /// chain. As a result, this function always force sets a property on the /// local object and does not traverse the scope chain. - pub fn define(&self, name: &str, value: Value<'gc>, mc: MutationContext<'gc, '_>) { + pub fn define(&self, name: &str, value: impl Into>, mc: MutationContext<'gc, '_>) { self.locals_mut(mc).force_set(name, value, EnumSet::empty()); } diff --git a/core/src/avm1/value.rs b/core/src/avm1/value.rs index ed10ee9fa..d8404254e 100644 --- a/core/src/avm1/value.rs +++ b/core/src/avm1/value.rs @@ -31,6 +31,12 @@ impl<'gc> From for Value<'gc> { } } +impl<'gc> From>> for Value<'gc> { + fn from(object: GcCell<'gc, Object<'gc>>) -> Self { + Value::Object(object) + } +} + unsafe impl<'gc> gc_arena::Collect for Value<'gc> { fn trace(&self, cc: gc_arena::CollectionContext) { if let Value::Object(object) = self { From 348e7f6adb90780e73db2288b2b3858439349402 Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Mon, 21 Oct 2019 16:10:10 +0200 Subject: [PATCH 7/8] chore: Impl From for Value, better dev ergonomics --- core/src/avm1.rs | 44 +++++++++++++++--------------- core/src/avm1/globals.rs | 40 ++++++++++++++-------------- core/src/avm1/globals/math.rs | 50 +++++++++++++++++------------------ core/src/avm1/value.rs | 30 +++++++++++++++++++++ 4 files changed, 97 insertions(+), 67 deletions(-) diff --git a/core/src/avm1.rs b/core/src/avm1.rs index 336231610..c4ef8fd9c 100644 --- a/core/src/avm1.rs +++ b/core/src/avm1.rs @@ -546,7 +546,7 @@ impl<'gc> Avm1<'gc> { fn action_add(&mut self, _context: &mut ActionContext) -> Result<(), Error> { let a = self.pop()?; let b = self.pop()?; - self.push(Value::Number(b.into_number_v1() + a.into_number_v1())); + self.push(b.into_number_v1() + a.into_number_v1()); Ok(()) } @@ -564,7 +564,7 @@ impl<'gc> Avm1<'gc> { b.push_str(&a.into_string()); self.push(b); } else { - self.push(Value::Number(b.as_number() + a.as_number())); + self.push(b.as_number() + a.as_number()); } Ok(()) } @@ -589,7 +589,7 @@ impl<'gc> Avm1<'gc> { // TODO(Herschel): Results on incorrect operands? let s = self.pop()?.into_string(); let result = s.bytes().nth(0).unwrap_or(0); - self.push(Value::Number(result.into())); + self.push(result); Ok(()) } @@ -606,7 +606,7 @@ impl<'gc> Avm1<'gc> { let a = self.pop()?.as_u32()?; let b = self.pop()?.as_u32()?; let result = a & b; - self.push(Value::Number(result.into())); + self.push(result); Ok(()) } @@ -614,7 +614,7 @@ impl<'gc> Avm1<'gc> { let a = self.pop()?.as_i32()? & 0b11111; // Only 5 bits used for shift count let b = self.pop()?.as_i32()?; let result = b << a; - self.push(Value::Number(result.into())); + self.push(result); Ok(()) } @@ -622,7 +622,7 @@ impl<'gc> Avm1<'gc> { let a = self.pop()?.as_u32()?; let b = self.pop()?.as_u32()?; let result = a | b; - self.push(Value::Number(result.into())); + self.push(result); Ok(()) } @@ -630,7 +630,7 @@ impl<'gc> Avm1<'gc> { let a = self.pop()?.as_i32()? & 0b11111; // Only 5 bits used for shift count let b = self.pop()?.as_i32()?; let result = b >> a; - self.push(Value::Number(result.into())); + self.push(result); Ok(()) } @@ -638,7 +638,7 @@ impl<'gc> Avm1<'gc> { let a = self.pop()?.as_u32()? & 0b11111; // Only 5 bits used for shift count let b = self.pop()?.as_u32()?; let result = b >> a; - self.push(Value::Number(result.into())); + self.push(result); Ok(()) } @@ -646,7 +646,7 @@ impl<'gc> Avm1<'gc> { let a = self.pop()?.as_u32()?; let b = self.pop()?.as_u32()?; let result = b ^ a; - self.push(Value::Number(result.into())); + self.push(result); Ok(()) } @@ -750,7 +750,7 @@ impl<'gc> Avm1<'gc> { fn action_decrement(&mut self, _context: &mut ActionContext) -> Result<(), Error> { let a = self.pop()?.as_number(); - self.push(Value::Number(a - 1.0)); + self.push(a - 1.0); Ok(()) } @@ -884,7 +884,7 @@ impl<'gc> Avm1<'gc> { // In SWF 4, the result is the string #ERROR#."" // Seems to be untrue for SWF v4, I get 1.#INF. - self.push(Value::Number(b.into_number_v1() / a.into_number_v1())); + self.push(b.into_number_v1() / a.into_number_v1()); Ok(()) } @@ -1011,7 +1011,7 @@ impl<'gc> Avm1<'gc> { } fn action_get_time(&mut self, context: &mut ActionContext) -> Result<(), Error> { - self.push(Value::Number(context.global_time as f64)); + self.push(context.global_time as f64); Ok(()) } @@ -1211,7 +1211,7 @@ impl<'gc> Avm1<'gc> { fn action_increment(&mut self, _context: &mut ActionContext) -> Result<(), Error> { let a = self.pop()?.as_number(); - self.push(Value::Number(a + 1.0)); + self.push(a + 1.0); Ok(()) } @@ -1291,7 +1291,7 @@ impl<'gc> Avm1<'gc> { // TODO(Herschel): Results on incorrect operands? let s = self.pop()?.into_string(); let result = s.chars().nth(0).unwrap_or('\0') as u32; - self.push(Value::Number(result.into())); + self.push(result); Ok(()) } @@ -1308,7 +1308,7 @@ impl<'gc> Avm1<'gc> { fn action_mb_string_length(&mut self, _context: &mut ActionContext) -> Result<(), Error> { // TODO(Herschel): Result with non-string operands? let val = self.pop()?.into_string().len(); - self.push(Value::Number(val as f64)); + self.push(val as f64); Ok(()) } @@ -1316,7 +1316,7 @@ impl<'gc> Avm1<'gc> { // AS1 multiply let a = self.pop()?; let b = self.pop()?; - self.push(Value::Number(a.into_number_v1() * b.into_number_v1())); + self.push(a.into_number_v1() * b.into_number_v1()); Ok(()) } @@ -1324,7 +1324,7 @@ impl<'gc> Avm1<'gc> { // TODO: Wrong operands? let a = self.pop()?.as_f64()?; let b = self.pop()?.as_f64()?; - self.push(Value::Number(a % b)); + self.push(a % b); Ok(()) } @@ -1457,7 +1457,7 @@ impl<'gc> Avm1<'gc> { // and the max value gets converted into an i32, so any number > 2^31 - 1 will return 0. let max = self.pop()?.into_number_v1() as i32; let val = context.rng.gen_range(0, max); - self.push(Value::Number(val.into())); + self.push(val); Ok(()) } @@ -1747,7 +1747,7 @@ impl<'gc> Avm1<'gc> { // Only returns byte length. // TODO(Herschel): Result with non-string operands? let val = self.pop()?.into_string().bytes().len() as f64; - self.push(Value::Number(val)); + self.push(val); Ok(()) } @@ -1767,7 +1767,7 @@ impl<'gc> Avm1<'gc> { fn action_subtract(&mut self, _context: &mut ActionContext) -> Result<(), Error> { let a = self.pop()?; let b = self.pop()?; - self.push(Value::Number(b.into_number_v1() - a.into_number_v1())); + self.push(b.into_number_v1() - a.into_number_v1()); Ok(()) } @@ -1788,13 +1788,13 @@ impl<'gc> Avm1<'gc> { fn action_to_integer(&mut self, _context: &mut ActionContext) -> Result<(), Error> { let val = self.pop()?; - self.push(Value::Number(val.into_number_v1().trunc())); + self.push(val.into_number_v1().trunc()); Ok(()) } fn action_to_number(&mut self, _context: &mut ActionContext) -> Result<(), Error> { let val = self.pop()?; - self.push(Value::Number(val.as_number())); + self.push(val.as_number()); Ok(()) } diff --git a/core/src/avm1/globals.rs b/core/src/avm1/globals.rs index 05b31f0b4..9b16ec889 100644 --- a/core/src/avm1/globals.rs +++ b/core/src/avm1/globals.rs @@ -140,11 +140,11 @@ mod tests { test_std!(boolean_function, boolean, 19, [true] => Value::Bool(true), [false] => Value::Bool(false), - [Value::Number(10.0)] => Value::Bool(true), - [Value::Number(-10.0)] => Value::Bool(true), - [Value::Number(0.0)] => Value::Bool(false), - [Value::Number(std::f64::INFINITY)] => Value::Bool(true), - [Value::Number(std::f64::NAN)] => Value::Bool(false), + [10.0] => Value::Bool(true), + [-10.0] => Value::Bool(true), + [0.0] => Value::Bool(false), + [std::f64::INFINITY] => Value::Bool(true), + [std::f64::NAN] => Value::Bool(false), [""] => Value::Bool(false), ["Hello"] => Value::Bool(true), [" "] => Value::Bool(true), @@ -156,11 +156,11 @@ mod tests { test_std!(boolean_function_swf6, boolean, 6, [true] => Value::Bool(true), [false] => Value::Bool(false), - [Value::Number(10.0)] => Value::Bool(true), - [Value::Number(-10.0)] => Value::Bool(true), - [Value::Number(0.0)] => Value::Bool(false), - [Value::Number(std::f64::INFINITY)] => Value::Bool(true), - [Value::Number(std::f64::NAN)] => Value::Bool(false), + [10.0] => Value::Bool(true), + [-10.0] => Value::Bool(true), + [0.0] => Value::Bool(false), + [std::f64::INFINITY] => Value::Bool(true), + [std::f64::NAN] => Value::Bool(false), [""] => Value::Bool(false), ["Hello"] => Value::Bool(false), [" "] => Value::Bool(false), @@ -172,11 +172,11 @@ mod tests { test_std!(is_nan_function, is_nan, 19, [true] => Value::Bool(false), [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), + [10.0] => Value::Bool(false), + [-10.0] => Value::Bool(false), + [0.0] => Value::Bool(false), + [std::f64::INFINITY] => Value::Bool(false), + [std::f64::NAN] => Value::Bool(true), [""] => Value::Bool(false), ["Hello"] => Value::Bool(true), [" "] => Value::Bool(true), @@ -196,11 +196,11 @@ mod tests { test_std!(number_function, number, 19, [true] => Value::Number(1.0), [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), + [10.0] => Value::Number(10.0), + [-10.0] => Value::Number(-10.0), + [0.0] => Value::Number(0.0), + [std::f64::INFINITY] => Value::Number(std::f64::INFINITY), + [std::f64::NAN] => Value::Number(std::f64::NAN), [""] => Value::Number(0.0), ["Hello"] => Value::Number(std::f64::NAN), [" "] => Value::Number(std::f64::NAN), diff --git a/core/src/avm1/globals/math.rs b/core/src/avm1/globals/math.rs index 781c15879..695787357 100644 --- a/core/src/avm1/globals/math.rs +++ b/core/src/avm1/globals/math.rs @@ -150,86 +150,86 @@ mod tests { test_std!(test_abs, "abs", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(-50.0)] => Value::Number(50.0), - [Value::Number(25.0)] => Value::Number(25.0) + [-50.0] => Value::Number(50.0), + [25.0] => Value::Number(25.0) ); test_std!(test_acos, "acos", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(-1.0)] => Value::Number(f64::acos(-1.0)), - [Value::Number(0.0)] => Value::Number(f64::acos(0.0)), - [Value::Number(1.0)] => Value::Number(f64::acos(1.0)) + [-1.0] => Value::Number(f64::acos(-1.0)), + [0.0] => Value::Number(f64::acos(0.0)), + [1.0] => Value::Number(f64::acos(1.0)) ); test_std!(test_asin, "asin", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(-1.0)] => Value::Number(f64::asin(-1.0)), - [Value::Number(0.0)] => Value::Number(f64::asin(0.0)), - [Value::Number(1.0)] => Value::Number(f64::asin(1.0)) + [-1.0] => Value::Number(f64::asin(-1.0)), + [0.0] => Value::Number(f64::asin(0.0)), + [1.0] => Value::Number(f64::asin(1.0)) ); test_std!(test_atan, "atan", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(-1.0)] => Value::Number(f64::atan(-1.0)), - [Value::Number(0.0)] => Value::Number(f64::atan(0.0)), - [Value::Number(1.0)] => Value::Number(f64::atan(1.0)) + [-1.0] => Value::Number(f64::atan(-1.0)), + [0.0] => Value::Number(f64::atan(0.0)), + [1.0] => Value::Number(f64::atan(1.0)) ); test_std!(test_ceil, "ceil", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(12.5)] => Value::Number(13.0) + [12.5] => Value::Number(13.0) ); test_std!(test_cos, "cos", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(0.0)] => Value::Number(1.0), - [Value::Number(std::f64::consts::PI)] => Value::Number(f64::cos(std::f64::consts::PI)) + [0.0] => Value::Number(1.0), + [std::f64::consts::PI] => Value::Number(f64::cos(std::f64::consts::PI)) ); test_std!(test_exp, "exp", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(1.0)] => Value::Number(f64::exp(1.0)), - [Value::Number(2.0)] => Value::Number(f64::exp(2.0)) + [1.0] => Value::Number(f64::exp(1.0)), + [2.0] => Value::Number(f64::exp(2.0)) ); test_std!(test_floor, "floor", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(12.5)] => Value::Number(12.0) + [12.5] => Value::Number(12.0) ); test_std!(test_round, "round", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(12.5)] => Value::Number(13.0), - [Value::Number(23.2)] => Value::Number(23.0) + [12.5] => Value::Number(13.0), + [23.2] => Value::Number(23.0) ); test_std!(test_sin, "sin", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(0.0)] => Value::Number(f64::sin(0.0)), - [Value::Number(std::f64::consts::PI / 2.0)] => Value::Number(f64::sin(std::f64::consts::PI / 2.0)) + [0.0] => Value::Number(f64::sin(0.0)), + [std::f64::consts::PI / 2.0] => Value::Number(f64::sin(std::f64::consts::PI / 2.0)) ); test_std!(test_sqrt, "sqrt", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(0.0)] => Value::Number(f64::sqrt(0.0)), - [Value::Number(5.0)] => Value::Number(f64::sqrt(5.0)) + [0.0] => Value::Number(f64::sqrt(0.0)), + [5.0] => Value::Number(f64::sqrt(5.0)) ); test_std!(test_tan, "tan", [] => Value::Number(NAN), [Value::Null] => Value::Number(NAN), - [Value::Number(0.0)] => Value::Number(f64::tan(0.0)), - [Value::Number(1.0)] => Value::Number(f64::tan(1.0)) + [0.0] => Value::Number(f64::tan(0.0)), + [1.0] => Value::Number(f64::tan(1.0)) ); #[test] diff --git a/core/src/avm1/value.rs b/core/src/avm1/value.rs index d8404254e..a6fb044f5 100644 --- a/core/src/avm1/value.rs +++ b/core/src/avm1/value.rs @@ -37,6 +37,36 @@ impl<'gc> From>> for Value<'gc> { } } +impl<'gc> From for Value<'gc> { + fn from(value: f64) -> Self { + Value::Number(value) + } +} + +impl<'gc> From for Value<'gc> { + fn from(value: f32) -> Self { + Value::Number(f64::from(value)) + } +} + +impl<'gc> From for Value<'gc> { + fn from(value: u8) -> Self { + Value::Number(f64::from(value)) + } +} + +impl<'gc> From for Value<'gc> { + fn from(value: i32) -> Self { + Value::Number(f64::from(value)) + } +} + +impl<'gc> From for Value<'gc> { + fn from(value: u32) -> Self { + Value::Number(f64::from(value)) + } +} + unsafe impl<'gc> gc_arena::Collect for Value<'gc> { fn trace(&self, cc: gc_arena::CollectionContext) { if let Value::Object(object) = self { From 6a2806b44ac1e427cb8e4f14fb7e2709a0791fff Mon Sep 17 00:00:00 2001 From: Nathan Adams Date: Mon, 21 Oct 2019 17:22:03 +0200 Subject: [PATCH 8/8] chore: Allow Into for test results --- core/src/avm1/globals.rs | 138 +++++++++++++++++----------------- core/src/avm1/globals/math.rs | 100 ++++++++++++------------ 2 files changed, 119 insertions(+), 119 deletions(-) diff --git a/core/src/avm1/globals.rs b/core/src/avm1/globals.rs index 9b16ec889..47187bef1 100644 --- a/core/src/avm1/globals.rs +++ b/core/src/avm1/globals.rs @@ -128,7 +128,7 @@ mod tests { $( args.push($arg.into()); )* - assert_eq!($fun(avm, context, this, &args), $out); + assert_eq!($fun(avm, context, this, &args), $out.into()); )* Ok(()) @@ -138,82 +138,82 @@ mod tests { } test_std!(boolean_function, boolean, 19, - [true] => Value::Bool(true), - [false] => Value::Bool(false), - [10.0] => Value::Bool(true), - [-10.0] => Value::Bool(true), - [0.0] => Value::Bool(false), - [std::f64::INFINITY] => Value::Bool(true), - [std::f64::NAN] => Value::Bool(false), - [""] => Value::Bool(false), - ["Hello"] => Value::Bool(true), - [" "] => Value::Bool(true), - ["0"] => Value::Bool(true), - ["1"] => Value::Bool(true), - [] => Value::Bool(false) + [true] => true, + [false] => false, + [10.0] => true, + [-10.0] => true, + [0.0] => false, + [std::f64::INFINITY] => true, + [std::f64::NAN] => false, + [""] => false, + ["Hello"] => true, + [" "] => true, + ["0"] => true, + ["1"] => true, + [] => false ); test_std!(boolean_function_swf6, boolean, 6, - [true] => Value::Bool(true), - [false] => Value::Bool(false), - [10.0] => Value::Bool(true), - [-10.0] => Value::Bool(true), - [0.0] => Value::Bool(false), - [std::f64::INFINITY] => Value::Bool(true), - [std::f64::NAN] => Value::Bool(false), - [""] => Value::Bool(false), - ["Hello"] => Value::Bool(false), - [" "] => Value::Bool(false), - ["0"] => Value::Bool(false), - ["1"] => Value::Bool(true), - [] => Value::Bool(false) + [true] => true, + [false] => false, + [10.0] => true, + [-10.0] => true, + [0.0] => false, + [std::f64::INFINITY] => true, + [std::f64::NAN] => false, + [""] => false, + ["Hello"] => false, + [" "] => false, + ["0"] => false, + ["1"] => true, + [] => false ); test_std!(is_nan_function, is_nan, 19, - [true] => Value::Bool(false), - [false] => Value::Bool(false), - [10.0] => Value::Bool(false), - [-10.0] => Value::Bool(false), - [0.0] => Value::Bool(false), - [std::f64::INFINITY] => Value::Bool(false), - [std::f64::NAN] => Value::Bool(true), - [""] => Value::Bool(false), - ["Hello"] => Value::Bool(true), - [" "] => Value::Bool(true), - [" 5 "] => Value::Bool(true), - ["0"] => Value::Bool(false), - ["1"] => Value::Bool(false), - ["Infinity"] => Value::Bool(true), - ["100a"] => Value::Bool(true), - ["0x10"] => Value::Bool(false), - ["0xhello"] => Value::Bool(true), - ["0x1999999981ffffff"] => Value::Bool(false), - ["0xUIXUIDFKHJDF012345678"] => Value::Bool(true), - ["123e-1"] => Value::Bool(false), - [] => Value::Bool(true) + [true] => false, + [false] => false, + [10.0] => false, + [-10.0] => false, + [0.0] => false, + [std::f64::INFINITY] => false, + [std::f64::NAN] => true, + [""] => false, + ["Hello"] => true, + [" "] => true, + [" 5 "] => true, + ["0"] => false, + ["1"] => false, + ["Infinity"] => true, + ["100a"] => true, + ["0x10"] => false, + ["0xhello"] => true, + ["0x1999999981ffffff"] => false, + ["0xUIXUIDFKHJDF012345678"] => true, + ["123e-1"] => false, + [] => true ); test_std!(number_function, number, 19, - [true] => Value::Number(1.0), - [false] => Value::Number(0.0), - [10.0] => Value::Number(10.0), - [-10.0] => Value::Number(-10.0), - [0.0] => Value::Number(0.0), - [std::f64::INFINITY] => Value::Number(std::f64::INFINITY), - [std::f64::NAN] => Value::Number(std::f64::NAN), - [""] => Value::Number(0.0), - ["Hello"] => Value::Number(std::f64::NAN), - [" "] => Value::Number(std::f64::NAN), - [" 5 "] => Value::Number(std::f64::NAN), - ["0"] => Value::Number(0.0), - ["1"] => Value::Number(1.0), - ["Infinity"] => Value::Number(std::f64::NAN), - ["100a"] => Value::Number(std::f64::NAN), - ["0x10"] => Value::Number(16.0), - ["0xhello"] => Value::Number(std::f64::NAN), - ["123e-1"] => Value::Number(12.3), - ["0x1999999981ffffff"] => Value::Number(-2113929217.0), - ["0xUIXUIDFKHJDF012345678"] => Value::Number(std::f64::NAN), - [] => Value::Number(0.0) + [true] => 1.0, + [false] => 0.0, + [10.0] => 10.0, + [-10.0] => -10.0, + [0.0] => 0.0, + [std::f64::INFINITY] => std::f64::INFINITY, + [std::f64::NAN] => std::f64::NAN, + [""] => 0.0, + ["Hello"] => std::f64::NAN, + [" "] => std::f64::NAN, + [" 5 "] => std::f64::NAN, + ["0"] => 0.0, + ["1"] => 1.0, + ["Infinity"] => std::f64::NAN, + ["100a"] => std::f64::NAN, + ["0x10"] => 16.0, + ["0xhello"] => std::f64::NAN, + ["123e-1"] => 12.3, + ["0x1999999981ffffff"] => -2113929217.0, + ["0xUIXUIDFKHJDF012345678"] => std::f64::NAN, + [] => 0.0 ); } diff --git a/core/src/avm1/globals/math.rs b/core/src/avm1/globals/math.rs index 695787357..8b4a7a310 100644 --- a/core/src/avm1/globals/math.rs +++ b/core/src/avm1/globals/math.rs @@ -138,7 +138,7 @@ mod tests { $( args.push($arg.into()); )* - assert_eq!(function.call(avm, context, math, &args)?, Some($out)); + assert_eq!(function.call(avm, context, math, &args)?, Some($out.into())); )* Ok(()) @@ -148,88 +148,88 @@ mod tests { } test_std!(test_abs, "abs", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [-50.0] => Value::Number(50.0), - [25.0] => Value::Number(25.0) + [] => NAN, + [Value::Null] => NAN, + [-50.0] => 50.0, + [25.0] => 25.0 ); test_std!(test_acos, "acos", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [-1.0] => Value::Number(f64::acos(-1.0)), - [0.0] => Value::Number(f64::acos(0.0)), - [1.0] => Value::Number(f64::acos(1.0)) + [] => NAN, + [Value::Null] => NAN, + [-1.0] => f64::acos(-1.0), + [0.0] => f64::acos(0.0), + [1.0] => f64::acos(1.0) ); test_std!(test_asin, "asin", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [-1.0] => Value::Number(f64::asin(-1.0)), - [0.0] => Value::Number(f64::asin(0.0)), - [1.0] => Value::Number(f64::asin(1.0)) + [] => NAN, + [Value::Null] => NAN, + [-1.0] => f64::asin(-1.0), + [0.0] => f64::asin(0.0), + [1.0] => f64::asin(1.0) ); test_std!(test_atan, "atan", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [-1.0] => Value::Number(f64::atan(-1.0)), - [0.0] => Value::Number(f64::atan(0.0)), - [1.0] => Value::Number(f64::atan(1.0)) + [] => NAN, + [Value::Null] => NAN, + [-1.0] => f64::atan(-1.0), + [0.0] => f64::atan(0.0), + [1.0] => f64::atan(1.0) ); test_std!(test_ceil, "ceil", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [12.5] => Value::Number(13.0) + [] => NAN, + [Value::Null] => NAN, + [12.5] => 13.0 ); test_std!(test_cos, "cos", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [0.0] => Value::Number(1.0), - [std::f64::consts::PI] => Value::Number(f64::cos(std::f64::consts::PI)) + [] => NAN, + [Value::Null] => NAN, + [0.0] => 1.0, + [std::f64::consts::PI] => f64::cos(std::f64::consts::PI) ); test_std!(test_exp, "exp", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [1.0] => Value::Number(f64::exp(1.0)), - [2.0] => Value::Number(f64::exp(2.0)) + [] => NAN, + [Value::Null] => NAN, + [1.0] => f64::exp(1.0), + [2.0] => f64::exp(2.0) ); test_std!(test_floor, "floor", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [12.5] => Value::Number(12.0) + [] => NAN, + [Value::Null] => NAN, + [12.5] => 12.0 ); test_std!(test_round, "round", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [12.5] => Value::Number(13.0), - [23.2] => Value::Number(23.0) + [] => NAN, + [Value::Null] => NAN, + [12.5] => 13.0, + [23.2] => 23.0 ); test_std!(test_sin, "sin", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [0.0] => Value::Number(f64::sin(0.0)), - [std::f64::consts::PI / 2.0] => Value::Number(f64::sin(std::f64::consts::PI / 2.0)) + [] => NAN, + [Value::Null] => NAN, + [0.0] => f64::sin(0.0), + [std::f64::consts::PI / 2.0] => f64::sin(std::f64::consts::PI / 2.0) ); test_std!(test_sqrt, "sqrt", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [0.0] => Value::Number(f64::sqrt(0.0)), - [5.0] => Value::Number(f64::sqrt(5.0)) + [] => NAN, + [Value::Null] => NAN, + [0.0] => f64::sqrt(0.0), + [5.0] => f64::sqrt(5.0) ); test_std!(test_tan, "tan", - [] => Value::Number(NAN), - [Value::Null] => Value::Number(NAN), - [0.0] => Value::Number(f64::tan(0.0)), - [1.0] => Value::Number(f64::tan(1.0)) + [] => NAN, + [Value::Null] => NAN, + [0.0] => f64::tan(0.0), + [1.0] => f64::tan(1.0) ); #[test]