avm2: Refactor `Object.delete_property` to work similar to get/set
This commit is contained in:
parent
e67ca1afe0
commit
503dc08594
|
@ -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),
|
||||
)
|
||||
}
|
||||
.push(object.delete_property(self.context.gc_context, &multiname)?);
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
|
|
@ -672,37 +672,67 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + 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<bool, Error> {
|
||||
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<bool, Error> {
|
||||
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.
|
||||
|
|
|
@ -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<bool, Error> {
|
||||
if name.namespace().is_public() {
|
||||
if let Ok(index) = name.local_name().parse::<usize>() {
|
||||
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<bool, Error> {
|
||||
|
|
|
@ -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<bool, Error> {
|
||||
if name.namespace().is_public() {
|
||||
if let Ok(index) = name.local_name().parse::<usize>() {
|
||||
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<bool, Error> {
|
||||
|
|
|
@ -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<bool, Error> {
|
||||
if name.namespace().is_package("") && name.local_name().parse::<usize>().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<bool, Error> {
|
||||
|
|
Loading…
Reference in New Issue