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>>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, 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
if let Some((movie, symbol)) = activation
.context
.library
.avm2_constructor_registry()
.proto_symbol(proto)
}) {
.constr_symbol(constructor)
{
let mut child = activation
.context
.library

View File

@ -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
Ok(constr) => {
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
),
};
.set_constr_symbol(constr, movie.clone(), id);
let library = activation
.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`.
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<Avm2Object<'gc>, WeakMovieSymbol>,
constr_map: WeakValueHashMap<Avm2Object<'gc>, 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<SwfMovie>, CharacterId)> {
match self.proto_map.get(&proto) {
pub fn constr_symbol(&self, proto: Avm2Object<'gc>) -> Option<(Arc<SwfMovie>, 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<SwfMovie>,
symbol: CharacterId,
) {
self.proto_map.insert(proto, MovieSymbol(movie, symbol));
self.constr_map.insert(proto, MovieSymbol(movie, symbol));
}
}