From f33976f4c0654ae75c7a1547650d9aee0b0c6969 Mon Sep 17 00:00:00 2001 From: David Wendt Date: Thu, 22 Apr 2021 22:06:38 -0400 Subject: [PATCH] avm2: Store symbol / class relationships using the class constructor, not the prototype. --- .../globals/flash/display/displayobject.rs | 23 +++++++++------- core/src/display_object/movie_clip.rs | 26 +++++-------------- core/src/library.rs | 22 ++++++++-------- 3 files changed, 31 insertions(+), 40 deletions(-) diff --git a/core/src/avm2/globals/flash/display/displayobject.rs b/core/src/avm2/globals/flash/display/displayobject.rs index 97f4c1d5c..b462f7a93 100644 --- a/core/src/avm2/globals/flash/display/displayobject.rs +++ b/core/src/avm2/globals/flash/display/displayobject.rs @@ -21,19 +21,24 @@ pub fn instance_init<'gc>( this: Option>, _args: &[Value<'gc>], ) -> Result, Error> { - if let Some(this) = this { + if let Some(mut this) = this { activation.super_init(this, &[])?; if this.as_display_object().is_none() { - let proto = this.proto(); + let constructor = this + .get_property( + this, + &QName::new(Namespace::public(), "constructor"), + activation, + )? + .coerce_to_object(activation)?; - if let Some((movie, symbol)) = proto.and_then(|proto| { - activation - .context - .library - .avm2_constructor_registry() - .proto_symbol(proto) - }) { + if let Some((movie, symbol)) = activation + .context + .library + .avm2_constructor_registry() + .constr_symbol(constructor) + { let mut child = activation .context .library diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index 2b3255090..fc4789771 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -586,26 +586,12 @@ impl<'gc> MovieClip<'gc> { .and_then(|v| v.coerce_to_object(&mut activation)); match constr { - Ok(mut constr) => { - let proto = constr - .get_property( - constr, - &Avm2QName::new(Avm2Namespace::public(), "prototype"), - &mut activation, - ) - .and_then(|v| v.coerce_to_object(&mut activation)); - match proto { - Ok(proto) => activation - .context - .library - .avm2_constructor_registry_mut() - .set_proto_symbol(proto, movie.clone(), id), - Err(e) => log::warn!( - "Got AVM2 error {} when getting prototype of symbol class {}", - e, - class_name - ), - }; + Ok(constr) => { + activation + .context + .library + .avm2_constructor_registry_mut() + .set_constr_symbol(constr, movie.clone(), id); let library = activation .context diff --git a/core/src/library.rs b/core/src/library.rs index 36be02227..cbeb2979b 100644 --- a/core/src/library.rs +++ b/core/src/library.rs @@ -79,17 +79,17 @@ impl WeakElement for WeakMovieSymbol { } } -/// The mappings between prototypes and library characters defined by +/// The mappings between constructors and library characters defined by /// `SymbolClass`. pub struct Avm2ConstructorRegistry<'gc> { - /// A list of AVM2 class prototypes and the character IDs they are expected + /// A list of AVM2 class constructors and the character IDs they are expected /// to instantiate. - proto_map: WeakValueHashMap, WeakMovieSymbol>, + constr_map: WeakValueHashMap, WeakMovieSymbol>, } unsafe impl Collect for Avm2ConstructorRegistry<'_> { fn trace(&self, cc: gc_arena::CollectionContext) { - for (k, _) in self.proto_map.iter() { + for (k, _) in self.constr_map.iter() { k.trace(cc); } } @@ -104,29 +104,29 @@ impl Default for Avm2ConstructorRegistry<'_> { impl<'gc> Avm2ConstructorRegistry<'gc> { pub fn new() -> Self { Self { - proto_map: WeakValueHashMap::new(), + constr_map: WeakValueHashMap::new(), } } - /// Retrieve the library symbol for a given AVM2 prototype. + /// Retrieve the library symbol for a given AVM2 class constructor. /// /// A value of `None` indicates that this AVM2 class is not associated with /// a library symbol. - pub fn proto_symbol(&self, proto: Avm2Object<'gc>) -> Option<(Arc, CharacterId)> { - match self.proto_map.get(&proto) { + pub fn constr_symbol(&self, proto: Avm2Object<'gc>) -> Option<(Arc, CharacterId)> { + match self.constr_map.get(&proto) { Some(MovieSymbol(movie, symbol)) => Some((movie, symbol)), None => None, } } - /// Associate an AVM2 prototype with a given library symbol. - pub fn set_proto_symbol( + /// Associate an AVM2 class constructor with a given library symbol. + pub fn set_constr_symbol( &mut self, proto: Avm2Object<'gc>, movie: Arc, symbol: CharacterId, ) { - self.proto_map.insert(proto, MovieSymbol(movie, symbol)); + self.constr_map.insert(proto, MovieSymbol(movie, symbol)); } }