Skip to content

Commit f39234f

Browse files
core/avm1/avm2: Remove Default impl for AvmString
1 parent 2d3a12d commit f39234f

File tree

13 files changed

+119
-100
lines changed

13 files changed

+119
-100
lines changed

core/src/avm1/globals/selection.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub fn get_focus<'gc>(
105105
.as_displayobject()
106106
.object()
107107
.coerce_to_string(activation)
108-
.unwrap_or_default()
108+
.unwrap_or_else(|_| activation.strings().empty())
109109
.into(),
110110
None => Value::Null,
111111
})

core/src/avm1/object/stage_object.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ impl<'gc> TObject<'gc> for StageObject<'gc> {
341341
// Button/MovieClip children are included in key list.
342342
for child in ctr.iter_render_list().rev() {
343343
if child.as_interactive().is_some() {
344-
keys.push(child.name());
344+
keys.push(child.name().expect("Interactive DisplayObjects have names"));
345345
}
346346
}
347347
}
@@ -657,8 +657,10 @@ fn frames_loaded<'gc>(
657657
.map_or(Value::Undefined, Value::from)
658658
}
659659

660-
fn name<'gc>(_activation: &mut Activation<'_, 'gc>, this: DisplayObject<'gc>) -> Value<'gc> {
661-
this.name().into()
660+
fn name<'gc>(activation: &mut Activation<'_, 'gc>, this: DisplayObject<'gc>) -> Value<'gc> {
661+
this.name()
662+
.unwrap_or_else(|| activation.strings().empty())
663+
.into()
662664
}
663665

664666
fn set_name<'gc>(

