avm2: Cache all `Vector` applications on the `Vector` class object.
This matches Flash Player behavior: notably, multiple applications of the same types see the same class and prototype, but different applications actually create new objects that don't share properties.
This commit is contained in:
parent
9a1b864988
commit
96afc5a6c2
|
@ -13,6 +13,7 @@ use crate::avm2::value::Value;
|
||||||
use crate::avm2::Error;
|
use crate::avm2::Error;
|
||||||
use crate::{impl_avm2_custom_object, impl_avm2_custom_object_properties};
|
use crate::{impl_avm2_custom_object, impl_avm2_custom_object_properties};
|
||||||
use gc_arena::{Collect, GcCell, MutationContext};
|
use gc_arena::{Collect, GcCell, MutationContext};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
/// An Object which can be called to execute its function code.
|
/// An Object which can be called to execute its function code.
|
||||||
#[derive(Collect, Debug, Clone, Copy)]
|
#[derive(Collect, Debug, Clone, Copy)]
|
||||||
|
@ -45,6 +46,11 @@ pub struct ClassObjectData<'gc> {
|
||||||
|
|
||||||
/// The native instance constructor function
|
/// The native instance constructor function
|
||||||
native_constructor: Executable<'gc>,
|
native_constructor: Executable<'gc>,
|
||||||
|
|
||||||
|
/// List of all applications of this class.
|
||||||
|
///
|
||||||
|
/// Only applicable if this class is generic.
|
||||||
|
applications: HashMap<Object<'gc>, Object<'gc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'gc> ClassObject<'gc> {
|
impl<'gc> ClassObject<'gc> {
|
||||||
|
@ -128,6 +134,7 @@ impl<'gc> ClassObject<'gc> {
|
||||||
instance_allocator: Allocator(instance_allocator),
|
instance_allocator: Allocator(instance_allocator),
|
||||||
constructor,
|
constructor,
|
||||||
native_constructor,
|
native_constructor,
|
||||||
|
applications: HashMap::new(),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -182,6 +189,7 @@ impl<'gc> ClassObject<'gc> {
|
||||||
instance_allocator: Allocator(instance_allocator),
|
instance_allocator: Allocator(instance_allocator),
|
||||||
constructor,
|
constructor,
|
||||||
native_constructor,
|
native_constructor,
|
||||||
|
applications: HashMap::new(),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.into();
|
.into();
|
||||||
|
@ -497,6 +505,19 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
|
||||||
return Err(format!("Class {:?} was already applied", self_class.read().name()).into());
|
return Err(format!("Class {:?} was already applied", self_class.read().name()).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if params.len() != 1 {
|
||||||
|
return Err(format!(
|
||||||
|
"Class {:?} only accepts one type parameter, {} given",
|
||||||
|
self_class.read().name(),
|
||||||
|
params.len()
|
||||||
|
)
|
||||||
|
.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(application) = self.0.read().applications.get(¶ms[0]) {
|
||||||
|
return Ok(*application);
|
||||||
|
}
|
||||||
|
|
||||||
let mut class_params = Vec::new();
|
let mut class_params = Vec::new();
|
||||||
for param in params {
|
for param in params {
|
||||||
class_params.push(param.as_class().ok_or(format!(
|
class_params.push(param.as_class().ok_or(format!(
|
||||||
|
@ -544,6 +565,7 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
|
||||||
instance_allocator,
|
instance_allocator,
|
||||||
constructor,
|
constructor,
|
||||||
native_constructor,
|
native_constructor,
|
||||||
|
applications: HashMap::new(),
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@ -552,6 +574,11 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
|
||||||
class_object.install_traits(activation, parameterized_class.read().class_traits())?;
|
class_object.install_traits(activation, parameterized_class.read().class_traits())?;
|
||||||
class_object.run_class_initializer(activation)?;
|
class_object.run_class_initializer(activation)?;
|
||||||
|
|
||||||
|
self.0
|
||||||
|
.write(activation.context.gc_context)
|
||||||
|
.applications
|
||||||
|
.insert(params[0], class_object.into());
|
||||||
|
|
||||||
Ok(class_object.into())
|
Ok(class_object.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue