avm2: Alternative implementation of XML hasOwnProperty @attribute
This commit is contained in:
parent
24079518d9
commit
791081051f
|
@ -715,3 +715,30 @@ pub fn to_xml_string<'gc>(
|
||||||
to_xml_string_inner(xml, &mut buf)?;
|
to_xml_string_inner(xml, &mut buf)?;
|
||||||
Ok(AvmString::new(activation.context.gc_context, buf))
|
Ok(AvmString::new(activation.context.gc_context, buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name_to_multiname<'gc>(
|
||||||
|
activation: &mut Activation<'_, 'gc>,
|
||||||
|
name: &Value<'gc>,
|
||||||
|
) -> Result<Multiname<'gc>, Error<'gc>> {
|
||||||
|
if let Value::Object(o) = name {
|
||||||
|
if let Some(qname) = o.as_qname_object() {
|
||||||
|
return Ok(qname.name().clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = name.coerce_to_string(activation)?;
|
||||||
|
|
||||||
|
if let Some(name) = name.strip_prefix(b'@') {
|
||||||
|
let name = AvmString::new(activation.context.gc_context, name);
|
||||||
|
return Ok(Multiname::attribute(
|
||||||
|
activation.avm2().public_namespace,
|
||||||
|
name,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(if &*name == b"*" {
|
||||||
|
Multiname::any(activation.context.gc_context)
|
||||||
|
} else {
|
||||||
|
Multiname::new(activation.avm2().public_namespace, name)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -210,8 +210,7 @@ pub fn has_own_property<'gc>(
|
||||||
args.get(0).ok_or_else(|| "No name specified".into());
|
args.get(0).ok_or_else(|| "No name specified".into());
|
||||||
let name = name?.coerce_to_string(activation)?;
|
let name = name?.coerce_to_string(activation)?;
|
||||||
|
|
||||||
let multiname = Multiname::new(activation.avm2().public_namespace, name);
|
Ok(this.has_own_property_string(name, activation)?.into())
|
||||||
Ok(this.has_own_property(&multiname).into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Object.prototype.isPrototypeOf`
|
/// `Object.prototype.isPrototypeOf`
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
//! XML builtin and prototype
|
//! XML builtin and prototype
|
||||||
|
|
||||||
use crate::avm2::e4x::{E4XNode, E4XNodeKind};
|
use crate::avm2::e4x::{name_to_multiname, E4XNode, E4XNodeKind};
|
||||||
pub use crate::avm2::object::xml_allocator;
|
pub use crate::avm2::object::xml_allocator;
|
||||||
use crate::avm2::object::{
|
use crate::avm2::object::{
|
||||||
E4XOrXml, NamespaceObject, QNameObject, TObject, XmlListObject, XmlObject,
|
E4XOrXml, NamespaceObject, QNameObject, TObject, XmlListObject, XmlObject,
|
||||||
|
@ -95,24 +95,6 @@ pub fn to_xml_string<'gc>(
|
||||||
Ok(Value::String(node.xml_to_xml_string(activation)?))
|
Ok(Value::String(node.xml_to_xml_string(activation)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name_to_multiname<'gc>(
|
|
||||||
activation: &mut Activation<'_, 'gc>,
|
|
||||||
name: &Value<'gc>,
|
|
||||||
) -> Result<Multiname<'gc>, Error<'gc>> {
|
|
||||||
if let Value::Object(o) = name {
|
|
||||||
if let Some(qname) = o.as_qname_object() {
|
|
||||||
return Ok(qname.name().clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let name = name.coerce_to_string(activation)?;
|
|
||||||
Ok(if &*name == b"*" {
|
|
||||||
Multiname::any(activation.context.gc_context)
|
|
||||||
} else {
|
|
||||||
Multiname::new(activation.avm2().public_namespace, name)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn child<'gc>(
|
pub fn child<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
this: Option<Object<'gc>>,
|
this: Option<Object<'gc>>,
|
||||||
|
|
|
@ -4,15 +4,13 @@ use ruffle_wstr::WString;
|
||||||
|
|
||||||
pub use crate::avm2::object::xml_list_allocator;
|
pub use crate::avm2::object::xml_list_allocator;
|
||||||
use crate::avm2::{
|
use crate::avm2::{
|
||||||
e4x::{simple_content_to_string, E4XNode, E4XNodeKind},
|
e4x::{name_to_multiname, simple_content_to_string, E4XNode, E4XNodeKind},
|
||||||
error::type_error,
|
error::type_error,
|
||||||
object::{E4XOrXml, XmlListObject},
|
object::{E4XOrXml, XmlListObject},
|
||||||
string::AvmString,
|
string::AvmString,
|
||||||
Activation, Error, Multiname, Object, TObject, Value,
|
Activation, Error, Multiname, Object, TObject, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::xml::name_to_multiname;
|
|
||||||
|
|
||||||
fn has_simple_content_inner(children: &[E4XOrXml<'_>]) -> bool {
|
fn has_simple_content_inner(children: &[E4XOrXml<'_>]) -> bool {
|
||||||
match children {
|
match children {
|
||||||
[] => true,
|
[] => true,
|
||||||
|
|
|
@ -314,6 +314,16 @@ impl<'gc> Multiname<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new Multiname with the `MultinameFlags::ATTRIBUTE` flag.
|
||||||
|
pub fn attribute(ns: Namespace<'gc>, name: impl Into<AvmString<'gc>>) -> Self {
|
||||||
|
Self {
|
||||||
|
ns: NamespaceSet::single(ns),
|
||||||
|
name: Some(name.into()),
|
||||||
|
params: Vec::new(),
|
||||||
|
flags: MultinameFlags::ATTRIBUTE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn namespace_set(&self) -> &[Namespace<'gc>] {
|
pub fn namespace_set(&self) -> &[Namespace<'gc>] {
|
||||||
match &self.ns {
|
match &self.ns {
|
||||||
NamespaceSet::Single(ns) => std::slice::from_ref(ns),
|
NamespaceSet::Single(ns) => std::slice::from_ref(ns),
|
||||||
|
|
|
@ -586,6 +586,15 @@ pub trait TObject<'gc>: 'gc + Collect + Debug + Into<Object<'gc>> + Clone + Copy
|
||||||
self.base().has_own_property(name)
|
self.base().has_own_property(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Same as has_own_property, but constructs a public Multiname for you.
|
||||||
|
fn has_own_property_string(
|
||||||
|
self,
|
||||||
|
name: impl Into<AvmString<'gc>>,
|
||||||
|
activation: &mut Activation<'_, 'gc>,
|
||||||
|
) -> Result<bool, Error<'gc>> {
|
||||||
|
Ok(self.has_own_property(&Multiname::new(activation.avm2().public_namespace, name)))
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if an object has one or more traits of a given name.
|
/// Returns true if an object has one or more traits of a given name.
|
||||||
fn has_trait(self, name: &Multiname<'gc>) -> bool {
|
fn has_trait(self, name: &Multiname<'gc>) -> bool {
|
||||||
let base = self.base();
|
let base = self.base();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//! Object representation for XML objects
|
//! Object representation for XML objects
|
||||||
|
|
||||||
use crate::avm2::activation::Activation;
|
use crate::avm2::activation::Activation;
|
||||||
use crate::avm2::e4x::{E4XNode, E4XNodeKind};
|
use crate::avm2::e4x::{name_to_multiname, E4XNode, E4XNodeKind};
|
||||||
use crate::avm2::object::script_object::ScriptObjectData;
|
use crate::avm2::object::script_object::ScriptObjectData;
|
||||||
use crate::avm2::object::{ClassObject, Object, ObjectPtr, TObject, XmlListObject};
|
use crate::avm2::object::{ClassObject, Object, ObjectPtr, TObject, XmlListObject};
|
||||||
use crate::avm2::string::AvmString;
|
use crate::avm2::string::AvmString;
|
||||||
|
@ -279,6 +279,15 @@ impl<'gc> TObject<'gc> for XmlObject<'gc> {
|
||||||
read.base.has_own_dynamic_property(name)
|
read.base.has_own_dynamic_property(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_own_property_string(
|
||||||
|
self,
|
||||||
|
name: impl Into<AvmString<'gc>>,
|
||||||
|
activation: &mut Activation<'_, 'gc>,
|
||||||
|
) -> Result<bool, Error<'gc>> {
|
||||||
|
let name = name_to_multiname(activation, &Value::String(name.into()))?;
|
||||||
|
Ok(self.has_own_property(&name))
|
||||||
|
}
|
||||||
|
|
||||||
fn set_property_local(
|
fn set_property_local(
|
||||||
self,
|
self,
|
||||||
name: &Multiname<'gc>,
|
name: &Multiname<'gc>,
|
||||||
|
|
Loading…
Reference in New Issue