core/src/avm2/e4x.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ impl<'gc> E4XNode<'gc> {
755755
) -> Result<Vec<Self>, Error<'gc>> {
756756
let string = match &value {
757757
// The docs claim that this throws a TypeError, but it actually doesn't
758-
Value::Null | Value::Undefined => AvmString::default(),
758+
Value::Null | Value::Undefined => activation.strings().empty(),
759759
// The docs claim that only String, Number or Boolean are accepted, but that's also a lie
760760
val => {
761761
if let Some(obj) = val.as_object() {
@@ -962,7 +962,7 @@ impl<'gc> E4XNode<'gc> {
962962
} else {
963963
(
964964
AvmString::new_utf8_bytes(activation.gc(), text.as_bytes()),
965-
AvmString::default(),
965+
activation.strings().empty(),
966966
)
967967
};
968968
let node = E4XNode(GcCell::new(
@@ -1312,16 +1312,22 @@ impl<'gc> E4XNode<'gc> {
13121312
return true;
13131313
}
13141314

1315-
let self_ns = self.namespace().map(|ns| ns.uri).unwrap_or_default();
1315+
let self_ns = self.namespace().map(|ns| ns.uri);
13161316
// FIXME: For cases where we don't have *any* explicit namespace
13171317
// we just give up and assume we should match the default public namespace.
13181318
if !name.namespace_set().iter().any(|ns| ns.is_namespace()) {
1319-
return self_ns.is_empty();
1319+
return self_ns.is_none_or(|n| n.is_empty());
13201320
}
13211321

1322-
name.namespace_set()
1323-
.iter()
1324-
.any(|ns| ns.as_uri_opt().expect("NS set cannot contain Any") == self_ns)
1322+
name.namespace_set().iter().any(|ns| {
1323+
let uri = ns.as_uri_opt().expect("NS set cannot contain Any");
1324+
1325+
if let Some(self_ns) = self_ns {
1326+
uri == self_ns
1327+
} else {
1328+
uri.is_empty()
1329+
}
1330+
})
13251331
}
13261332

13271333
pub fn descendants(&self, name: &Multiname<'gc>, out: &mut Vec<E4XOrXml<'gc>>) {
@@ -1412,7 +1418,7 @@ pub fn simple_content_to_string<'gc>(
14121418
children: impl Iterator<Item = E4XOrXml<'gc>>,
14131419
activation: &mut Activation<'_, 'gc>,
14141420
) -> AvmString<'gc> {
1415-
let mut out = AvmString::default();
1421+
let mut out = activation.strings().empty();
14161422
for child in children {
14171423
if matches!(
14181424
&*child.node().kind(),

core/src/avm2/globals/flash/display/display_object.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,14 +542,17 @@ pub fn set_rotation<'gc>(
542542

543543
/// Implements `name`'s getter.
544544
pub fn get_name<'gc>(
545-
_activation: &mut Activation<'_, 'gc>,
545+
activation: &mut Activation<'_, 'gc>,
546546
this: Value<'gc>,
547547
_args: &[Value<'gc>],
548548
) -> Result<Value<'gc>, Error<'gc>> {
549549
let this = this.as_object().unwrap();
550550

551551
if let Some(dobj) = this.as_display_object() {
552-
return Ok(dobj.name().into());
552+
return Ok(dobj
553+
.name()
554+
.unwrap_or_else(|| activation.strings().empty())
555+
.into());
553556
}
554557

555558
Ok(Value::Undefined)

core/src/avm2/globals/xml.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub fn init<'gc>(
5454

5555
let node = match nodes.as_slice() {
5656
// XML defaults to an empty text node when nothing was parsed
57-
[] => E4XNode::text(activation.gc(), AvmString::default(), None),
57+
[] => E4XNode::text(activation.gc(), activation.strings().empty(), None),
5858
[node] => *node,
5959
nodes => {
6060
let mut single_element_node = None;

core/src/avm2/traits.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -405,19 +405,24 @@ fn default_value_for_type<'gc>(type_name: Option<Gc<'gc, Multiname<'gc>>>) -> Va
405405
// like `Activation::resolve_type` to get an actual `Class` object, and then check something like `Class::built_in_type`.
406406
// The Multiname is guaranteed to be static by `pool.pool_multiname_static` earlier.
407407
if type_name.contains_public_namespace() {
408-
let name = type_name.local_name().unwrap_or_default();
409-
if &name == b"Boolean" {
410-
false.into()
411-
} else if &name == b"Number" {
412-
f64::NAN.into()
413-
} else if &name == b"int" {
414-
0.into()
415-
} else if &name == b"String" {
416-
Value::Null
417-
} else if &name == b"uint" {
418-
0.into()
408+
let name = type_name.local_name();
409+
if let Some(name) = name {
410+
if &name == b"Boolean" {
411+
false.into()
412+
} else if &name == b"Number" {
413+
f64::NAN.into()
414+
} else if &name == b"int" {
415+
0.into()
416+
} else if &name == b"String" {
417+
Value::Null
418+
} else if &name == b"uint" {
419+
0.into()
420+
} else {
421+
Value::Null // Object type
422+
}
419423
} else {
420-
Value::Null // Object type
424+
// No local name?
425+
Value::Null
421426
}
422427
} else {
423428
// Object type

core/src/debug_ui/display_object.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,9 @@ impl DisplayObjectWindow {
11281128
ui.label("Name");
11291129
// &mut of a temporary thing because we don't want to actually be able to change this
11301130
// If we disable it, the user can't highlight or interact with it, so this makes it readonly but enabled
1131-
ui.text_edit_singleline(&mut object.name().to_string());
1131+
ui.text_edit_singleline(
1132+
&mut object.name().map(|s| s.to_string()).unwrap_or_default(),
1133+
);
11321134
ui.end_row();
11331135

11341136
if let crate::avm1::Value::Object(object) = object.object() {
@@ -1315,7 +1317,10 @@ impl DisplayObjectWindow {
13151317
}
13161318

13171319
fn matches_search(object: DisplayObject, search: &WStr) -> bool {
1318-
if object.name().to_ascii_lowercase().contains(search) {
1320+
if object
1321+
.name()
1322+
.is_some_and(|n| n.to_ascii_lowercase().contains(search))
1323+
{
13191324
return true;
13201325
}
13211326

@@ -1392,10 +1397,14 @@ fn summary_name(object: DisplayObject) -> Cow<'static, str> {
13921397
let do_type = display_object_type(object);
13931398
let name = object.name();
13941399

1395-
if name.is_empty() {
1396-
Cow::Borrowed(do_type)
1400+
if let Some(name) = name {
1401+
if name.is_empty() {
1402+
Cow::Borrowed(do_type)
1403+
} else {
1404+
Cow::Owned(format!("{do_type} \"{name}\""))
1405+
}
13971406
} else {
1398-
Cow::Owned(format!("{do_type} \"{name}\""))
1407+
Cow::Borrowed("")
13991408
}
14001409
}
14011410

core/src/debug_ui/movie.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ impl MovieWindow {
132132
let name = export_characters
133133
.iter()
134134
.find_map(|(k, v)| if *v == id { Some(k) } else { None })
135-
.unwrap_or_default()
136-
.to_string();
135+
.map(|s| s.to_string())
136+
.unwrap_or_default();
137137

138138
let search = self.character_search.to_ascii_lowercase();
139139
if !id.to_string().to_ascii_lowercase().contains(&search)

core/src/display_object.rs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,10 +1556,7 @@ pub trait TDisplayObject<'gc>:
15561556
}
15571557
}
15581558

1559-
fn name(&self) -> AvmString<'gc> {
1560-
self.base().name().unwrap_or_default()
1561-
}
1562-
fn name_optional(&self) -> Option<AvmString<'gc>> {
1559+
fn name(&self) -> Option<AvmString<'gc>> {
15631560
self.base().name()
15641561
}
15651562
fn set_name(&self, gc_context: &Mutation<'gc>, name: AvmString<'gc>) {
@@ -1581,7 +1578,9 @@ pub trait TDisplayObject<'gc>:
15811578
if let Some(parent) = self.avm1_parent() {
15821579
let mut path = parent.path();
15831580
path.push_byte(b'.');
1584-
path.push_str(&self.name());
1581+
if let Some(name) = self.name() {
1582+
path.push_str(&name);
1583+
}
15851584
path
15861585
} else {
15871586
WString::from_utf8_owned(format!("_level{}", self.depth()))
@@ -1595,7 +1594,9 @@ pub trait TDisplayObject<'gc>:
15951594
if let Some(parent) = object.avm1_parent() {
15961595
let mut path = build_slash_path(parent);
15971596
path.push_byte(b'/');
1598-
path.push_str(&object.name());
1597+
if let Some(name) = object.name() {
1598+
path.push_str(&name);
1599+
}
15991600
path
16001601
} else {
16011602
let level = object.depth();
@@ -2046,20 +2047,24 @@ pub trait TDisplayObject<'gc>:
20462047
if self.has_explicit_name() {
20472048
if let Some(parent @ Avm2Value::Object(_)) = self.parent().map(|p| p.object2()) {
20482049
if let Avm2Value::Object(child) = self.object2() {
2049-
let domain = context
2050-
.library
2051-
.library_for_movie(self.movie())
2052-
.unwrap()
2053-
.avm2_domain();
2054-
let mut activation = Avm2Activation::from_domain(context, domain);
2055-
let name =
2056-
Avm2Multiname::new(activation.avm2().find_public_namespace(), self.name());
2057-
if let Err(e) = parent.init_property(&name, child.into(), &mut activation) {
2058-
tracing::error!(
2059-
"Got error when setting AVM2 child named \"{}\": {}",
2060-
&self.name(),
2061-
e
2062-
);
2050+
if let Some(name) = self.name() {
2051+
let domain = context
2052+
.library
2053+
.library_for_movie(self.movie())
2054+
.unwrap()
2055+
.avm2_domain();
2056+
let mut activation = Avm2Activation::from_domain(context, domain);
2057+
let multiname =
2058+
Avm2Multiname::new(activation.avm2().find_public_namespace(), name);
2059+
if let Err(e) =
2060+
parent.init_property(&multiname, child.into(), &mut activation)
2061+
{
2062+
tracing::error!(
2063+
"Got error when setting AVM2 child named \"{}\": {}",
2064+
&name,
2065+
e
2066+
);
2067+
}
20632068
}
20642069
}
20652070
}
@@ -2138,7 +2143,7 @@ pub trait TDisplayObject<'gc>:
21382143
bounds.x_min.to_pixels(),
21392144
bounds.y_min.to_pixels(),
21402145
classname,
2141-
self.name(),
2146+
self.name().map(|s| s.to_string()).unwrap_or_default(),
21422147
self_str,
21432148
self.id(),
21442149
depth
@@ -2470,7 +2475,7 @@ pub trait TDisplayObject<'gc>:
24702475
let name = AvmString::new_utf8(context.gc(), format!("root{}", self.depth() + 1));
24712476
self.set_name(context.gc(), name);
24722477
} else {
2473-
self.set_name(context.gc(), Default::default());
2478+
self.set_name(context.gc(), context.strings.empty());
24742479
}
24752480
}
24762481

core/src/display_object/container.rs

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -718,29 +718,29 @@ impl<'gc> ChildContainer<'gc> {
718718
"Parent must be removed *after* calling `remove_child_from_render_list`",
719719
);
720720
if child.has_explicit_name() {
721-
if let Avm2Value::Object(parent_obj) = parent.object2() {
722-
let parent_obj = Avm2Value::from(parent_obj);
723-
724-
let mut activation = Avm2Activation::from_nothing(context);
725-
let name = Avm2Multiname::new(
726-
activation.avm2().find_public_namespace(),
727-
child.name(),
728-
);
729-
let current_val = parent_obj.get_property(&name, &mut activation);
730-
match current_val {
731-
Ok(Avm2Value::Null) | Ok(Avm2Value::Undefined) => {}
732-
Ok(_other) => {
733-
let res = parent_obj.set_property(
734-
&name,
735-
Avm2Value::Null,
736-
&mut activation,
737-
);
738-
if let Err(e) = res {
739-
tracing::error!("Failed to set child {} ({:?}) to null on parent obj {:?}: {:?}", child.name(), child, parent_obj, e);
721+
if let Some(name) = child.name() {
722+
if let Avm2Value::Object(parent_obj) = parent.object2() {
723+
let parent_obj = Avm2Value::from(parent_obj);
724+
725+
let mut activation = Avm2Activation::from_nothing(context);
726+
let multiname =
727+
Avm2Multiname::new(activation.avm2().find_public_namespace(), name);
728+
let current_val = parent_obj.get_property(&multiname, &mut activation);
729+
match current_val {
730+
Ok(Avm2Value::Null) | Ok(Avm2Value::Undefined) => {}
731+
Ok(_other) => {
732+
let res = parent_obj.set_property(
733+
&multiname,
734+
Avm2Value::Null,
735+
&mut activation,
736+
);
737+
if let Err(e) = res {
738+
tracing::error!("Failed to set child {} ({:?}) to null on parent obj {:?}: {:?}", name, child, parent_obj, e);
739+
}
740+
}
741+
Err(e) => {
742+
tracing::error!("Failed to get current value of child {} ({:?}) on parent obj {:?}: {:?}", name, child, parent_obj, e);
740743
}
741-
}
742-
Err(e) => {
743-
tracing::error!("Failed to get current value of child {} ({:?}) on parent obj {:?}: {:?}", child.name(), child, parent_obj, e);
744744
}
745745
}
746746
}
@@ -844,16 +844,12 @@ impl<'gc> ChildContainer<'gc> {
844844
let mut matching_render_children = if case_sensitive {
845845
self.depth_list
846846
.iter()
847-
.filter(|(_, child)| child.name_optional().is_some_and(|n| n == name))
847+
.filter(|(_, child)| child.name().is_some_and(|n| n == name))
848848
.collect::<Vec<_>>()
849849
} else {
850850
self.depth_list
851851
.iter()
852-
.filter(|(_, child)| {
853-
child
854-
.name_optional()
855-
.is_some_and(|n| n.eq_ignore_case(name))
856-
})
852+
.filter(|(_, child)| child.name().is_some_and(|n| n.eq_ignore_case(name)))
857853
.collect::<Vec<_>>()
858854
};
859855

@@ -872,13 +868,12 @@ impl<'gc> ChildContainer<'gc> {
872868
self.render_list
873869
.iter()
874870
.copied()
875-
.find(|child| child.name_optional().is_some_and(|n| n == name))
871+
.find(|child| child.name().is_some_and(|n| n == name))
876872
} else {
877-
self.render_list.iter().copied().find(|child| {
878-
child
879-
.name_optional()
880-
.is_some_and(|n| n.eq_ignore_case(name))
881-
})
873+
self.render_list
874+
.iter()
875+
.copied()
876+
.find(|child| child.name().is_some_and(|n| n.eq_ignore_case(name)))
882877
}
883878
}
884879
}

0 commit comments

Comments
 (0)