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)
|
(multiname, object)
|
||||||
};
|
};
|
||||||
|
|
||||||
self.context
|
let did_delete = object.delete_property(self, &multiname)?;
|
||||||
.avm2
|
|
||||||
.push(object.delete_property(self.context.gc_context, &multiname)?);
|
self.context.avm2.push(did_delete);
|
||||||
|
|
||||||
Ok(FrameControl::Continue)
|
Ok(FrameControl::Continue)
|
||||||
}
|
}
|
||||||
|
|
|
@ -687,17 +687,17 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
||||||
Ok(base.delete_property(name))
|
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.
|
/// By default, undefined property deletion succeeds for dynamic classes,
|
||||||
fn delete_property(
|
/// 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,
|
&self,
|
||||||
gc_context: MutationContext<'gc, '_>,
|
_activation: &mut Activation<'_, 'gc, '_>,
|
||||||
multiname: &Multiname<'gc>,
|
_multiname: &Multiname<'gc>,
|
||||||
) -> Result<bool, Error> {
|
) -> Result<bool, Error> {
|
||||||
let name = self.resolve_multiname(multiname)?;
|
|
||||||
|
|
||||||
if name.is_none() {
|
|
||||||
// Unknown properties on a dynamic class delete successfully.
|
// Unknown properties on a dynamic class delete successfully.
|
||||||
return Ok(!self
|
return Ok(!self
|
||||||
.instance_of_class_definition()
|
.instance_of_class_definition()
|
||||||
|
@ -705,6 +705,20 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
||||||
.unwrap_or(false));
|
.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.
|
//At this point, the name should be known.
|
||||||
let name = name.unwrap();
|
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.
|
/// Retrieve the `__proto__` of a given object.
|
||||||
|
|
|
@ -172,4 +172,39 @@ impl<'gc> TObject<'gc> for ProxyObject<'gc> {
|
||||||
)
|
)
|
||||||
.into())
|
.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");
|
||||||
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) {
|
} else if (name is String) {
|
||||||
trace("///type of name is String");
|
trace("///type of name is String");
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,3 +77,6 @@ trace(delete p.proxy_var);
|
||||||
|
|
||||||
trace("///delete p.proxy_fn");
|
trace("///delete p.proxy_fn");
|
||||||
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
|
///name.uri
|
||||||
|
|
||||||
true
|
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