avm1: Allow Avm1String to contain &'static str

This commit is contained in:
Nathan Adams 2020-07-13 00:43:12 +02:00 committed by Mike Welsh
parent ad733f2f21
commit e03e3f6c4e
16 changed files with 106 additions and 95 deletions

View File

@ -257,7 +257,7 @@ mod tests {
with_avm(19, |activation, context, _root| -> Result<(), Error> { with_avm(19, |activation, context, _root| -> Result<(), Error> {
assert_eq!( assert_eq!(
VariableDumper::dump( VariableDumper::dump(
&Value::String(Avm1String::new(context.gc_context, "".to_string())), &Value::String(Avm1String::from("")),
" ", " ",
activation, activation,
context context
@ -266,10 +266,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
VariableDumper::dump( VariableDumper::dump(
&Value::String(Avm1String::new( &Value::String(Avm1String::from("HELLO WORLD")),
context.gc_context,
"HELLO WORLD".to_string()
)),
" ", " ",
activation, activation,
context context
@ -278,9 +275,8 @@ mod tests {
); );
assert_eq!( assert_eq!(
VariableDumper::dump( VariableDumper::dump(
&Value::String(Avm1String::new( &Value::String(Avm1String::from(
context.gc_context, "Escape \"this\" string\nplease! \u{0008}\u{000C}\n\r\t\"\\"
"Escape \"this\" string\nplease! \u{0008}\u{000C}\n\r\t\"\\".to_string()
)), )),
" ", " ",
activation, activation,
@ -312,7 +308,7 @@ mod tests {
object.set("self", object.into(), activation, context)?; object.set("self", object.into(), activation, context)?;
object.set( object.set(
"test", "test",
Value::String(Avm1String::new(context.gc_context, "value".to_string())), Value::String(Avm1String::from("value")),
activation, activation,
context, context,
)?; )?;
@ -335,7 +331,7 @@ mod tests {
object.set("self", object.into(), activation, context)?; object.set("self", object.into(), activation, context)?;
object.set( object.set(
"test", "test",
Value::String(Avm1String::new(context.gc_context, "value".to_string())), Value::String(Avm1String::from("value")),
activation, activation,
context, context,
)?; )?;

View File

@ -448,7 +448,7 @@ impl<'gc> FunctionObject<'gc> {
gc_context, gc_context,
FunctionObjectData { FunctionObjectData {
function: Some(function.into()), function: Some(function.into()),
primitive: Avm1String::new(gc_context, "[type Function]".to_string()).into(), primitive: Avm1String::from("[type Function]").into(),
}, },
), ),
} }
@ -553,8 +553,7 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
context.gc_context, context.gc_context,
FunctionObjectData { FunctionObjectData {
function: None, function: None,
primitive: Avm1String::new(context.gc_context, "[type Function]".to_string()) primitive: Avm1String::from("[type Function]").into(),
.into(),
}, },
), ),
}; };

View File

@ -32,13 +32,13 @@ pub fn create_proto<'gc>(
object.define_value( object.define_value(
gc_context, gc_context,
"message", "message",
Avm1String::new(gc_context, "Error".to_string()).into(), Avm1String::from("Error").into(),
EnumSet::empty(), EnumSet::empty(),
); );
object.define_value( object.define_value(
gc_context, gc_context,
"name", "name",
Avm1String::new(gc_context, "Error".to_string()).into(), Avm1String::from("Error").into(),
EnumSet::empty(), EnumSet::empty(),
); );

View File

@ -93,11 +93,11 @@ pub fn apply<'gc>(
/// Implements `Function.prototype.toString` /// Implements `Function.prototype.toString`
fn to_string<'gc>( fn to_string<'gc>(
_: &mut Activation<'_, 'gc>, _: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, _context: &mut UpdateContext<'_, 'gc, '_>,
_: Object<'gc>, _: Object<'gc>,
_: &[Value<'gc>], _: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
Ok(Avm1String::new(context.gc_context, "[type Function]".to_string()).into()) Ok(Avm1String::from("[type Function]").into())
} }
/// Partially construct `Function.prototype`. /// Partially construct `Function.prototype`.

View File

@ -159,7 +159,7 @@ fn to_string<'gc>(
Ordering::Greater => (n as u32, false), Ordering::Greater => (n as u32, false),
Ordering::Equal => { Ordering::Equal => {
// Bail out immediately if we're 0. // Bail out immediately if we're 0.
return Ok(Avm1String::new(context.gc_context, "0".to_string()).into()); return Ok(Avm1String::from("0").into());
} }
}; };
@ -185,7 +185,7 @@ fn to_string<'gc>(
// for example, NaN.toString(3) gives "-/.//./..././/0.0./0.". // for example, NaN.toString(3) gives "-/.//./..././/0.0./0.".
// Flash Player 6 will print a much more sane value of 0, so let's go with that. // Flash Player 6 will print a much more sane value of 0, so let's go with that.
// TODO: Allow configuration of player version. // TODO: Allow configuration of player version.
Ok(Avm1String::new(context.gc_context, "0".to_string()).into()) Ok(Avm1String::from("0").into())
} }
} }

View File

@ -89,11 +89,11 @@ pub fn has_own_property<'gc>(
/// Implements `Object.prototype.toString` /// Implements `Object.prototype.toString`
fn to_string<'gc>( fn to_string<'gc>(
_: &mut Activation<'_, 'gc>, _: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, _context: &mut UpdateContext<'_, 'gc, '_>,
_: Object<'gc>, _: Object<'gc>,
_: &[Value<'gc>], _: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
Ok(Avm1String::new(context.gc_context, "[object Object]".to_string()).into()) Ok(Avm1String::from("[object Object]").into())
} }
/// Implements `Object.prototype.isPropertyEnumerable` /// Implements `Object.prototype.isPropertyEnumerable`

View File

@ -87,12 +87,12 @@ fn add_listener<'gc>(
fn align<'gc>( fn align<'gc>(
_activation: &mut Activation<'_, 'gc>, _activation: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, _context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>, _this: Object<'gc>,
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
log::warn!("Stage.align: unimplemented"); log::warn!("Stage.align: unimplemented");
Ok(Avm1String::new(context.gc_context, "".to_string()).into()) Ok(Avm1String::from("").into())
} }
fn set_align<'gc>( fn set_align<'gc>(
@ -116,22 +116,22 @@ fn height<'gc>(
fn remove_listener<'gc>( fn remove_listener<'gc>(
_activation: &mut Activation<'_, 'gc>, _activation: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, _context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>, _this: Object<'gc>,
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
log::warn!("Stage.removeListener: unimplemented"); log::warn!("Stage.removeListener: unimplemented");
Ok(Avm1String::new(context.gc_context, "".to_string()).into()) Ok(Avm1String::from("").into())
} }
fn scale_mode<'gc>( fn scale_mode<'gc>(
_activation: &mut Activation<'_, 'gc>, _activation: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, _context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>, _this: Object<'gc>,
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
log::warn!("Stage.scaleMode: unimplemented"); log::warn!("Stage.scaleMode: unimplemented");
Ok(Avm1String::new(context.gc_context, "noScale".to_string()).into()) Ok(Avm1String::from("noScale").into())
} }
fn set_scale_mode<'gc>( fn set_scale_mode<'gc>(

View File

@ -395,7 +395,7 @@ fn slice<'gc>(
); );
Ok(Avm1String::new(context.gc_context, ret).into()) Ok(Avm1String::new(context.gc_context, ret).into())
} else { } else {
Ok(Avm1String::new(context.gc_context, "".to_string()).into()) Ok(Avm1String::from("").into())
} }
} }

