avm2: Store symbol / class relationships using the class constructor, not the prototype.
This commit is contained in:
parent
0ee9e0f820
commit
f33976f4c0
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue