avm2: Support indices in XMLList.child
This commit is contained in:
parent
d9dad1109a
commit
ed6fa6b2fe
|
@ -216,29 +216,9 @@ pub fn child<'gc>(
|
|||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let xml = this.as_xml_object().unwrap();
|
||||
let multiname = name_to_multiname(activation, &args[0], false)?;
|
||||
let children = if let E4XNodeKind::Element { children, .. } = &*xml.node().kind() {
|
||||
if let Some(local_name) = multiname.local_name() {
|
||||
if let Ok(index) = local_name.parse::<usize>() {
|
||||
let children = if let Some(node) = children.get(index) {
|
||||
vec![E4XOrXml::E4X(*node)]
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
return Ok(XmlListObject::new(activation, children, None, None).into());
|
||||
}
|
||||
}
|
||||
|
||||
children
|
||||
.iter()
|
||||
.filter(|node| node.matches_name(&multiname))
|
||||
.map(|node| E4XOrXml::E4X(*node))
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
// FIXME: If name is not a number index, then we should call [[Get]] (get_property_local) with the name.
|
||||
Ok(XmlListObject::new(activation, children, Some(xml.into()), Some(multiname)).into())
|
||||
let list = xml.child(&multiname, activation);
|
||||
Ok(list.into())
|
||||
}
|
||||
|
||||
pub fn child_index<'gc>(
|
||||
|
|
|
@ -166,21 +166,26 @@ pub fn child<'gc>(
|
|||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let list = this.as_xml_list_object().unwrap();
|
||||
let this = this.as_xml_list_object().unwrap();
|
||||
let multiname = name_to_multiname(activation, &args[0], false)?;
|
||||
let children = list.children();
|
||||
let mut sub_children = Vec::new();
|
||||
for child in &*children {
|
||||
if let E4XNodeKind::Element { ref children, .. } = &*child.node().kind() {
|
||||
sub_children.extend(
|
||||
children
|
||||
.iter()
|
||||
.filter(|node| node.matches_name(&multiname))
|
||||
.map(|node| E4XOrXml::E4X(*node)),
|
||||
);
|
||||
let mut children = this.children_mut(activation.gc());
|
||||
|
||||
// 1. Let m be a new XMLList with m.[[TargetObject]] = list
|
||||
let list = XmlListObject::new(activation, Some(this.into()), None);
|
||||
|
||||
// 2. For i = 0 to list.[[Length]]-1
|
||||
for child in &mut *children {
|
||||
// 2.a. Let r = list[i].child(propertyName)
|
||||
let child = child.get_or_create_xml(activation);
|
||||
let r = child.child(&multiname, activation);
|
||||
// 2.b. If r.[[Length]] > 0, call the [[Append]] method of m with argument r
|
||||
if r.length() > 0 {
|
||||
list.append(r.into(), activation.gc());
|
||||
}
|
||||
}
|
||||
Ok(XmlListObject::new(activation, sub_children, Some(list.into()), None).into())
|
||||
|
||||
// 3. Return m
|
||||
Ok(list.into())
|
||||
}
|
||||
|
||||
pub fn children<'gc>(
|
||||
|
@ -308,6 +313,7 @@ pub fn descendants<'gc>(
|
|||
}
|
||||
}
|
||||
|
||||
// ECMA-357 13.5.4.20 XMLList.prototype.text ( )
|
||||
pub fn text<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
|
|
|
@ -14,7 +14,7 @@ use gc_arena::{Collect, GcCell, GcWeakCell, Mutation};
|
|||
use ruffle_wstr::WString;
|
||||
use std::cell::{Ref, RefMut};
|
||||
|
||||
use super::xml_list_object::E4XOrXml;
|
||||
use super::xml_list_object::{E4XOrXml, XmlOrXmlListObject};
|
||||
use super::PrimitiveObject;
|
||||
|
||||
/// A class instance allocator that allocates XML objects.
|
||||
|
@ -70,6 +70,49 @@ impl<'gc> XmlObject<'gc> {
|
|||
))
|
||||
}
|
||||
|
||||
pub fn child(
|
||||
&self,
|
||||
name: &Multiname<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
) -> XmlListObject<'gc> {
|
||||
let children = if let E4XNodeKind::Element { children, .. } = &*self.node().kind() {
|
||||
if let Some(local_name) = name.local_name() {
|
||||
if let Ok(index) = local_name.parse::<usize>() {
|
||||
let children = if let Some(node) = children.get(index) {
|
||||
vec![E4XOrXml::E4X(*node)]
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
let list = XmlListObject::new_with_children(activation, children, None, None);
|
||||
|
||||
if list.length() > 0 {
|
||||
// NOTE: Since avmplus uses appendNode here, when the node exists, that implicitly sets the target_dirty flag.
|
||||
list.set_dirty_flag(activation.gc());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
children
|
||||
.iter()
|
||||
.filter(|node| node.matches_name(name))
|
||||
.map(|node| E4XOrXml::E4X(*node))
|
||||
.collect()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
// FIXME: If name is not a number index, then we should call [[Get]] (get_property_local) with the name.
|
||||
XmlListObject::new_with_children(
|
||||
activation,
|
||||
children,
|
||||
Some(XmlOrXmlListObject::Xml(*self)),
|
||||
Some(name.clone()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn length(&self) -> Option<usize> {
|
||||
self.node().length()
|
||||
}
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
num_ticks = 1
|
||||
known_failure = true
|
||||
|
|
Loading…
Reference in New Issue