avm2: Make `QName` a copy type.

This commit is contained in:
David Wendt 2021-11-27 12:50:13 -05:00 committed by kmeisthax
parent d53abfebf4
commit 769c45add5
22 changed files with 172 additions and 208 deletions

View File

@ -1468,7 +1468,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
let name = name_value.coerce_to_string(self)?;
let qname = QName::new(Namespace::public(), name);
let has_prop = obj.has_property_via_in(self, &qname)?;
let has_prop = obj.has_property_via_in(self, qname)?;
self.context.avm2.push(has_prop);

View File

@ -497,8 +497,8 @@ impl<'gc> Class<'gc> {
))
}
pub fn name(&self) -> &QName<'gc> {
&self.name
pub fn name(&self) -> QName<'gc> {
self.name
}
pub fn set_name(&mut self, name: QName<'gc>) {
@ -727,7 +727,7 @@ impl<'gc> Class<'gc> {
}
/// Determines if this class provides a given trait on its instances.
pub fn has_instance_trait(&self, name: &QName<'gc>) -> bool {
pub fn has_instance_trait(&self, name: QName<'gc>) -> bool {
for trait_entry in self.instance_traits.iter() {
if name == trait_entry.name() {
return true;

View File

@ -110,14 +110,14 @@ impl<'gc> Domain<'gc> {
if let Some(local_name) = multiname.local_name() {
for (qname, script) in read.defs.iter() {
if qname.local_name() == local_name {
return Ok(Some((qname.clone(), *script)));
return Ok(Some((*qname, *script)));
}
}
} else {
return Ok(None);
}
} else if let Some(name) = multiname.local_name() {
let qname = QName::new(ns.clone(), name);
let qname = QName::new(*ns, name);
if read.defs.contains_key(&qname) {
let script = read.defs.get(&qname).cloned().unwrap();
return Ok(Some((qname, script)));
@ -141,11 +141,11 @@ impl<'gc> Domain<'gc> {
name: QName<'gc>,
) -> Result<Value<'gc>, Error> {
let (name, mut script) = self
.get_defining_script(&name.clone().into())?
.get_defining_script(&name.into())?
.ok_or_else(|| format!("MovieClip Symbol {} does not exist", name.local_name()))?;
let globals = script.globals(&mut activation.context)?;
globals.get_property(globals, &name.clone().into(), activation)
globals.get_property(globals, &name.into(), activation)
}
/// Export a definition from a script into the current application domain.
@ -158,7 +158,7 @@ impl<'gc> Domain<'gc> {
script: Script<'gc>,
mc: MutationContext<'gc, '_>,
) -> Result<(), Error> {
if self.has_definition(name.clone()) {
if self.has_definition(name) {
return Err(format!(
"VerifyError: Attempted to redefine existing name {}",
name.local_name()

View File

@ -312,7 +312,7 @@ fn function<'gc>(
let qname = QName::new(Namespace::package(package), name);
let method = Method::from_builtin(nf, name, mc);
let as3fn = FunctionObject::from_method(activation, method, scope, None, None).into();
domain.export_definition(qname.clone(), script, mc)?;
domain.export_definition(qname, script, mc)?;
script
.init()
.1
@ -333,9 +333,9 @@ fn dynamic_class<'gc>(
) -> Result<(), Error> {
let (_, mut global, mut domain) = script.init();
let class = class_object.inner_class_definition();
let name = class.read().name().clone();
let name = class.read().name();
global.install_const(mc, name.clone(), 0, class_object.into());
global.install_const(mc, name, 0, class_object.into());
domain.export_definition(name, script, mc)
}
@ -372,13 +372,13 @@ fn class<'gc>(
None
};
let class_name = class_read.name().clone();
let class_name = class_read.name();
drop(class_read);
let class_object = ClassObject::from_class(activation, class_def, super_class)?;
global.install_const(
activation.context.gc_context,
class_name.clone(),
class_name,
0,
class_object.into(),
);
@ -405,7 +405,7 @@ fn constant<'gc>(
) -> Result<(), Error> {
let (_, mut global, mut domain) = script.init();
let name = QName::new(Namespace::package(package), name);
domain.export_definition(name.clone(), script, mc)?;
domain.export_definition(name, script, mc)?;
global.install_const(mc, name, 0, value);
Ok(())

View File

@ -21,9 +21,7 @@ pub fn instance_init<'gc>(
if let Some(this) = this {
activation.super_init(this, &[])?;
let name = this
.instance_of_class_definition()
.map(|c| c.read().name().clone());
let name = this.instance_of_class_definition().map(|c| c.read().name());
let character = this
.instance_of()
.and_then(|t| {

View File

@ -168,7 +168,7 @@ pub fn has_own_property<'gc>(
let name = name?.coerce_to_string(activation)?;
let qname = QName::dynamic_name(name);
Ok(this.has_own_property(&qname)?.into())
Ok(this.has_own_property(qname)?.into())
}
/// `Object.prototype.isPrototypeOf`
@ -205,7 +205,7 @@ pub fn property_is_enumerable<'gc>(
let name = name?.coerce_to_string(activation)?;
let qname = QName::dynamic_name(name);
Ok(this.property_is_enumerable(&qname).into())
Ok(this.property_is_enumerable(qname).into())
}
/// `Object.prototype.setPropertyIsEnumerable`
@ -221,7 +221,7 @@ pub fn set_property_is_enumerable<'gc>(
if let Some(Value::Bool(is_enum)) = args.get(1) {
let qname = QName::dynamic_name(name);
this.set_local_property_is_enumerable(activation.context.gc_context, &qname, *is_enum)?;
this.set_local_property_is_enumerable(activation.context.gc_context, qname, *is_enum)?;
}
Ok(Value::Undefined)

View File

@ -22,9 +22,7 @@ pub fn instance_init<'gc>(
let local_arg = args.get(1).cloned().unwrap_or(Value::Undefined);
let namespace = match ns_arg {
Value::Object(o) if o.as_namespace().is_some() => {
o.as_namespace().unwrap().clone()
}
Value::Object(o) if o.as_namespace().is_some() => *o.as_namespace().unwrap(),
Value::Undefined | Value::Null => Namespace::Any,
v => Namespace::Namespace(v.coerce_to_string(activation)?),
};
@ -33,13 +31,9 @@ pub fn instance_init<'gc>(
} else {
let qname_arg = args.get(0).cloned().unwrap_or(Value::Undefined);
let namespace = match qname_arg {
Value::Object(o) if o.as_qname_object().is_some() => o
.as_qname_object()
.unwrap()
.qname()
.unwrap()
.namespace()
.clone(),
Value::Object(o) if o.as_qname_object().is_some() => {
o.as_qname_object().unwrap().qname().unwrap().namespace()
}
_ => Namespace::Namespace("".into()),
};

View File

@ -217,14 +217,14 @@ pub fn exec<'gc>(
object.set_property_local(
object,
&QName::new(Namespace::public(), "index"),
QName::new(Namespace::public(), "index"),
Value::Number(index as f64),
activation,
)?;
object.set_property_local(
object,
&QName::new(Namespace::public(), "input"),
QName::new(Namespace::public(), "input"),
text.into(),
activation,
)?;

View File

@ -69,11 +69,11 @@ pub fn class_init<'gc>(
int_vector_class
.inner_class_definition()
.write(activation.context.gc_context)
.set_name(int_vector_name.clone());
.set_name(int_vector_name);
globals.install_const(
activation.context.gc_context,
int_vector_name.clone(),
int_vector_name,
0,
int_vector_class.into(),
);
@ -85,11 +85,11 @@ pub fn class_init<'gc>(
uint_vector_class
.inner_class_definition()
.write(activation.context.gc_context)
.set_name(uint_vector_name.clone());
.set_name(uint_vector_name);
globals.install_const(
activation.context.gc_context,
uint_vector_name.clone(),
uint_vector_name,
0,
uint_vector_class.into(),
);
@ -101,11 +101,11 @@ pub fn class_init<'gc>(
number_vector_class
.inner_class_definition()
.write(activation.context.gc_context)
.set_name(number_vector_name.clone());
.set_name(number_vector_name);
globals.install_const(
activation.context.gc_context,
number_vector_name.clone(),
number_vector_name,
0,
number_vector_class.into(),
);
@ -116,11 +116,11 @@ pub fn class_init<'gc>(
object_vector_class
.inner_class_definition()
.write(activation.context.gc_context)
.set_name(object_vector_name.clone());
.set_name(object_vector_name);
globals.install_const(
activation.context.gc_context,
object_vector_name.clone(),
object_vector_name,
0,
object_vector_class.into(),
);

View File

@ -13,7 +13,7 @@ use swf::avm2::types::{
/// Represents the name of a namespace.
#[allow(clippy::enum_variant_names)]
#[derive(Clone, Collect, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Clone, Copy, Collect, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[collect(no_drop)]
pub enum Namespace<'gc> {
Namespace(AvmString<'gc>),
@ -139,7 +139,7 @@ impl<'gc> Namespace<'gc> {
/// `QName`. All other forms of names and multinames are either versions of
/// `QName` with unspecified parameters, or multiple names to be checked in
/// order.
#[derive(Clone, Collect, Debug, Hash)]
#[derive(Clone, Copy, Collect, Debug, Hash)]
#[collect(no_drop)]
pub struct QName<'gc> {
ns: Namespace<'gc>,
@ -225,7 +225,7 @@ impl<'gc> QName<'gc> {
}
/// Converts this `QName` to a fully qualified name.
pub fn to_qualified_name(&self, mc: MutationContext<'gc, '_>) -> AvmString<'gc> {
pub fn to_qualified_name(self, mc: MutationContext<'gc, '_>) -> AvmString<'gc> {
let uri = self.namespace().as_uri();
let name = self.local_name();
uri.is_empty().then(|| name).unwrap_or_else(|| {
@ -240,8 +240,8 @@ impl<'gc> QName<'gc> {
self.name
}
pub fn namespace(&self) -> &Namespace<'gc> {
&self.ns
pub fn namespace(self) -> Namespace<'gc> {
self.ns
}
/// Get the string value of this QName, including the namespace URI.
@ -377,9 +377,10 @@ impl<'gc> Multiname<'gc> {
}
}
AbcMultiname::RTQName { name } | AbcMultiname::RTQNameA { name } => {
let ns = activation.avm2().pop().as_namespace()?.clone();
let ns_value = activation.avm2().pop();
let ns = ns_value.as_namespace()?;
Self {
ns: vec![ns],
ns: vec![*ns],
name: translation_unit
.pool_string_option(name.0, activation.context.gc_context)?,
params: Vec::new(),
@ -387,9 +388,10 @@ impl<'gc> Multiname<'gc> {
}
AbcMultiname::RTQNameL | AbcMultiname::RTQNameLA => {
let name = activation.avm2().pop().coerce_to_string(activation)?;
let ns = activation.avm2().pop().as_namespace()?.clone();
let ns_value = activation.avm2().pop();
let ns = ns_value.as_namespace()?;
Self {
ns: vec![ns],
ns: vec![*ns],
name: Some(name),
params: Vec::new(),
}
@ -597,7 +599,7 @@ impl<'gc> Multiname<'gc> {
let ns_match = self
.ns
.iter()
.any(|ns| ns == &Namespace::Any || ns == name.namespace());
.any(|ns| *ns == Namespace::Any || *ns == name.namespace());
let name_match = self.name.map(|n| n == name.local_name()).unwrap_or(true);
ns_match && name_match

View File

@ -121,7 +121,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
fn get_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<Value<'gc>, Error> {
let base = self.base();
@ -178,18 +178,13 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
// At this point, the name must be a valid QName.
let name = name.unwrap();
if !self.base().has_own_instantiated_property(&name) {
if !self.base().has_own_instantiated_property(name) {
// Initialize lazy-bound methods at this point in time.
if let Some(class) = self.instance_of() {
if let Some((bound_method, disp_id)) =
class.bound_instance_method(activation, receiver, &name)?
class.bound_instance_method(activation, receiver, name)?
{
self.install_method(
activation.context.gc_context,
name.clone(),
disp_id,
bound_method,
);
self.install_method(activation.context.gc_context, name, disp_id, bound_method);
return Ok(bound_method.into());
}
@ -197,25 +192,18 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
// Class methods are also lazy-bound.
if let Some(class) = self.as_class_object() {
if let Some((bound_method, disp_id)) =
class.bound_class_method(activation, &name)?
{
self.install_method(
activation.context.gc_context,
name.clone(),
disp_id,
bound_method,
);
if let Some((bound_method, disp_id)) = class.bound_class_method(activation, name)? {
self.install_method(activation.context.gc_context, name, disp_id, bound_method);
return Ok(bound_method.into());
}
}
}
let is_set_only = self.base().has_own_virtual_set_only_property(&name);
let is_set_only = self.base().has_own_virtual_set_only_property(name);
if self.has_own_property(&name)? && !is_set_only {
return self.get_property_local(receiver, &name, activation);
if self.has_own_property(name)? && !is_set_only {
return self.get_property_local(receiver, name, activation);
}
if let Some(proto) = self.proto() {
@ -233,7 +221,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
fn set_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<(), Error> {
@ -311,7 +299,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
// Reject attempts to overwrite lazy-bound methods before they have
// been bound.
if let Some(class) = self.instance_of() {
if class.instance_method(&name)?.is_some() {
if class.instance_method(name)?.is_some() {
return Err(format!(
"Cannot overwrite read-only property {:?}",
name.local_name()
@ -321,7 +309,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
}
if let Some(class) = self.as_class_object() {
if class.class_method(&name)?.is_some() {
if class.class_method(name)?.is_some() {
return Err(format!(
"Cannot overwrite read-only property {:?}",
name.local_name()
@ -330,7 +318,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
}
}
self.set_property_local(receiver, &name, value, activation)
self.set_property_local(receiver, name, value, activation)
}
/// Initialize a property by QName, after multiname resolution and all
@ -341,7 +329,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
fn init_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<(), Error> {
@ -381,7 +369,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
// Reject attempts to overwrite lazy-bound methods before they have
// been bound.
if let Some(class) = self.instance_of() {
if class.instance_method(&name)?.is_some() {
if class.instance_method(name)?.is_some() {
return Err(format!(
"Cannot overwrite read-only property {:?}",
name.local_name()
@ -391,7 +379,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
}
if let Some(class) = self.as_class_object() {
if class.class_method(&name)?.is_some() {
if class.class_method(name)?.is_some() {
return Err(format!(
"Cannot overwrite read-only property {:?}",
name.local_name()
@ -400,7 +388,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
}
}
self.init_property_local(receiver, &name, value, activation)
self.init_property_local(receiver, name, value, activation)
}
/// Call a named property that does not exist.
@ -439,7 +427,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
let name = name.unwrap();
if let Some(class) = self.instance_of() {
if let Some((superclass, method_trait)) = class.instance_method(&name)? {
if let Some((superclass, method_trait)) = class.instance_method(name)? {
let method = method_trait.as_method().unwrap();
if !method.needs_arguments_object() {
let scope = class.instance_scope();
@ -455,7 +443,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
}
if let Some(class) = self.as_class_object() {
if let Some(method_trait) = class.class_method(&name)? {
if let Some(method_trait) = class.class_method(name)? {
let method = method_trait.as_method().unwrap();
if !method.needs_arguments_object() {
let scope = class.class_scope();
@ -532,12 +520,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
if let Some((bound_method, name)) =
class.bound_instance_method_by_id(activation, self.into(), id)?
{
self.install_method(
activation.context.gc_context,
name.clone(),
id,
bound_method,
);
self.install_method(activation.context.gc_context, name, id, bound_method);
}
}
@ -545,12 +528,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
if let Some((bound_method, name)) =
class.bound_class_method_by_id(activation, id)?
{
self.install_method(
activation.context.gc_context,
name.clone(),
id,
bound_method,
);
self.install_method(activation.context.gc_context, name, id, bound_method);
}
}
}
@ -576,7 +554,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
if let Some(name) = multiname.local_name() {
for ns in matching_set.iter() {
if multiname.namespace_set().any(|n| n == ns) {
return Ok(Some(QName::new(ns.clone(), name)));
return Ok(Some(QName::new(*ns, name)));
}
}
}
@ -584,7 +562,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
if multiname.namespace_set().any(|n| *n == Namespace::Any) {
return Ok(matching_set
.first()
.map(|ns| QName::new(ns.clone(), multiname.local_name().unwrap())));
.map(|ns| QName::new(*ns, multiname.local_name().unwrap())));
}
if let Some(proto) = self.proto() {
@ -616,13 +594,13 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
fn has_property_via_in(
self,
_activation: &mut Activation<'_, 'gc, '_>,
name: &QName<'gc>,
name: QName<'gc>,
) -> Result<bool, Error> {
self.has_property(name)
}
/// Indicates whether or not a property exists on an object.
fn has_property(self, name: &QName<'gc>) -> Result<bool, Error> {
fn has_property(self, name: QName<'gc>) -> Result<bool, Error> {
if self.has_own_property(name)? {
Ok(true)
} else if let Some(proto) = self.proto() {
@ -634,14 +612,14 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
/// Indicates whether or not a property or trait exists on an object and is
/// not part of the prototype chain.
fn has_own_property(self, name: &QName<'gc>) -> Result<bool, Error> {
fn has_own_property(self, name: QName<'gc>) -> Result<bool, Error> {
let base = self.base();
base.has_own_property(name)
}
/// Returns true if an object has one or more traits of a given name.
fn has_trait(self, name: &QName<'gc>) -> Result<bool, Error> {
fn has_trait(self, name: QName<'gc>) -> Result<bool, Error> {
let base = self.base();
base.has_trait(name)
@ -651,7 +629,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
fn is_property_overwritable(
self,
_gc_context: MutationContext<'gc, '_>,
name: &QName<'gc>,
name: QName<'gc>,
) -> bool {
let base = self.base();
@ -666,7 +644,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
fn delete_property_local(
&self,
gc_context: MutationContext<'gc, '_>,
name: &QName<'gc>,
name: QName<'gc>,
) -> Result<bool, Error> {
let mut base = self.base_mut(gc_context);
@ -710,10 +688,10 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
// Reject attempts to delete lazy-bound methods before they have
// been bound.
if !self.base().has_own_instantiated_property(&name) {
if !self.base().has_own_instantiated_property(name) {
if let Some(class) = self.instance_of() {
if class
.instance_method(&name)
.instance_method(name)
.map(|t| t.is_some())
.unwrap_or(false)
{
@ -723,7 +701,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
if let Some(class) = self.as_class_object() {
if class
.class_method(&name)
.class_method(name)
.map(|t| t.is_some())
.unwrap_or(false)
{
@ -732,7 +710,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
}
}
self.delete_property_local(activation.context.gc_context, &name)
self.delete_property_local(activation.context.gc_context, name)
}
/// Retrieve the `__proto__` of a given object.
@ -812,7 +790,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
/// Determine if a property is currently enumerable.
///
/// Properties that do not exist are also not enumerable.
fn property_is_enumerable(&self, name: &QName<'gc>) -> bool {
fn property_is_enumerable(&self, name: QName<'gc>) -> bool {
let base = self.base();
base.property_is_enumerable(name)
@ -822,7 +800,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
fn set_local_property_is_enumerable(
&self,
mc: MutationContext<'gc, '_>,
name: &QName<'gc>,
name: QName<'gc>,
is_enumerable: bool,
) -> Result<(), Error> {
let mut base = self.base_mut(mc);
@ -985,7 +963,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
defining_class: Option<ClassObject<'gc>>,
) -> Result<Value<'gc>, Error> {
let receiver = (*self).into();
let trait_name = trait_entry.name().clone();
let trait_name = trait_entry.name();
avm_debug!(
activation.avm2(),

View File

@ -90,7 +90,7 @@ impl<'gc> TObject<'gc> for ArrayObject<'gc> {
fn get_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<Value<'gc>, Error> {
let read = self.0.read();
@ -111,7 +111,7 @@ impl<'gc> TObject<'gc> for ArrayObject<'gc> {
fn set_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<(), Error> {
@ -139,7 +139,7 @@ impl<'gc> TObject<'gc> for ArrayObject<'gc> {
fn init_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<(), Error> {
@ -167,7 +167,7 @@ impl<'gc> TObject<'gc> for ArrayObject<'gc> {
fn delete_property_local(
&self,
gc_context: MutationContext<'gc, '_>,
name: &QName<'gc>,
name: QName<'gc>,
) -> Result<bool, Error> {
if name.namespace().is_public() {
if let Ok(index) = name.local_name().parse::<usize>() {
@ -179,7 +179,7 @@ impl<'gc> TObject<'gc> for ArrayObject<'gc> {
Ok(self.0.write(gc_context).base.delete_property(name))
}
fn has_own_property(self, name: &QName<'gc>) -> Result<bool, Error> {
fn has_own_property(self, name: QName<'gc>) -> Result<bool, Error> {
if name.namespace().is_public() {
if let Ok(index) = name.local_name().parse::<usize>() {
return Ok(self.0.read().array.get(index).is_some());
@ -239,7 +239,7 @@ impl<'gc> TObject<'gc> for ArrayObject<'gc> {
}
}
fn property_is_enumerable(&self, name: &QName<'gc>) -> bool {
fn property_is_enumerable(&self, name: QName<'gc>) -> bool {
name.local_name()
.parse::<u32>()
.map(|index| self.0.read().array.length() as u32 >= index)

View File

@ -81,7 +81,7 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> {
fn get_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<Value<'gc>, Error> {
let read = self.0.read();
@ -106,7 +106,7 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> {
fn set_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<(), Error> {
@ -136,7 +136,7 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> {
fn init_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<(), Error> {
@ -166,7 +166,7 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> {
fn delete_property_local(
&self,
gc_context: MutationContext<'gc, '_>,
name: &QName<'gc>,
name: QName<'gc>,
) -> Result<bool, Error> {
if name.namespace().is_public() {
if let Ok(index) = name.local_name().parse::<usize>() {
@ -178,7 +178,7 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> {
Ok(self.0.write(gc_context).base.delete_property(name))
}
fn has_own_property(self, name: &QName<'gc>) -> Result<bool, Error> {
fn has_own_property(self, name: QName<'gc>) -> Result<bool, Error> {
if name.namespace().is_public() {
if let Ok(index) = name.local_name().parse::<usize>() {
return Ok(self.0.read().storage.get(index).is_some());

View File

@ -331,7 +331,7 @@ impl<'gc> ClassObject<'gc> {
} else {
write
.resolved_class_traits
.insert(trait_data.name().clone(), vec![trait_data.clone()]);
.insert(trait_data.name(), vec![trait_data.clone()]);
}
}
@ -391,7 +391,7 @@ impl<'gc> ClassObject<'gc> {
} else {
write
.resolved_instance_traits
.insert(trait_data.name().clone(), vec![new_trait_slot]);
.insert(trait_data.name(), vec![new_trait_slot]);
}
}
@ -457,14 +457,14 @@ impl<'gc> ClassObject<'gc> {
.0
.read()
.resolved_instance_traits
.get(&public_name)
.get(public_name)
.cloned();
if let Some(trait_slot) = trait_slot {
self.0
.write(activation.context.gc_context)
.resolved_instance_traits
.insert(interface_trait.name().clone(), trait_slot);
.insert(interface_trait.name(), trait_slot);
}
}
}
@ -532,7 +532,7 @@ impl<'gc> ClassObject<'gc> {
/// trait exists with the requested parameters.
pub fn lookup_instance_traits(
self,
name: &QName<'gc>,
name: QName<'gc>,
filter: fn(&Trait<'gc>) -> bool,
) -> Option<(ClassObject<'gc>, Trait<'gc>)> {
self.0
@ -544,7 +544,7 @@ impl<'gc> ClassObject<'gc> {
}
/// Determine if we have an instance trait with a given name.
pub fn has_instance_trait(self, name: &QName<'gc>) -> bool {
pub fn has_instance_trait(self, name: QName<'gc>) -> bool {
self.0.read().resolved_instance_traits.get(name).is_some()
}
@ -708,7 +708,7 @@ impl<'gc> ClassObject<'gc> {
let name = name.unwrap();
let lookup_result =
self.lookup_instance_traits(&name, |t| matches!(t.kind(), TraitKind::Method { .. }));
self.lookup_instance_traits(name, |t| matches!(t.kind(), TraitKind::Method { .. }));
if let Some((superclass_object, method_trait)) = lookup_result {
let scope = superclass_object.class_scope();
@ -769,7 +769,7 @@ impl<'gc> ClassObject<'gc> {
let name = name.unwrap();
let lookup_result =
self.lookup_instance_traits(&name, |t| matches!(t.kind(), TraitKind::Getter { .. }));
self.lookup_instance_traits(name, |t| matches!(t.kind(), TraitKind::Getter { .. }));
if let Some((superclass_object, method_trait)) = lookup_result {
let scope = superclass_object.class_scope();
@ -832,7 +832,7 @@ impl<'gc> ClassObject<'gc> {
let name = name.unwrap();
let lookup_result =
self.lookup_instance_traits(&name, |t| matches!(t.kind(), TraitKind::Setter { .. }));
self.lookup_instance_traits(name, |t| matches!(t.kind(), TraitKind::Setter { .. }));
if let Some((superclass_object, method_trait)) = lookup_result {
let scope = superclass_object.class_scope();
@ -858,7 +858,7 @@ impl<'gc> ClassObject<'gc> {
/// If a trait is returned, it is guaranteed to have a method.
pub fn instance_method(
self,
name: &QName<'gc>,
name: QName<'gc>,
) -> Result<Option<(ClassObject<'gc>, Trait<'gc>)>, Error> {
Ok(self.lookup_instance_traits(name, |t| matches!(t.kind(), TraitKind::Method { .. })))
}
@ -877,7 +877,7 @@ impl<'gc> ClassObject<'gc> {
self,
activation: &mut Activation<'_, 'gc, '_>,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
) -> Result<Option<(Object<'gc>, u32)>, Error> {
if let Some((superclass, method_trait)) = self.instance_method(name)? {
let method = method_trait.as_method().unwrap();
@ -923,7 +923,7 @@ impl<'gc> ClassObject<'gc> {
TraitKind::Method { .. } => Some(t),
_ => None,
}) {
let name = method_trait.name().clone();
let name = method_trait.name();
let method = method_trait.as_method().unwrap();
let scope = self.instance_scope();
@ -951,7 +951,7 @@ impl<'gc> ClassObject<'gc> {
/// trait exists with the requested parameters.
pub fn lookup_class_traits(
self,
name: &QName<'gc>,
name: QName<'gc>,
filter: fn(&Trait<'gc>) -> bool,
) -> Option<Trait<'gc>> {
self.0
@ -963,7 +963,7 @@ impl<'gc> ClassObject<'gc> {
}
/// Determine if we have a class trait with a given name.
pub fn has_class_trait(self, name: &QName<'gc>) -> bool {
pub fn has_class_trait(self, name: QName<'gc>) -> bool {
self.0.read().resolved_class_traits.get(name).is_some()
}
@ -982,7 +982,7 @@ impl<'gc> ClassObject<'gc> {
/// inherited by subclasses.
///
/// If a trait is returned, it is guaranteed to have a method.
pub fn class_method(self, name: &QName<'gc>) -> Result<Option<Trait<'gc>>, Error> {
pub fn class_method(self, name: QName<'gc>) -> Result<Option<Trait<'gc>>, Error> {
Ok(self.lookup_class_traits(name, |t| matches!(t.kind(), TraitKind::Method { .. })))
}
@ -999,7 +999,7 @@ impl<'gc> ClassObject<'gc> {
pub fn bound_class_method(
self,
activation: &mut Activation<'_, 'gc, '_>,
name: &QName<'gc>,
name: QName<'gc>,
) -> Result<Option<(Object<'gc>, u32)>, Error> {
if let Some(method_trait) = self.class_method(name)? {
let method = method_trait.as_method().unwrap();
@ -1044,7 +1044,7 @@ impl<'gc> ClassObject<'gc> {
_ => None,
}) {
let method = method_trait.as_method().unwrap();
let name = method_trait.name().clone();
let name = method_trait.name();
let scope = self.class_scope();
Ok(Some((
@ -1164,13 +1164,13 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
.into())
}
fn has_trait(self, name: &QName<'gc>) -> Result<bool, Error> {
fn has_trait(self, name: QName<'gc>) -> Result<bool, Error> {
let read = self.0.read();
Ok(self.has_class_trait(name) || read.base.has_trait(name)?)
}
fn has_own_property(self, name: &QName<'gc>) -> Result<bool, Error> {
fn has_own_property(self, name: QName<'gc>) -> Result<bool, Error> {
let read = self.0.read();
Ok(read.base.has_own_instantiated_property(name)
@ -1199,7 +1199,7 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
fn set_local_property_is_enumerable(
&self,
mc: MutationContext<'gc, '_>,
name: &QName<'gc>,
name: QName<'gc>,
is_enumerable: bool,
) -> Result<(), Error> {
// Traits are never enumerable.

View File

@ -76,10 +76,8 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
if let Some(local_name) = multiname.local_name() {
for namespace in multiname.namespace_set() {
if namespace.is_any() || namespace.is_public() || namespace.is_namespace() {
let qname = QNameObject::from_qname(
activation,
QName::new(namespace.clone(), local_name),
)?;
let qname =
QNameObject::from_qname(activation, QName::new(*namespace, local_name))?;
return receiver.call_property(
&QName::new(Namespace::Namespace(NS_FLASH_PROXY.into()), "getProperty")
@ -116,10 +114,8 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
if let Some(local_name) = multiname.local_name() {
for namespace in multiname.namespace_set() {
if namespace.is_any() || namespace.is_public() || namespace.is_namespace() {
let qname = QNameObject::from_qname(
activation,
QName::new(namespace.clone(), local_name),
)?;
let qname =
QNameObject::from_qname(activation, QName::new(*namespace, local_name))?;
receiver.call_property(
&QName::new(Namespace::Namespace(NS_FLASH_PROXY.into()), "setProperty")
@ -160,10 +156,8 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
if let Some(local_name) = multiname.local_name() {
for namespace in multiname.namespace_set() {
if namespace.is_any() || namespace.is_public() || namespace.is_namespace() {
let qname = QNameObject::from_qname(
activation,
QName::new(namespace.clone(), local_name),
)?;
let qname =
QNameObject::from_qname(activation, QName::new(*namespace, local_name))?;
let mut args = vec![qname.into()];
args.extend_from_slice(arguments);
@ -197,10 +191,8 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
if let Some(local_name) = multiname.local_name() {
for namespace in multiname.namespace_set() {
if namespace.is_any() || namespace.is_public() || namespace.is_namespace() {
let qname = QNameObject::from_qname(
activation,
QName::new(namespace.clone(), local_name),
)?;
let qname =
QNameObject::from_qname(activation, QName::new(*namespace, local_name))?;
return Ok(self
.call_property(
@ -227,7 +219,7 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
fn has_property_via_in(
self,
activation: &mut Activation<'_, 'gc, '_>,
name: &QName<'gc>,
name: QName<'gc>,
) -> Result<bool, Error> {
Ok(self
.call_property(

View File

@ -137,7 +137,7 @@ impl<'gc> ScriptObjectData<'gc> {
pub fn get_property_local(
&self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
_activation: &mut Activation<'_, 'gc, '_>,
) -> Result<ReturnValue<'gc>, Error> {
let prop = self.values.get(name);
@ -152,7 +152,7 @@ impl<'gc> ScriptObjectData<'gc> {
pub fn set_property_local(
&mut self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<ReturnValue<'gc>, Error> {
@ -174,9 +174,9 @@ impl<'gc> ScriptObjectData<'gc> {
prop.set(receiver, value)
} else {
//TODO: Not all classes are dynamic like this
self.enumerants.push(name.clone());
self.enumerants.push(name);
self.values
.insert(name.clone(), Property::new_dynamic_property(value));
.insert(name, Property::new_dynamic_property(value));
Ok(Value::Undefined.into())
}
@ -185,7 +185,7 @@ impl<'gc> ScriptObjectData<'gc> {
pub fn init_property_local(
&mut self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<ReturnValue<'gc>, Error> {
@ -199,20 +199,20 @@ impl<'gc> ScriptObjectData<'gc> {
} else {
//TODO: Not all classes are dynamic like this
self.values
.insert(name.clone(), Property::new_dynamic_property(value));
.insert(name, Property::new_dynamic_property(value));
Ok(Value::Undefined.into())
}
}
pub fn is_property_overwritable(&self, name: &QName<'gc>) -> bool {
pub fn is_property_overwritable(&self, name: QName<'gc>) -> bool {
self.values
.get(name)
.map(|p| p.is_overwritable())
.unwrap_or(true)
}
pub fn delete_property(&mut self, name: &QName<'gc>) -> bool {
pub fn delete_property(&mut self, name: QName<'gc>) -> bool {
let can_delete = if let Some(prop) = self.values.get(name) {
prop.can_delete()
} else {
@ -267,7 +267,7 @@ impl<'gc> ScriptObjectData<'gc> {
self.methods.get(id as usize).and_then(|v| *v)
}
pub fn has_trait(&self, name: &QName<'gc>) -> Result<bool, Error> {
pub fn has_trait(&self, name: QName<'gc>) -> Result<bool, Error> {
match self.instance_of {
//Class instances have instance traits from any class in the base
//class chain.
@ -294,15 +294,15 @@ impl<'gc> ScriptObjectData<'gc> {
Ok(ns_set)
}
pub fn has_own_property(&self, name: &QName<'gc>) -> Result<bool, Error> {
pub fn has_own_property(&self, name: QName<'gc>) -> Result<bool, Error> {
Ok(self.has_own_instantiated_property(name) || self.has_trait(name)?)
}
pub fn has_own_instantiated_property(&self, name: &QName<'gc>) -> bool {
pub fn has_own_instantiated_property(&self, name: QName<'gc>) -> bool {
self.values.get(name).is_some()
}
pub fn has_own_virtual_set_only_property(&self, name: &QName<'gc>) -> bool {
pub fn has_own_virtual_set_only_property(&self, name: QName<'gc>) -> bool {
matches!(
self.values.get(name),
Some(Property::Virtual {
@ -344,13 +344,13 @@ impl<'gc> ScriptObjectData<'gc> {
.map(|q| q.local_name().into())
}
pub fn property_is_enumerable(&self, name: &QName<'gc>) -> bool {
self.enumerants.contains(name)
pub fn property_is_enumerable(&self, name: QName<'gc>) -> bool {
self.enumerants.contains(&name)
}
pub fn set_local_property_is_enumerable(
&mut self,
name: &QName<'gc>,
name: QName<'gc>,
is_enumerable: bool,
) -> Result<(), Error> {
// Traits are never enumerable
@ -358,12 +358,12 @@ impl<'gc> ScriptObjectData<'gc> {
return Ok(());
}
if is_enumerable && self.values.contains_key(name) && !self.enumerants.contains(name) {
self.enumerants.push(name.clone());
} else if !is_enumerable && self.enumerants.contains(name) {
if is_enumerable && self.values.contains_key(name) && !self.enumerants.contains(&name) {
self.enumerants.push(name);
} else if !is_enumerable && self.enumerants.contains(&name) {
let mut index = None;
for (i, other_name) in self.enumerants.iter().enumerate() {
if other_name == name {
if *other_name == name {
index = Some(i);
}
}
@ -422,12 +422,12 @@ impl<'gc> ScriptObjectData<'gc> {
*self.methods.get_mut(disp_id as usize).unwrap() = Some(function);
}
if !self.values.contains_key(&name) {
self.values.insert(name.clone(), Property::new_virtual());
if !self.values.contains_key(name) {
self.values.insert(name, Property::new_virtual());
}
self.values
.get_mut(&name)
.get_mut(name)
.unwrap()
.install_virtual_getter(function)
}
@ -456,12 +456,12 @@ impl<'gc> ScriptObjectData<'gc> {
*self.methods.get_mut(disp_id as usize).unwrap() = Some(function);
}
if !self.values.contains_key(&name) {
self.values.insert(name.clone(), Property::new_virtual());
if !self.values.contains_key(name) {
self.values.insert(name, Property::new_virtual());
}
self.values
.get_mut(&name)
.get_mut(name)
.unwrap()
.install_virtual_setter(function)
}

View File

@ -101,7 +101,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
fn get_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<Value<'gc>, Error> {
let read = self.0.read();
@ -122,7 +122,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
fn set_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<(), Error> {
@ -160,7 +160,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
fn init_property_local(
self,
receiver: Object<'gc>,
name: &QName<'gc>,
name: QName<'gc>,
value: Value<'gc>,
activation: &mut Activation<'_, 'gc, '_>,
) -> Result<(), Error> {
@ -198,7 +198,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
fn delete_property_local(
&self,
gc_context: MutationContext<'gc, '_>,
name: &QName<'gc>,
name: QName<'gc>,
) -> Result<bool, Error> {
if name.namespace().is_package("") && name.local_name().parse::<usize>().is_ok() {
return Ok(true);
@ -207,7 +207,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
Ok(self.0.write(gc_context).base.delete_property(name))
}
fn has_own_property(self, name: &QName<'gc>) -> Result<bool, Error> {
fn has_own_property(self, name: QName<'gc>) -> Result<bool, Error> {
if name.namespace().is_package("") {
if let Ok(index) = name.local_name().parse::<usize>() {
return Ok(self.0.read().vector.is_in_range(index));
@ -259,7 +259,7 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> {
}
}
fn property_is_enumerable(&self, name: &QName<'gc>) -> bool {
fn property_is_enumerable(&self, name: QName<'gc>) -> bool {
name.local_name()
.parse::<u32>()
.map(|index| self.0.read().vector.length() as u32 >= index)

View File

@ -35,22 +35,22 @@ impl<'gc, V> PropertyMap<'gc, V> {
Self(HashMap::new())
}
pub fn get(&self, name: &QName<'gc>) -> Option<&V> {
pub fn get(&self, name: QName<'gc>) -> Option<&V> {
self.0
.get(&name.local_name())
.iter()
.filter_map(|v| {
v.iter()
.filter(|(n, _)| n == name.namespace())
.filter(|(n, _)| *n == name.namespace())
.map(|(_, v)| v)
.next()
})
.next()
}
pub fn get_mut(&mut self, name: &QName<'gc>) -> Option<&mut V> {
pub fn get_mut(&mut self, name: QName<'gc>) -> Option<&mut V> {
if let Some(bucket) = self.0.get_mut(&name.local_name()) {
if let Some((_, old_value)) = bucket.iter_mut().find(|(n, _)| n == name.namespace()) {
if let Some((_, old_value)) = bucket.iter_mut().find(|(n, _)| *n == name.namespace()) {
return Some(old_value);
}
}
@ -58,35 +58,35 @@ impl<'gc, V> PropertyMap<'gc, V> {
None
}
pub fn contains_key(&self, name: &QName<'gc>) -> bool {
pub fn contains_key(&self, name: QName<'gc>) -> bool {
self.0
.get(&name.local_name())
.iter()
.any(|v| v.iter().any(|(n, _)| n == name.namespace()))
.any(|v| v.iter().any(|(n, _)| *n == name.namespace()))
}
pub fn insert(&mut self, name: QName<'gc>, mut value: V) -> Option<V> {
let bucket = self.0.entry(name.local_name()).or_default();
if let Some((_, old_value)) = bucket.iter_mut().find(|(n, _)| n == name.namespace()) {
if let Some((_, old_value)) = bucket.iter_mut().find(|(n, _)| *n == name.namespace()) {
swap(old_value, &mut value);
Some(value)
} else {
bucket.push((name.namespace().clone(), value));
bucket.push((name.namespace(), value));
None
}
}
pub fn remove(&mut self, name: &QName<'gc>) -> Option<V> {
pub fn remove(&mut self, name: QName<'gc>) -> Option<V> {
let bucket = self.0.get_mut(&name.local_name());
if let Some(bucket) = bucket {
let position = bucket
.iter_mut()
.enumerate()
.find(|(_, (n, _))| n == name.namespace());
.find(|(_, (n, _))| *n == name.namespace());
if let Some((position, _)) = position {
return Some(bucket.remove(position).1);
}
@ -98,7 +98,7 @@ impl<'gc, V> PropertyMap<'gc, V> {
pub fn namespaces_of(&self, local_name: AvmString<'gc>) -> Vec<Namespace<'gc>> {
self.0
.get(&local_name)
.map(|vals| vals.iter().map(|(ns, _v)| ns.clone()).collect())
.map(|vals| vals.iter().map(|(ns, _v)| *ns).collect())
.unwrap_or_default()
}
}

View File

@ -132,8 +132,8 @@ impl<'gc> ScopeChain<'gc> {
// 2. We are at depth 0 (global scope)
//
// But no matter what, we always search traits first.
if values.has_trait(&qname)?
|| ((scope.with() || depth == 0) && values.has_property(&qname)?)
if values.has_trait(qname)?
|| ((scope.with() || depth == 0) && values.has_property(qname)?)
{
return Ok(Some(values));
}
@ -202,8 +202,8 @@ impl<'gc> ScopeStack<'gc> {
// We search the dynamic properties if either conditions are met:
// 1. Scope is a `with` scope
// 2. We are at depth 0 AND we are at global$init (script initializer).
if values.has_trait(&qname)?
|| ((scope.with() || (global && depth == 0)) && values.has_property(&qname)?)
if values.has_trait(qname)?
|| ((scope.with() || (global && depth == 0)) && values.has_property(qname)?)
{
return Ok(Some(values));
}

View File

@ -346,7 +346,7 @@ impl<'gc> Script<'gc> {
let newtrait = Trait::from_abc_trait(unit, abc_trait, activation)?;
if !newtrait.name().namespace().is_private() {
write.domain.export_definition(
newtrait.name().clone(),
newtrait.name(),
*self,
activation.context.gc_context,
)?;

View File

@ -102,7 +102,7 @@ pub enum TraitKind<'gc> {
impl<'gc> Trait<'gc> {
pub fn from_class(class: GcCell<'gc, Class<'gc>>) -> Self {
let name = class.read().name().clone();
let name = class.read().name();
Trait {
name,
@ -273,8 +273,8 @@ impl<'gc> Trait<'gc> {
})
}
pub fn name(&self) -> &QName<'gc> {
&self.name
pub fn name(&self) -> QName<'gc> {
self.name
}
pub fn kind(&self) -> &TraitKind<'gc> {

View File

@ -595,7 +595,7 @@ impl<'gc> MovieClip<'gc> {
.library_for_movie_mut(movie.clone());
let domain = library.avm2_domain();
let class_object = domain
.get_defined_value(&mut activation, name.clone())
.get_defined_value(&mut activation, name)
.and_then(|v| v.coerce_to_object(&mut activation))
.and_then(|v| {
v.as_class_object().ok_or_else(|| {