diff --git a/core/src/avm2/activation.rs b/core/src/avm2/activation.rs index f39e8c2e1..d2153323a 100644 --- a/core/src/avm2/activation.rs +++ b/core/src/avm2/activation.rs @@ -1405,19 +1405,9 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> { (multiname, object) }; - if let Some(name) = object.resolve_multiname(&multiname)? { - self.context - .avm2 - .push(object.delete_property(self.context.gc_context, &name)) - } else { - // Unknown properties on a dynamic class delete successfully. - self.context.avm2.push( - !object - .instance_of_class_definition() - .map(|c| c.read().is_sealed()) - .unwrap_or(false), - ) - } + self.context + .avm2 + .push(object.delete_property(self.context.gc_context, &multiname)?); Ok(FrameControl::Continue) } diff --git a/core/src/avm2/object.rs b/core/src/avm2/object.rs index a12921081..d325b764c 100644 --- a/core/src/avm2/object.rs +++ b/core/src/avm2/object.rs @@ -672,37 +672,67 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into> + Clone + Copy base.is_property_overwritable(name) } + /// Delete a property by QName, after multiname resolution and all other + /// considerations have been taken. + /// + /// This required method is only intended to be called by other TObject + /// methods. + fn delete_property_local( + &self, + gc_context: MutationContext<'gc, '_>, + name: &QName<'gc>, + ) -> Result { + let mut base = self.base_mut(gc_context); + + Ok(base.delete_property(name)) + } + /// Delete a named property from the object. /// /// Returns false if the property cannot be deleted. - fn delete_property(&self, gc_context: MutationContext<'gc, '_>, name: &QName<'gc>) -> bool { - let mut base = self.base_mut(gc_context); + fn delete_property( + &self, + gc_context: MutationContext<'gc, '_>, + multiname: &Multiname<'gc>, + ) -> Result { + let name = self.resolve_multiname(multiname)?; + + if name.is_none() { + // Unknown properties on a dynamic class delete successfully. + return Ok(!self + .instance_of_class_definition() + .map(|c| c.read().is_sealed()) + .unwrap_or(false)); + } + + //At this point, the name should be known. + let name = name.unwrap(); // Reject attempts to delete lazy-bound methods before they have // been bound. - if !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) { - return false; + return Ok(false); } } if let Some(class) = self.as_class_object() { if class - .class_method(name) + .class_method(&name) .map(|t| t.is_some()) .unwrap_or(false) { - return false; + return Ok(false); } } } - base.delete_property(name) + self.delete_property_local(gc_context, &name) } /// Retrieve the `__proto__` of a given object. diff --git a/core/src/avm2/object/array_object.rs b/core/src/avm2/object/array_object.rs index d862ddc5b..895da8448 100644 --- a/core/src/avm2/object/array_object.rs +++ b/core/src/avm2/object/array_object.rs @@ -164,15 +164,19 @@ impl<'gc> TObject<'gc> for ArrayObject<'gc> { Ok(()) } - fn delete_property(&self, gc_context: MutationContext<'gc, '_>, name: &QName<'gc>) -> bool { + fn delete_property_local( + &self, + gc_context: MutationContext<'gc, '_>, + name: &QName<'gc>, + ) -> Result { if name.namespace().is_public() { if let Ok(index) = name.local_name().parse::() { self.0.write(gc_context).array.delete(index); - return true; + return Ok(true); } } - self.0.write(gc_context).base.delete_property(name) + Ok(self.0.write(gc_context).base.delete_property(name)) } fn has_own_property(self, name: &QName<'gc>) -> Result { diff --git a/core/src/avm2/object/bytearray_object.rs b/core/src/avm2/object/bytearray_object.rs index 8bd525d07..eaf4733ad 100644 --- a/core/src/avm2/object/bytearray_object.rs +++ b/core/src/avm2/object/bytearray_object.rs @@ -163,15 +163,19 @@ impl<'gc> TObject<'gc> for ByteArrayObject<'gc> { Ok(()) } - fn delete_property(&self, gc_context: MutationContext<'gc, '_>, name: &QName<'gc>) -> bool { + fn delete_property_local( + &self, + gc_context: MutationContext<'gc, '_>, + name: &QName<'gc>, + ) -> Result { if name.namespace().is_public() { if let Ok(index) = name.local_name().parse::() { self.0.write(gc_context).storage.delete(index); - return true; + return Ok(true); } } - self.0.write(gc_context).base.delete_property(name) + Ok(self.0.write(gc_context).base.delete_property(name)) } fn has_own_property(self, name: &QName<'gc>) -> Result { diff --git a/core/src/avm2/object/vector_object.rs b/core/src/avm2/object/vector_object.rs index 3d656c141..b98972e68 100644 --- a/core/src/avm2/object/vector_object.rs +++ b/core/src/avm2/object/vector_object.rs @@ -195,12 +195,16 @@ impl<'gc> TObject<'gc> for VectorObject<'gc> { Ok(()) } - fn delete_property(&self, gc_context: MutationContext<'gc, '_>, name: &QName<'gc>) -> bool { + fn delete_property_local( + &self, + gc_context: MutationContext<'gc, '_>, + name: &QName<'gc>, + ) -> Result { if name.namespace().is_package("") && name.local_name().parse::().is_ok() { - return true; + return Ok(true); } - self.0.write(gc_context).base.delete_property(name) + Ok(self.0.write(gc_context).base.delete_property(name)) } fn has_own_property(self, name: &QName<'gc>) -> Result {