diff --git a/core/src/avm1/activation.rs b/core/src/avm1/activation.rs index 01fa09431207c..33c539239220a 100644 --- a/core/src/avm1/activation.rs +++ b/core/src/avm1/activation.rs @@ -1008,7 +1008,7 @@ impl<'a, 'gc> Activation<'a, 'gc> { // SWF19: "If A is zero, the result NaN, Infinity, or -Infinity is pushed to the stack in SWF 5 and later. // In SWF 4, the result is the string #ERROR#." let result: Value<'gc> = if a == 0.0 && self.swf_version() < 5 { - AvmString::new_utf8(self.gc(), "#ERROR#").into() + AvmString::new_ascii_static(self.gc(), b"#ERROR#").into() } else { (b / a).into() }; diff --git a/core/src/avm1/globals/object.rs b/core/src/avm1/globals/object.rs index f634b8290e7ec..8f8759f496ee7 100644 --- a/core/src/avm1/globals/object.rs +++ b/core/src/avm1/globals/object.rs @@ -116,9 +116,9 @@ fn to_string<'gc>( _args: &[Value<'gc>], ) -> Result, Error<'gc>> { if this.as_executable().is_some() { - Ok(AvmString::new_utf8(activation.gc(), "[type Function]").into()) + Ok(AvmString::new_ascii_static(activation.gc(), b"[type Function]").into()) } else { - Ok(AvmString::new_utf8(activation.gc(), "[object Object]").into()) + Ok(AvmString::new_ascii_static(activation.gc(), b"[object Object]").into()) } } diff --git a/core/src/avm1/globals/system_ime.rs b/core/src/avm1/globals/system_ime.rs index 6c2854f98cc9a..6b4a63c869509 100644 --- a/core/src/avm1/globals/system_ime.rs +++ b/core/src/avm1/globals/system_ime.rs @@ -44,7 +44,7 @@ fn get_conversion_mode<'gc>( _this: Object<'gc>, _args: &[Value<'gc>], ) -> Result, Error<'gc>> { - Ok(AvmString::new_utf8(activation.gc(), "KOREAN").into()) + Ok(AvmString::new_ascii_static(activation.gc(), b"KOREAN").into()) } fn get_enabled<'gc>( diff --git a/core/src/avm1/value.rs b/core/src/avm1/value.rs index 0dd9a71731118..810da606762cf 100644 --- a/core/src/avm1/value.rs +++ b/core/src/avm1/value.rs @@ -423,9 +423,9 @@ impl<'gc> Value<'gc> { Value::String(s) => s, _ => { if object.as_executable().is_some() { - AvmString::new_utf8(activation.gc(), "[type Function]") + AvmString::new_ascii_static(activation.gc(), b"[type Function]") } else { - AvmString::new_utf8(activation.gc(), "[type Object]") + AvmString::new_ascii_static(activation.gc(), b"[type Object]") } } } diff --git a/core/src/avm2/domain.rs b/core/src/avm2/domain.rs index f9b7f4c44f1fd..8f5c85d1176c7 100644 --- a/core/src/avm2/domain.rs +++ b/core/src/avm2/domain.rs @@ -290,7 +290,7 @@ impl<'gc> Domain<'gc> { activation.gc(), &name[(start + 2)..(name.len() - 1)], )); - name = AvmString::new_utf8(activation.gc(), "__AS3__.vec::Vector"); + name = AvmString::new_ascii_static(activation.gc(), b"__AS3__.vec::Vector"); } // FIXME - is this the correct api version? let api_version = activation.avm2().root_api_version; diff --git a/core/src/avm2/globals/Date.as b/core/src/avm2/globals/Date.as index b78e9ca00d648..08d83e523d738 100644 --- a/core/src/avm2/globals/Date.as +++ b/core/src/avm2/globals/Date.as @@ -4,8 +4,6 @@ package { public dynamic class Date { public static const length:int = 7; - private static const invalidDateStr:String = "Invalid Date"; - prototype.valueOf = function():* { var d:Date = this; return d.AS3::valueOf(); diff --git a/core/src/avm2/globals/class.rs b/core/src/avm2/globals/class.rs index 6a3cd67fc77c3..fa564c707962c 100644 --- a/core/src/avm2/globals/class.rs +++ b/core/src/avm2/globals/class.rs @@ -103,7 +103,7 @@ pub fn create_c_class<'gc>( let gc_context = activation.gc(); let namespaces = activation.avm2().namespaces; - let class_name = AvmString::new_utf8(gc_context, "Class$"); + let class_name = AvmString::new_ascii_static(gc_context, b"Class$"); let class_c_class = Class::custom_new( QName::new(namespaces.public_all(), class_name), Some(class_i_class), diff --git a/core/src/avm2/globals/date.rs b/core/src/avm2/globals/date.rs index 33a43a715d420..76dec1f12e1ab 100644 --- a/core/src/avm2/globals/date.rs +++ b/core/src/avm2/globals/date.rs @@ -934,7 +934,7 @@ pub fn to_string<'gc>( ) .into()) } else { - Ok(AvmString::new_utf8(activation.gc(), "Invalid Date").into()) + Ok(AvmString::new_ascii_static(activation.gc(), b"Invalid Date").into()) } } @@ -955,7 +955,7 @@ pub fn to_utc_string<'gc>( ) .into()) } else { - Ok(AvmString::new_utf8(activation.gc(), "Invalid Date").into()) + Ok(AvmString::new_ascii_static(activation.gc(), b"Invalid Date").into()) } } @@ -979,7 +979,7 @@ pub fn to_locale_string<'gc>( ) .into()) } else { - Ok(AvmString::new_utf8(activation.gc(), "Invalid Date").into()) + Ok(AvmString::new_ascii_static(activation.gc(), b"Invalid Date").into()) } } @@ -999,7 +999,7 @@ pub fn to_time_string<'gc>( { Ok(AvmString::new_utf8(activation.gc(), date.format("%T GMT%z").to_string()).into()) } else { - Ok(AvmString::new_utf8(activation.gc(), "Invalid Date").into()) + Ok(AvmString::new_ascii_static(activation.gc(), b"Invalid Date").into()) } } @@ -1019,7 +1019,7 @@ pub fn to_locale_time_string<'gc>( { Ok(AvmString::new_utf8(activation.gc(), date.format("%T %p").to_string()).into()) } else { - Ok(AvmString::new_utf8(activation.gc(), "Invalid Date").into()) + Ok(AvmString::new_ascii_static(activation.gc(), b"Invalid Date").into()) } } @@ -1039,7 +1039,7 @@ pub fn to_date_string<'gc>( { Ok(AvmString::new_utf8(activation.gc(), date.format("%a %b %-d %-Y").to_string()).into()) } else { - Ok(AvmString::new_utf8(activation.gc(), "Invalid Date").into()) + Ok(AvmString::new_ascii_static(activation.gc(), b"Invalid Date").into()) } } diff --git a/core/src/avm2/globals/flash/ui/keyboard.rs b/core/src/avm2/globals/flash/ui/keyboard.rs index 153c18654a305..99ec867de7338 100644 --- a/core/src/avm2/globals/flash/ui/keyboard.rs +++ b/core/src/avm2/globals/flash/ui/keyboard.rs @@ -39,7 +39,7 @@ pub fn get_physical_keyboard_type<'gc>( _args: &[Value<'gc>], ) -> Result, Error<'gc>> { avm2_stub_getter!(activation, "flash.ui.Keyboard", "physicalKeyboardType"); - Ok(AvmString::new_utf8(activation.gc(), "alphanumeric").into()) + Ok(AvmString::new_ascii_static(activation.gc(), b"alphanumeric").into()) } pub fn is_accessible<'gc>( diff --git a/core/src/avm2/globals/number.rs b/core/src/avm2/globals/number.rs index 3502b2e685738..b9f03aec8911c 100644 --- a/core/src/avm2/globals/number.rs +++ b/core/src/avm2/globals/number.rs @@ -136,7 +136,7 @@ pub fn print_with_radix<'gc>( if number.is_infinite() { if number < 0.0 { - return Ok(AvmString::new_utf8(activation.gc(), "-Infinity")); + return Ok(AvmString::new_ascii_static(activation.gc(), b"-Infinity")); } else if number > 0.0 { return Ok(istr!("Infinity")); } diff --git a/core/src/avm2/globals/object.rs b/core/src/avm2/globals/object.rs index 9f935fce04c5f..bb6e212fb0d3f 100644 --- a/core/src/avm2/globals/object.rs +++ b/core/src/avm2/globals/object.rs @@ -355,7 +355,7 @@ pub fn create_c_class<'gc>( let gc_context = activation.gc(); let namespaces = activation.avm2().namespaces; - let class_name = AvmString::new_utf8(gc_context, "Object$"); + let class_name = AvmString::new_ascii_static(gc_context, b"Object$"); let object_c_class = Class::custom_new( QName::new(namespaces.public_all(), class_name), Some(class_i_class), diff --git a/core/src/avm2/globals/xml.rs b/core/src/avm2/globals/xml.rs index 6ba054344d149..5be58ad77f05f 100644 --- a/core/src/avm2/globals/xml.rs +++ b/core/src/avm2/globals/xml.rs @@ -866,17 +866,17 @@ pub fn node_kind<'gc>( let this = this.as_object().unwrap(); let xml = this.as_xml_object().unwrap(); - let name = match &*xml.node().kind() { - E4XNodeKind::Text(_) => "text", - E4XNodeKind::CData(_) => "text", // cdata pretends to be text here - E4XNodeKind::Comment(_) => "comment", - E4XNodeKind::ProcessingInstruction(_) => "processing-instruction", - E4XNodeKind::Attribute(_) => "attribute", - E4XNodeKind::Element { .. } => "element", + let name: &'static [u8] = match &*xml.node().kind() { + E4XNodeKind::Text(_) => b"text", + E4XNodeKind::CData(_) => b"text", // cdata pretends to be text here + E4XNodeKind::Comment(_) => b"comment", + E4XNodeKind::ProcessingInstruction(_) => b"processing-instruction", + E4XNodeKind::Attribute(_) => b"attribute", + E4XNodeKind::Element { .. } => b"element", }; // FIXME should we intern these? - Ok(AvmString::new_utf8(activation.gc(), name).into()) + Ok(AvmString::new_ascii_static(activation.gc(), name).into()) } pub fn append_child<'gc>( diff --git a/core/src/avm2/namespace.rs b/core/src/avm2/namespace.rs index 0a30ba4fcccc8..2c3ed58865ad4 100644 --- a/core/src/avm2/namespace.rs +++ b/core/src/avm2/namespace.rs @@ -349,8 +349,8 @@ impl<'gc> CommonNamespaces<'gc> { let empty_string = context.empty(); let as3_namespace_string = - AvmString::new_utf8(context.gc(), "http://adobe.com/AS3/2006/builtin"); - let vector_namespace_string = AvmString::new_utf8(context.gc(), "__AS3__.vec"); + AvmString::new_ascii_static(context.gc(), b"http://adobe.com/AS3/2006/builtin"); + let vector_namespace_string = AvmString::new_ascii_static(context.gc(), b"__AS3__.vec"); Self { public_namespaces: std::array::from_fn(|val| { diff --git a/core/src/backend/audio.rs b/core/src/backend/audio.rs index cf585841a5d86..aba3fb464c657 100644 --- a/core/src/backend/audio.rs +++ b/core/src/backend/audio.rs @@ -412,7 +412,7 @@ impl<'gc> AudioManager<'gc> { // Fire soundComplete event. if let Some(root) = context.stage.root_clip() { - let method_name = AvmString::new_utf8(mc, "onSoundComplete"); + let method_name = AvmString::new_ascii_static(mc, b"onSoundComplete"); context.action_queue.queue_action( root, diff --git a/core/src/context.rs b/core/src/context.rs index 794b04a40b33b..acae440afdab3 100644 --- a/core/src/context.rs +++ b/core/src/context.rs @@ -422,7 +422,7 @@ impl<'gc> UpdateContext<'gc> { .get_version_string(activation.context.avm1); object.define_value( activation.gc(), - AvmString::new_utf8(activation.gc(), "$version"), + AvmString::new_ascii_static(activation.gc(), b"$version"), AvmString::new_utf8(activation.gc(), version_string).into(), Attribute::empty(), ); diff --git a/core/src/display_object/interactive.rs b/core/src/display_object/interactive.rs index 6bc5d657846f6..9d631cd8894eb 100644 --- a/core/src/display_object/interactive.rs +++ b/core/src/display_object/interactive.rs @@ -610,9 +610,9 @@ pub trait TInteractiveObject<'gc>: .unwrap_or(Avm1Value::Null); let method_name = if focused { - AvmString::new_utf8(context.gc(), "onSetFocus") + AvmString::new_ascii_static(context.gc(), b"onSetFocus") } else { - AvmString::new_utf8(context.gc(), "onKillFocus") + AvmString::new_ascii_static(context.gc(), b"onKillFocus") }; Avm1::run_stack_frame_for_method(self_do, object, method_name, &[other], context); diff --git a/core/src/loader.rs b/core/src/loader.rs index 2c5bd8fad74fa..b2f95699ea362 100644 --- a/core/src/loader.rs +++ b/core/src/loader.rs @@ -2531,7 +2531,7 @@ impl<'gc> Loader<'gc> { match vm_data { MovieLoaderVMData::Avm1 { broadcaster } => { if let Some(broadcaster) = broadcaster { - let error_message = AvmString::new_utf8(uc.gc(), "LoadNeverCompleted"); + let error_message = AvmString::new_ascii_static(uc.gc(), b"LoadNeverCompleted"); Avm1::run_stack_frame_for_method( clip, diff --git a/core/src/string/avm_string.rs b/core/src/string/avm_string.rs index 9d4a8546dc443..944afefd65fc8 100644 --- a/core/src/string/avm_string.rs +++ b/core/src/string/avm_string.rs @@ -21,6 +21,11 @@ impl<'gc> AvmString<'gc> { } } + pub fn new_ascii_static(gc_context: &Mutation<'gc>, bytes: &'static [u8]) -> Self { + let repr = AvmStringRepr::from_raw_static(WStr::from_units(bytes), false); + Self(Gc::new(gc_context, repr)) + } + pub fn new_utf8<'s, S: Into>>(gc_context: &Mutation<'gc>, string: S) -> Self { let buf = match string.into() { Cow::Owned(utf8) => WString::from_utf8_owned(utf8),