View File

@ -29,11 +29,11 @@ fn do_conversion<'gc>(
fn get_conversion_mode<'gc>( fn get_conversion_mode<'gc>(
_activation: &mut Activation<'_, 'gc>, _activation: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, _context: &mut UpdateContext<'_, 'gc, '_>,
_this: Object<'gc>, _this: Object<'gc>,
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
Ok(Avm1String::new(context.gc_context, "KOREAN".to_string()).into()) Ok(Avm1String::from("KOREAN").into())
} }
fn get_enabled<'gc>( fn get_enabled<'gc>(
@ -85,49 +85,49 @@ pub fn create<'gc>(
ime.define_value( ime.define_value(
gc_context, gc_context,
"ALPHANUMERIC_FULL", "ALPHANUMERIC_FULL",
Avm1String::new(gc_context, "ALPHANUMERIC_FULL".to_string()).into(), Avm1String::from("ALPHANUMERIC_FULL").into(),
Attribute::DontDelete | ReadOnly | DontEnum, Attribute::DontDelete | ReadOnly | DontEnum,
); );
ime.define_value( ime.define_value(
gc_context, gc_context,
"ALPHANUMERIC_HALF", "ALPHANUMERIC_HALF",
Avm1String::new(gc_context, "ALPHANUMERIC_HALF".to_string()).into(), Avm1String::from("ALPHANUMERIC_HALF").into(),
DontDelete | ReadOnly | DontEnum, DontDelete | ReadOnly | DontEnum,
); );
ime.define_value( ime.define_value(
gc_context, gc_context,
"CHINESE", "CHINESE",
Avm1String::new(gc_context, "CHINESE".to_string()).into(), Avm1String::from("CHINESE").into(),
DontDelete | ReadOnly | DontEnum, DontDelete | ReadOnly | DontEnum,
); );
ime.define_value( ime.define_value(
gc_context, gc_context,
"JAPANESE_HIRAGANA", "JAPANESE_HIRAGANA",
Avm1String::new(gc_context, "JAPANESE_HIRAGANA".to_string()).into(), Avm1String::from("JAPANESE_HIRAGANA").into(),
DontDelete | ReadOnly | DontEnum, DontDelete | ReadOnly | DontEnum,
); );
ime.define_value( ime.define_value(
gc_context, gc_context,
"JAPANESE_KATAKANA_FULL", "JAPANESE_KATAKANA_FULL",
Avm1String::new(gc_context, "JAPANESE_KATAKANA_FULL".to_string()).into(), Avm1String::from("JAPANESE_KATAKANA_FULL").into(),
DontDelete | ReadOnly | DontEnum, DontDelete | ReadOnly | DontEnum,
); );
ime.define_value( ime.define_value(
gc_context, gc_context,
"KOREAN", "KOREAN",
Avm1String::new(gc_context, "KOREAN".to_string()).into(), Avm1String::from("KOREAN").into(),
DontDelete | ReadOnly | DontEnum, DontDelete | ReadOnly | DontEnum,
); );
ime.define_value( ime.define_value(
gc_context, gc_context,
"UNKNOWN", "UNKNOWN",
Avm1String::new(gc_context, "UNKNOWN".to_string()).into(), Avm1String::from("UNKNOWN").into(),
DontDelete | ReadOnly | DontEnum, DontDelete | ReadOnly | DontEnum,
); );

View File

@ -372,7 +372,7 @@ pub fn set_word_wrap<'gc>(
pub fn auto_size<'gc>( pub fn auto_size<'gc>(
_activation: &mut Activation<'_, 'gc>, _activation: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, _context: &mut UpdateContext<'_, 'gc, '_>,
this: Object<'gc>, this: Object<'gc>,
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
@ -381,12 +381,10 @@ pub fn auto_size<'gc>(
.and_then(|dobj| dobj.as_edit_text()) .and_then(|dobj| dobj.as_edit_text())
{ {
return Ok(match etext.autosize() { return Ok(match etext.autosize() {
AutoSizeMode::None => Avm1String::new(context.gc_context, "none".to_string()).into(), AutoSizeMode::None => Avm1String::from("none").into(),
AutoSizeMode::Left => Avm1String::new(context.gc_context, "left".to_string()).into(), AutoSizeMode::Left => Avm1String::from("left").into(),
AutoSizeMode::Center => { AutoSizeMode::Center => Avm1String::from("center").into(),
Avm1String::new(context.gc_context, "center".to_string()).into() AutoSizeMode::Right => Avm1String::from("right").into(),
}
AutoSizeMode::Right => Avm1String::new(context.gc_context, "right".to_string()).into(),
}); });
} }

View File

@ -234,7 +234,7 @@ pub fn xmlnode_to_string<'gc>(
.into()); .into());
} }
Ok(Avm1String::new(ac.gc_context, "".to_string()).into()) Ok(Avm1String::from("").into())
} }
pub fn xmlnode_local_name<'gc>( pub fn xmlnode_local_name<'gc>(

View File

@ -955,13 +955,13 @@ mod tests {
object.as_script_object().unwrap().define_value( object.as_script_object().unwrap().define_value(
context.gc_context, context.gc_context,
"forced", "forced",
Avm1String::new(context.gc_context, "forced".to_string()).into(), Avm1String::from("forced").into(),
EnumSet::empty(), EnumSet::empty(),
); );
object object
.set( .set(
"natural", "natural",
Avm1String::new(context.gc_context, "natural".to_string()).into(), Avm1String::from("natural").into(),
activation, activation,
context, context,
) )
@ -969,11 +969,11 @@ mod tests {
assert_eq!( assert_eq!(
object.get("forced", activation, context).unwrap(), object.get("forced", activation, context).unwrap(),
Avm1String::new(context.gc_context, "forced".to_string()).into() Avm1String::from("forced").into()
); );
assert_eq!( assert_eq!(
object.get("natural", activation, context).unwrap(), object.get("natural", activation, context).unwrap(),
Avm1String::new(context.gc_context, "natural".to_string()).into() Avm1String::from("natural").into()
); );
}) })
} }
@ -984,20 +984,20 @@ mod tests {
object.as_script_object().unwrap().define_value( object.as_script_object().unwrap().define_value(
context.gc_context, context.gc_context,
"normal", "normal",
Avm1String::new(context.gc_context, "initial".to_string()).into(), Avm1String::from("initial").into(),
EnumSet::empty(), EnumSet::empty(),
); );
object.as_script_object().unwrap().define_value( object.as_script_object().unwrap().define_value(
context.gc_context, context.gc_context,
"readonly", "readonly",
Avm1String::new(context.gc_context, "initial".to_string()).into(), Avm1String::from("initial").into(),
ReadOnly.into(), ReadOnly.into(),
); );
object object
.set( .set(
"normal", "normal",
Avm1String::new(context.gc_context, "replaced".to_string()).into(), Avm1String::from("replaced").into(),
activation, activation,
context, context,
) )
@ -1005,7 +1005,7 @@ mod tests {
object object
.set( .set(
"readonly", "readonly",
Avm1String::new(context.gc_context, "replaced".to_string()).into(), Avm1String::from("replaced").into(),
activation, activation,
context, context,
) )
@ -1013,11 +1013,11 @@ mod tests {
assert_eq!( assert_eq!(
object.get("normal", activation, context).unwrap(), object.get("normal", activation, context).unwrap(),
Avm1String::new(context.gc_context, "replaced".to_string()).into() Avm1String::from("replaced").into()
); );
assert_eq!( assert_eq!(
object.get("readonly", activation, context).unwrap(), object.get("readonly", activation, context).unwrap(),
Avm1String::new(context.gc_context, "initial".to_string()).into() Avm1String::from("initial").into()
); );
}) })
} }
@ -1028,14 +1028,14 @@ mod tests {
object.as_script_object().unwrap().define_value( object.as_script_object().unwrap().define_value(
context.gc_context, context.gc_context,
"test", "test",
Avm1String::new(context.gc_context, "initial".to_string()).into(), Avm1String::from("initial").into(),
DontDelete.into(), DontDelete.into(),
); );
assert_eq!(object.delete(activation, context.gc_context, "test"), false); assert_eq!(object.delete(activation, context.gc_context, "test"), false);
assert_eq!( assert_eq!(
object.get("test", activation, context).unwrap(), object.get("test", activation, context).unwrap(),
Avm1String::new(context.gc_context, "initial".to_string()).into() Avm1String::from("initial").into()
); );
object object
@ -1043,7 +1043,7 @@ mod tests {
.unwrap() .unwrap()
.set( .set(
"test", "test",
Avm1String::new(context.gc_context, "replaced".to_string()).into(), Avm1String::from("replaced").into(),
activation, activation,
context, context,
) )
@ -1052,7 +1052,7 @@ mod tests {
assert_eq!(object.delete(activation, context.gc_context, "test"), false); assert_eq!(object.delete(activation, context.gc_context, "test"), false);
assert_eq!( assert_eq!(
object.get("test", activation, context).unwrap(), object.get("test", activation, context).unwrap(),
Avm1String::new(context.gc_context, "replaced".to_string()).into() Avm1String::from("replaced").into()
); );
}) })
} }
@ -1060,8 +1060,8 @@ mod tests {
#[test] #[test]
fn test_virtual_get() { fn test_virtual_get() {
with_object(0, |activation, context, object| { with_object(0, |activation, context, object| {
let getter = Executable::Native(|_avm, context, _this, _args| { let getter = Executable::Native(|_avm, _context, _this, _args| {
Ok(Avm1String::new(context.gc_context, "Virtual!".to_string()).into()) Ok(Avm1String::from("Virtual!").into())
}); });
object.as_script_object().unwrap().add_property( object.as_script_object().unwrap().add_property(
@ -1074,21 +1074,21 @@ mod tests {
assert_eq!( assert_eq!(
object.get("test", activation, context).unwrap(), object.get("test", activation, context).unwrap(),
Avm1String::new(context.gc_context, "Virtual!".to_string()).into() Avm1String::from("Virtual!").into()
); );
// This set should do nothing // This set should do nothing
object object
.set( .set(
"test", "test",
Avm1String::new(context.gc_context, "Ignored!".to_string()).into(), Avm1String::from("Ignored!").into(),
activation, activation,
context, context,
) )
.unwrap(); .unwrap();
assert_eq!( assert_eq!(
object.get("test", activation, context).unwrap(), object.get("test", activation, context).unwrap(),
Avm1String::new(context.gc_context, "Virtual!".to_string()).into() Avm1String::from("Virtual!").into()
); );
}) })
} }
@ -1096,8 +1096,8 @@ mod tests {
#[test] #[test]
fn test_delete() { fn test_delete() {
with_object(0, |activation, context, object| { with_object(0, |activation, context, object| {
let getter = Executable::Native(|_avm, context, _this, _args| { let getter = Executable::Native(|_avm, _context, _this, _args| {
Ok(Avm1String::new(context.gc_context, "Virtual!".to_string()).into()) Ok(Avm1String::from("Virtual!").into())
}); });
object.as_script_object().unwrap().add_property( object.as_script_object().unwrap().add_property(
@ -1117,13 +1117,13 @@ mod tests {
object.as_script_object().unwrap().define_value( object.as_script_object().unwrap().define_value(
context.gc_context, context.gc_context,
"stored", "stored",
Avm1String::new(context.gc_context, "Stored!".to_string()).into(), Avm1String::from("Stored!").into(),
EnumSet::empty(), EnumSet::empty(),
); );
object.as_script_object().unwrap().define_value( object.as_script_object().unwrap().define_value(
context.gc_context, context.gc_context,
"stored_un", "stored_un",
Avm1String::new(context.gc_context, "Stored!".to_string()).into(), Avm1String::from("Stored!").into(),
DontDelete.into(), DontDelete.into(),
); );
@ -1154,7 +1154,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
object.get("virtual_un", activation, context).unwrap(), object.get("virtual_un", activation, context).unwrap(),
Avm1String::new(context.gc_context, "Virtual!".to_string()).into() Avm1String::from("Virtual!").into()
); );
assert_eq!( assert_eq!(
object.get("stored", activation, context).unwrap(), object.get("stored", activation, context).unwrap(),
@ -1162,7 +1162,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
object.get("stored_un", activation, context).unwrap(), object.get("stored_un", activation, context).unwrap(),
Avm1String::new(context.gc_context, "Stored!".to_string()).into() Avm1String::from("Stored!").into()
); );
}) })
} }

View File

@ -889,20 +889,20 @@ fn set_name<'gc>(
fn drop_target<'gc>( fn drop_target<'gc>(
_activation: &mut Activation<'_, 'gc>, _activation: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, _context: &mut UpdateContext<'_, 'gc, '_>,
_this: DisplayObject<'gc>, _this: DisplayObject<'gc>,
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
log::warn!("Unimplemented property _droptarget"); log::warn!("Unimplemented property _droptarget");
Ok(Avm1String::new(context.gc_context, "".to_string()).into()) Ok(Avm1String::from("").into())
} }
fn url<'gc>( fn url<'gc>(
_activation: &mut Activation<'_, 'gc>, _activation: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, _context: &mut UpdateContext<'_, 'gc, '_>,
_this: DisplayObject<'gc>, _this: DisplayObject<'gc>,
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
log::warn!("Unimplemented property _url"); log::warn!("Unimplemented property _url");
Ok(Avm1String::new(context.gc_context, "".to_string()).into()) Ok(Avm1String::from("").into())
} }
fn high_quality<'gc>( fn high_quality<'gc>(
@ -964,11 +964,11 @@ fn set_sound_buf_time<'gc>(
fn quality<'gc>( fn quality<'gc>(
_activation: &mut Activation<'_, 'gc>, _activation: &mut Activation<'_, 'gc>,
context: &mut UpdateContext<'_, 'gc, '_>, _context: &mut UpdateContext<'_, 'gc, '_>,
_this: DisplayObject<'gc>, _this: DisplayObject<'gc>,
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
log::warn!("Unimplemented property _quality"); log::warn!("Unimplemented property _quality");
Ok(Avm1String::new(context.gc_context, "HIGH".to_string()).into()) Ok(Avm1String::from("HIGH").into())
} }
fn set_quality<'gc>( fn set_quality<'gc>(

View File

@ -3,11 +3,22 @@ use std::ops::Deref;
#[derive(Debug, Clone, Collect)] #[derive(Debug, Clone, Collect)]
#[collect(no_drop)] #[collect(no_drop)]
pub struct Avm1String<'gc>(Gc<'gc, String>); enum Source<'gc> {
Owned(Gc<'gc, String>),
Static(&'static str),
}
#[derive(Debug, Clone, Collect)]
#[collect(no_drop)]
pub struct Avm1String<'gc> {
source: Source<'gc>,
}
impl<'gc> Avm1String<'gc> { impl<'gc> Avm1String<'gc> {
pub fn new<S: Into<String>>(gc_context: MutationContext<'gc, '_>, string: S) -> Self { pub fn new<S: Into<String>>(gc_context: MutationContext<'gc, '_>, string: S) -> Self {
Self(Gc::allocate(gc_context, string.into())) Self {
source: Source::Owned(Gc::allocate(gc_context, string.into())),
}
} }
pub fn as_str(&self) -> &str { pub fn as_str(&self) -> &str {
@ -15,19 +26,33 @@ impl<'gc> Avm1String<'gc> {
} }
} }
impl<'gc> From<&'static str> for Avm1String<'gc> {
fn from(str: &'static str) -> Self {
Self {
source: Source::Static(str),
}
}
}
impl Deref for Avm1String<'_> { impl Deref for Avm1String<'_> {
type Target = str; type Target = str;
#[inline] #[inline]
fn deref(&self) -> &str { fn deref(&self) -> &str {
self.0.deref() match &self.source {
Source::Owned(str) => str.deref(),
Source::Static(str) => str,
}
} }
} }
impl AsRef<str> for Avm1String<'_> { impl AsRef<str> for Avm1String<'_> {
#[inline] #[inline]
fn as_ref(&self) -> &str { fn as_ref(&self) -> &str {
self match &self.source {
Source::Owned(str) => str,
Source::Static(str) => str,
}
} }
} }

View File

@ -9,7 +9,7 @@ fn locals_into_form_values() {
my_locals my_locals
.set( .set(
"value1", "value1",
Avm1String::new(context.gc_context, "string".to_string()).into(), Avm1String::from("string").into(),
activation, activation,
context, context,
) )

View File

@ -323,7 +323,7 @@ impl<'gc> Loader<'gc> {
uc, uc,
"broadcastMessage", "broadcastMessage",
&[ &[
Avm1String::new(uc.gc_context, "onLoadStart".to_string()).into(), Avm1String::from("onLoadStart").into(),
Value::Object(broadcaster), Value::Object(broadcaster),
], ],
); );
@ -359,8 +359,7 @@ impl<'gc> Loader<'gc> {
uc, uc,
"broadcastMessage", "broadcastMessage",
&[ &[
Avm1String::new(uc.gc_context, "onLoadProgress".to_string()) Avm1String::from("onLoadProgress").into(),
.into(),
Value::Object(broadcaster), Value::Object(broadcaster),
length.into(), length.into(),
length.into(), length.into(),
@ -397,8 +396,7 @@ impl<'gc> Loader<'gc> {
uc, uc,
"broadcastMessage", "broadcastMessage",
&[ &[
Avm1String::new(uc.gc_context, "onLoadComplete".to_string()) Avm1String::from("onLoadComplete").into(),
.into(),
Value::Object(broadcaster), Value::Object(broadcaster),
], ],
); );
@ -438,14 +436,9 @@ impl<'gc> Loader<'gc> {
uc, uc,
"broadcastMessage", "broadcastMessage",
&[ &[
Avm1String::new(uc.gc_context, "onLoadError".to_string()) Avm1String::from("onLoadError").into(),
.into(),
Value::Object(broadcaster), Value::Object(broadcaster),
Avm1String::new( Avm1String::from("LoadNeverCompleted").into(),
uc.gc_context,
"LoadNeverCompleted".to_string(),
)
.into(),
], ],
); );
} }
@ -520,7 +513,7 @@ impl<'gc> Loader<'gc> {
loaded_clip: DisplayObject<'gc>, loaded_clip: DisplayObject<'gc>,
clip_object: Option<Object<'gc>>, clip_object: Option<Object<'gc>>,
queue: &mut ActionQueue<'gc>, queue: &mut ActionQueue<'gc>,
gc_context: MutationContext<'gc, '_>, _gc_context: MutationContext<'gc, '_>,
) -> bool { ) -> bool {
let (clip, broadcaster, load_complete) = match self { let (clip, broadcaster, load_complete) = match self {
Loader::Movie { Loader::Movie {
@ -540,7 +533,7 @@ impl<'gc> Loader<'gc> {
object: broadcaster, object: broadcaster,
name: "broadcastMessage", name: "broadcastMessage",
args: vec![ args: vec![
Avm1String::new(gc_context, "onLoadInit".to_string()).into(), Avm1String::from("onLoadInit").into(),
clip_object.map(|co| co.into()).unwrap_or(Value::Undefined), clip_object.map(|co| co.into()).unwrap_or(Value::Undefined),
], ],
}, },