avm2: Implement `Proxy.deleteproperty`
This commit is contained in:
parent
503dc08594
commit
427b2bf17a
|
@ -1405,9 +1405,9 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
(multiname, object)
|
||||
};
|
||||
|
||||
self.context
|
||||
.avm2
|
||||
.push(object.delete_property(self.context.gc_context, &multiname)?);
|
||||
let did_delete = object.delete_property(self, &multiname)?;
|
||||
|
||||
self.context.avm2.push(did_delete);
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
|
|
@ -687,17 +687,17 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
Ok(base.delete_property(name))
|
||||
}
|
||||
|
||||
/// Delete a named property from the object.
|
||||
/// Delete a property that does not exist.
|
||||
///
|
||||
/// Returns false if the property cannot be deleted.
|
||||
fn delete_property(
|
||||
/// By default, undefined property deletion succeeds for dynamic classes,
|
||||
/// and fails for sealed ones. Objects that have particular alternative
|
||||
/// behavior for undefined values may substitute their own implementation
|
||||
/// here without disturbing the rest of `deleteproperty`'s implementation.
|
||||
fn delete_property_undef(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
multiname: &Multiname<'gc>,
|
||||
_activation: &mut Activation<'_, '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()
|
||||
|
@ -705,6 +705,20 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
.unwrap_or(false));
|
||||
}
|
||||
|
||||
/// Delete a named property from the object.
|
||||
///
|
||||
/// Returns false if the property cannot be deleted.
|
||||
fn delete_property(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
multiname: &Multiname<'gc>,
|
||||
) -> Result<bool, Error> {
|
||||
let name = self.resolve_multiname(multiname)?;
|
||||
|
||||
if name.is_none() {
|
||||
return self.delete_property_undef(activation, multiname);
|
||||
}
|
||||
|
||||
//At this point, the name should be known.
|
||||
let name = name.unwrap();
|
||||
|
||||
|
@ -732,7 +746,7 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
|||
}
|
||||
}
|
||||
|
||||
self.delete_property_local(gc_context, &name)
|
||||
self.delete_property_local(activation.context.gc_context, &name)
|
||||
}
|
||||
|
||||
/// Retrieve the `__proto__` of a given object.
|
||||
|
|
|
@ -172,4 +172,39 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
|
|||
)
|
||||
.into())
|
||||
}
|
||||
|
||||
fn delete_property_undef(
|
||||
&self,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
multiname: &Multiname<'gc>,
|
||||
) -> Result<bool, Error> {
|
||||
for namespace in multiname.namespace_set() {
|
||||
if let Some(local_name) = multiname.local_name() {
|
||||
if namespace.is_any() || namespace.is_public() || namespace.is_namespace() {
|
||||
let qname = QNameObject::from_qname(
|
||||
activation,
|
||||
QName::new(namespace.clone(), local_name),
|
||||
)?;
|
||||
|
||||
return Ok(self
|
||||
.call_property(
|
||||
&QName::new(
|
||||
Namespace::Namespace(NS_FLASH_PROXY.into()),
|
||||
"deleteProperty",
|
||||
)
|
||||
.into(),
|
||||
&[qname.into()],
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_boolean());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unknown properties on a dynamic class delete successfully.
|
||||
return Ok(!self
|
||||
.instance_of_class_definition()
|
||||
.map(|c| c.read().is_sealed())
|
||||
.unwrap_or(false));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,11 @@ dynamic class TestProxy extends Proxy {
|
|||
|
||||
trace("///name.uri");
|
||||
trace(name.uri);
|
||||
|
||||
if (name.localName === "crazy_return") {
|
||||
trace("///returning non-bool value");
|
||||
return "This isn't a bool at all";
|
||||
}
|
||||
} else if (name is String) {
|
||||
trace("///type of name is String");
|
||||
} else {
|
||||
|
@ -72,3 +77,6 @@ trace(delete p.proxy_var);
|
|||
|
||||
trace("///delete p.proxy_fn");
|
||||
trace(delete p.proxy_fn);
|
||||
|
||||
trace("///delete p.crazy_return");
|
||||
trace(delete p.crazy_return);
|
|
@ -57,3 +57,12 @@ proxy_fn
|
|||
///name.uri
|
||||
|
||||
true
|
||||
///delete p.crazy_return
|
||||
///attempted to delete property: crazy_return
|
||||
///type of name is QName
|
||||
///name.localName
|
||||
crazy_return
|
||||
///name.uri
|
||||
|
||||
///returning non-bool value
|
||||
true
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue