diff --git a/core/src/avm2/amf.rs b/core/src/avm2/amf.rs index b235064ab7a9..5b2887531024 100644 --- a/core/src/avm2/amf.rs +++ b/core/src/avm2/amf.rs @@ -79,31 +79,13 @@ pub fn serialize_value<'gc>( } else if let Some(vec) = o.as_vector_storage() { let val_type = vec.value_type(); if val_type == Some(activation.avm2().class_defs().int) { - let int_vec: Vec<_> = vec - .iter() - .map(|v| { - v.as_integer(activation.strings()) - .expect("Unexpected non-int value in int vector") - }) - .collect(); + let int_vec: Vec<_> = vec.iter().map(|v| v.as_i32()).collect(); Some(AmfValue::VectorInt(int_vec, vec.is_fixed())) } else if val_type == Some(activation.avm2().class_defs().uint) { - let uint_vec: Vec<_> = vec - .iter() - .map(|v| { - v.as_u32(activation.strings()) - .expect("Unexpected non-uint value in int vector") - }) - .collect(); + let uint_vec: Vec<_> = vec.iter().map(|v| v.as_u32()).collect(); Some(AmfValue::VectorUInt(uint_vec, vec.is_fixed())) } else if val_type == Some(activation.avm2().class_defs().number) { - let num_vec: Vec<_> = vec - .iter() - .map(|v| { - v.as_number(activation.strings()) - .expect("Unexpected non-uint value in int vector") - }) - .collect(); + let num_vec: Vec<_> = vec.iter().map(|v| v.as_f64()).collect(); Some(AmfValue::VectorDouble(num_vec, vec.is_fixed())) } else { let obj_vec: Vec<_> = vec diff --git a/core/src/avm2/globals/array.rs b/core/src/avm2/globals/array.rs index 1f7f7aaeb401..9a6017ce321f 100644 --- a/core/src/avm2/globals/array.rs +++ b/core/src/avm2/globals/array.rs @@ -73,10 +73,7 @@ pub fn instance_init<'gc>( if let Some(mut array) = this.as_array_storage_mut(activation.context.gc_context) { if args.len() == 1 { - if let Some(expected_len) = args - .get(0) - .and_then(|v| v.as_number(activation.strings()).ok()) - { + if let Some(expected_len) = args.get(0).filter(|v| v.is_number()).map(|v| v.as_f64()) { if expected_len < 0.0 || expected_len.is_nan() || expected_len.fract() != 0.0 { return Err(Error::AvmError(range_error( activation, diff --git a/core/src/avm2/globals/flash/display/graphics.rs b/core/src/avm2/globals/flash/display/graphics.rs index e0aef2284158..4787d5038520 100644 --- a/core/src/avm2/globals/flash/display/graphics.rs +++ b/core/src/avm2/globals/flash/display/graphics.rs @@ -1283,17 +1283,9 @@ fn read_point<'gc>( data: &VectorStorage<'gc>, data_index: &mut usize, ) -> Option> { - let x = data - .get(*data_index, activation) - .ok()? - .as_number(activation.strings()) - .expect("data is not a Vec."); - - let y = data - .get(*data_index + 1, activation) - .ok()? - .as_number(activation.strings()) - .expect("data is not a Vec."); + let x = data.get(*data_index, activation).ok()?.as_f64(); + + let y = data.get(*data_index + 1, activation).ok()?.as_f64(); *data_index += 2; @@ -1395,8 +1387,7 @@ fn process_commands<'gc>( let command = commands .get(i, activation) .expect("missing command") - .as_integer(activation.strings()) - .expect("commands is not a Vec."); + .as_i32(); if process_command(activation, drawing, data, command, &mut data_index).is_none() { break; diff --git a/core/src/avm2/globals/flash/display/shader_job.rs b/core/src/avm2/globals/flash/display/shader_job.rs index bdef3b993ff0..da360c9ef062 100644 --- a/core/src/avm2/globals/flash/display/shader_job.rs +++ b/core/src/avm2/globals/flash/display/shader_job.rs @@ -107,19 +107,16 @@ pub fn get_shader_args<'gc>( let width = shader_input .get_public_property("width", activation) .unwrap() - .as_u32(activation.strings()) - .unwrap(); + .as_u32(); let height = shader_input .get_public_property("height", activation) .unwrap() - .as_u32(activation.strings()) - .unwrap(); + .as_u32(); let input_channels = shader_input .get_public_property("channels", activation) .unwrap() - .as_u32(activation.strings()) - .unwrap(); + .as_u32(); assert_eq!(*channels as u32, input_channels); @@ -155,10 +152,7 @@ pub fn get_shader_args<'gc>( channels: input_channels, bytes: vector .iter() - .flat_map(|val| { - (val.as_number(activation.strings()).unwrap() as f32) - .to_le_bytes() - }) + .flat_map(|val| (val.as_f64() as f32).to_le_bytes()) .collect(), } } else { @@ -207,15 +201,9 @@ pub fn start<'gc>( .as_object() .expect("ShaderJob.target is not an object"); - let output_width = this - .get_public_property("width", activation)? - .as_u32(activation.strings()) - .expect("ShaderJob.width is not a number"); + let output_width = this.get_public_property("width", activation)?.as_u32(); - let output_height = this - .get_public_property("height", activation)? - .as_u32(activation.strings()) - .expect("ShaderJob.height is not a number"); + let output_height = this.get_public_property("height", activation)?.as_u32(); let pixel_bender_target = if let Some(bitmap) = target.as_bitmap_data() { let target_bitmap = bitmap.sync(activation.context.renderer); diff --git a/core/src/avm2/globals/flash/display3D/context_3d.rs b/core/src/avm2/globals/flash/display3D/context_3d.rs index 0d9bfa68c081..62e870ad89e2 100644 --- a/core/src/avm2/globals/flash/display3D/context_3d.rs +++ b/core/src/avm2/globals/flash/display3D/context_3d.rs @@ -320,8 +320,8 @@ pub fn set_program_constants_from_matrix<'gc>( .as_vector_storage() .unwrap() .iter() - .map(|val| val.coerce_to_number(activation).map(|val| val as f32)) - .collect::, Error>>()?; + .map(|val| val.as_f64() as f32) + .collect::>(); context.set_program_constants_from_matrix(is_vertex, first_register, matrix_raw_data); } @@ -365,9 +365,9 @@ pub fn set_program_constants_from_vector<'gc>( let raw_data = vector .iter() - .map(|val| val.as_number(activation.strings()).map(|val| val as f32)) + .map(|val| val.as_f64() as f32) .take(to_take) - .collect::, _>>()?; + .collect::>(); context.set_program_constants_from_matrix(program_type, first_register, raw_data); } @@ -375,19 +375,19 @@ pub fn set_program_constants_from_vector<'gc>( } pub fn clear<'gc>( - activation: &mut Activation<'_, 'gc>, + _activation: &mut Activation<'_, 'gc>, this: Object<'gc>, args: &[Value<'gc>], ) -> Result, Error<'gc>> { if let Some(context) = this.as_context_3d() { // This is a native method, so all of the arguments have been checked and coerced for us - let red = args[0].as_number(activation.strings())?; - let green = args[1].as_number(activation.strings())?; - let blue = args[2].as_number(activation.strings())?; - let alpha = args[3].as_number(activation.strings())?; - let depth = args[4].as_number(activation.strings())?; - let stencil = args[5].as_integer(activation.strings())? as u32; - let mask = args[6].as_integer(activation.strings())? as u32; + let red = args[0].as_f64(); + let green = args[1].as_f64(); + let blue = args[2].as_f64(); + let alpha = args[3].as_f64(); + let depth = args[4].as_f64(); + let stencil = args[5].as_i32() as u32; + let mask = args[6].as_i32() as u32; context.set_clear(red, green, blue, alpha, depth, stencil, mask); } Ok(Value::Undefined) @@ -400,11 +400,11 @@ pub fn create_texture<'gc>( ) -> Result, Error<'gc>> { if let Some(context) = this.as_context_3d() { // This is a native method, so all of the arguments have been checked and coerced for us - let width = args[0].as_integer(activation.strings())? as u32; - let height = args[1].as_integer(activation.strings())? as u32; + let width = args[0].as_i32() as u32; + let height = args[1].as_i32() as u32; let format = args[2].coerce_to_string(activation)?; let optimize_for_render_to_texture = args[3].coerce_to_boolean(); - let streaming_levels = args[4].as_integer(activation.strings())? as u32; + let streaming_levels = args[4].as_i32() as u32; let format = Context3DTextureFormat::from_wstr(&format).ok_or_else(|| { Error::RustError( format!("Unsupported texture format in createTexture: {:?}", format).into(), @@ -433,8 +433,8 @@ pub fn create_rectangle_texture<'gc>( ) -> Result, Error<'gc>> { if let Some(context) = this.as_context_3d() { // This is a native method, so all of the arguments have been checked and coerced for us - let width = args[0].as_integer(activation.strings())? as u32; - let height = args[1].as_integer(activation.strings())? as u32; + let width = args[0].as_i32() as u32; + let height = args[1].as_i32() as u32; let format = args[2].coerce_to_string(activation)?; let optimize_for_render_to_texture = args[3].coerce_to_boolean(); let format = Context3DTextureFormat::from_wstr(&format).ok_or_else(|| { @@ -469,10 +469,10 @@ pub fn create_cube_texture<'gc>( ) -> Result, Error<'gc>> { if let Some(context) = this.as_context_3d() { // This is a native method, so all of the arguments have been checked and coerced for us - let size = args[0].as_integer(activation.strings())? as u32; + let size = args[0].as_i32() as u32; let format = args[1].coerce_to_string(activation)?; let optimize_for_render_to_texture = args[2].coerce_to_boolean(); - let streaming_levels = args[3].as_integer(activation.strings())? as u32; + let streaming_levels = args[3].as_i32() as u32; let format = Context3DTextureFormat::from_wstr(&format).ok_or_else(|| { Error::RustError( format!( @@ -501,7 +501,7 @@ pub fn set_texture_at<'gc>( ) -> Result, Error<'gc>> { if let Some(context) = this.as_context_3d() { // This is a native method, so all of the arguments have been checked and coerced for us - let sampler = args[0].as_integer(activation.strings())? as u32; + let sampler = args[0].as_i32() as u32; let mut cube = false; let texture = if matches!(args[1], Value::Null) { None @@ -652,7 +652,7 @@ pub fn set_sampler_state_at<'gc>( ) -> Result, Error<'gc>> { if let Some(context) = this.as_context_3d() { // This is a native method, so all of the arguments have been checked and coerced for us - let sampler = args[0].as_integer(activation.strings())? as u32; + let sampler = args[0].as_i32() as u32; let wrap = args[1].coerce_to_string(activation)?; let filter = args[2].coerce_to_string(activation)?; let mip_filter = args[3].coerce_to_string(activation)?; diff --git a/core/src/avm2/globals/json.rs b/core/src/avm2/globals/json.rs index d22a0b9ef0d2..c32040ef6939 100644 --- a/core/src/avm2/globals/json.rs +++ b/core/src/avm2/globals/json.rs @@ -332,16 +332,15 @@ pub fn stringify<'gc>( }; Some(indent_bytes) } - } else { - let indent_size = spaces - .as_number(activation.strings()) - .unwrap_or(0.0) - .clamp(0.0, 10.0) as u16; + } else if spaces.is_number() { + let indent_size = spaces.as_f64().clamp(0.0, 10.0) as u16; if indent_size == 0 { None } else { Some(Cow::Owned(b" ".repeat(indent_size.into()))) } + } else { + None }; let mut serializer = AvmSerializer::new(replacer); diff --git a/core/src/avm2/value.rs b/core/src/avm2/value.rs index 95b15d1209f9..9df20f8f92f0 100644 --- a/core/src/avm2/value.rs +++ b/core/src/avm2/value.rs @@ -9,7 +9,7 @@ use crate::avm2::Error; use crate::avm2::Multiname; use crate::avm2::Namespace; use crate::ecma_conversions::{f64_to_wrapping_i32, f64_to_wrapping_u32}; -use crate::string::{AvmAtom, AvmString, StringContext, WStr}; +use crate::string::{AvmAtom, AvmString, WStr}; use gc_arena::Collect; use num_bigint::BigInt; use num_traits::{ToPrimitive, Zero}; @@ -552,52 +552,30 @@ impl<'gc> Value<'gc> { /// Get the numerical portion of the value, if it exists. /// - /// This function performs no numerical coercion, nor are user-defined - /// object methods called. This should only be used if you specifically - /// need the behavior of only handling actual numbers; otherwise you should - /// use the appropriate `coerce_to_` method. - pub fn as_number(&self, context: &mut StringContext<'gc>) -> Result> { + /// This function performs no numerical coercion, nor are any methods called. + pub fn as_f64(&self) -> f64 { match self { - // Methods that look for numbers in Flash Player don't seem to care - // about user-defined `valueOf` implementations. This code upholds - // that limitation as long as `TObject`'s `value_of` method also - // does not call user-defined functions. - Value::Object(num) => match num.value_of(context)? { - Value::Number(num) => Ok(num), - Value::Integer(num) => Ok(num as f64), - _ => Err(format!("Expected Number, int, or uint, found {self:?}").into()), - }, - Value::Number(num) => Ok(*num), - Value::Integer(num) => Ok(*num as f64), - _ => Err(format!("Expected Number, int, or uint, found {self:?}").into()), + Value::Number(num) => *num, + Value::Integer(num) => *num as f64, + _ => panic!("Expected Number or Integer"), } } /// Like `as_number`, but for `i32` - pub fn as_integer(&self, context: &mut StringContext<'gc>) -> Result> { + pub fn as_i32(&self) -> i32 { match self { - Value::Object(num) => match num.value_of(context)? { - Value::Number(num) => Ok(num as i32), - Value::Integer(num) => Ok(num), - _ => Err(format!("Expected Number, int, or uint, found {self:?}").into()), - }, - Value::Number(num) => Ok(*num as i32), - Value::Integer(num) => Ok(*num), - _ => Err(format!("Expected Number, int, or uint, found {self:?}").into()), + Value::Number(num) => *num as i32, + Value::Integer(num) => *num, + _ => panic!("Expected Number or Integer"), } } /// Like `as_number`, but for `u32` - pub fn as_u32(&self, context: &mut StringContext<'gc>) -> Result> { + pub fn as_u32(&self) -> u32 { match self { - Value::Object(num) => match num.value_of(context)? { - Value::Number(num) => Ok(num as u32), - Value::Integer(num) => Ok(num as u32), - _ => Err(format!("Expected Number, int, or uint, found {self:?}").into()), - }, - Value::Number(num) => Ok(*num as u32), - Value::Integer(num) => Ok(*num as u32), - _ => Err(format!("Expected Number, int, or uint, found {self:?}").into()), + Value::Number(num) => *num as u32, + Value::Integer(num) => *num as u32, + _ => panic!("Expected Number or Integer"), } } diff --git a/core/src/bitmap/operations.rs b/core/src/bitmap/operations.rs index 1a774442f266..b25ac0abb6c6 100644 --- a/core/src/bitmap/operations.rs +++ b/core/src/bitmap/operations.rs @@ -1669,8 +1669,8 @@ pub fn set_vector<'gc>( let color = iter .next() .expect("BitmapData.setVector: Expected element") - .as_u32(activation.strings()) - .expect("BitmapData.setVector: Expected uint vector"); + .as_u32(); + bitmap_data.set_pixel32_raw( x, y,