avm2: Store symbol / class relationships using the class constructor, not the prototype.

This commit is contained in:
David Wendt 2021-04-22 22:06:38 -04:00 committed by Mike Welsh
parent 0ee9e0f820
commit f33976f4c0
3 changed files with 31 additions and 40 deletions

View File

@ -21,19 +21,24 @@ pub fn instance_init<'gc>(
this: Option<Object<'gc>>, this: Option<Object<'gc>>,
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Value<'gc>, Error> { ) -> Result<Value<'gc>, Error> {
if let Some(this) = this { if let Some(mut this) = this {
activation.super_init(this, &[])?; activation.super_init(this, &[])?;
if this.as_display_object().is_none() { 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| { if let Some((movie, symbol)) = activation
activation
.context .context
.library .library
.avm2_constructor_registry() .avm2_constructor_registry()
.proto_symbol(proto) .constr_symbol(constructor)
}) { {
let mut child = activation let mut child = activation
.context .context
.library .library

View File

@ -586,26 +586,12 @@ impl<'gc> MovieClip<'gc> {
.and_then(|v| v.coerce_to_object(&mut activation)); .and_then(|v| v.coerce_to_object(&mut activation));
match constr { match constr {
Ok(mut constr) => { Ok(constr) => {
let proto = constr activation
.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 .context
.library .library
.avm2_constructor_registry_mut() .avm2_constructor_registry_mut()
.set_proto_symbol(proto, movie.clone(), id), .set_constr_symbol(constr, movie.clone(), id);
Err(e) => log::warn!(
"Got AVM2 error {} when getting prototype of symbol class {}",
e,
class_name
),
};
let library = activation let library = activation
.context .context

View File

@ -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`. /// `SymbolClass`.
pub struct Avm2ConstructorRegistry<'gc> { 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. /// to instantiate.
proto_map: WeakValueHashMap<Avm2Object<'gc>, WeakMovieSymbol>, constr_map: WeakValueHashMap<Avm2Object<'gc>, WeakMovieSymbol>,
} }
unsafe impl Collect for Avm2ConstructorRegistry<'_> { unsafe impl Collect for Avm2ConstructorRegistry<'_> {
fn trace(&self, cc: gc_arena::CollectionContext) { fn trace(&self, cc: gc_arena::CollectionContext) {
for (k, _) in self.proto_map.iter() { for (k, _) in self.constr_map.iter() {
k.trace(cc); k.trace(cc);
} }
} }
@ -104,29 +104,29 @@ impl Default for Avm2ConstructorRegistry<'_> {
impl<'gc> Avm2ConstructorRegistry<'gc> { impl<'gc> Avm2ConstructorRegistry<'gc> {
pub fn new() -> Self { pub fn new() -> Self {
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 value of `None` indicates that this AVM2 class is not associated with
/// a library symbol. /// a library symbol.
pub fn proto_symbol(&self, proto: Avm2Object<'gc>) -> Option<(Arc<SwfMovie>, CharacterId)> { pub fn constr_symbol(&self, proto: Avm2Object<'gc>) -> Option<(Arc<SwfMovie>, CharacterId)> {
match self.proto_map.get(&proto) { match self.constr_map.get(&proto) {
Some(MovieSymbol(movie, symbol)) => Some((movie, symbol)), Some(MovieSymbol(movie, symbol)) => Some((movie, symbol)),
None => None, None => None,
} }
} }
/// Associate an AVM2 prototype with a given library symbol. /// Associate an AVM2 class constructor with a given library symbol.
pub fn set_proto_symbol( pub fn set_constr_symbol(
&mut self, &mut self,
proto: Avm2Object<'gc>, proto: Avm2Object<'gc>,
movie: Arc<SwfMovie>, movie: Arc<SwfMovie>,
symbol: CharacterId, symbol: CharacterId,
) { ) {
self.proto_map.insert(proto, MovieSymbol(movie, symbol)); self.constr_map.insert(proto, MovieSymbol(movie, symbol));
} }
} }