avm2+tests: Fully implement XML.appendChild, add a test

This commit is contained in:
Lord-McSweeney 2023-07-27 03:03:35 -07:00 committed by Nathan Adams
parent cf8dde966f
commit cf5c02ca1b
5 changed files with 83 additions and 8 deletions

View File

@ -314,22 +314,59 @@ pub fn append_child<'gc>(
) -> Result<Value<'gc>, Error<'gc>> {
let xml = this.as_xml_object().unwrap();
let child = args.get_object(activation, 0, "child")?;
if let Some(child) = child.as_xml_object() {
let child = args.get_value(0);
if let Some(child) = child.as_object().and_then(|o| o.as_xml_object()) {
xml.node()
.append_child(activation.context.gc_context, *child.node())?;
} else if let Some(list) = child.as_xml_list_object() {
if list.target().is_some() {
return Err("Cannot append XMLList with target".into());
}
} else if let Some(list) = child.as_object().and_then(|o| o.as_xml_list_object()) {
for child in &*list.children() {
xml.node()
.append_child(activation.context.gc_context, *child.node())?;
}
} else {
return Err(format!("Cannot append non-XML value {child:?}").into());
// Appending a non-XML/XMLList object
let last_child_name = if let E4XNodeKind::Element { children, .. } = &*xml.node().kind() {
let num_children = children.len();
match num_children {
0 => None,
_ => children[num_children - 1].local_name(),
}
} else {
// FIXME - figure out exactly when appending is allowed in FP,
// and throw the proper AVM error.
return Err(Error::RustError(
format!(
"Cannot append child {child:?} to node {:?}",
xml.node().kind()
)
.into(),
));
};
Ok(Value::Undefined)
let text = child.coerce_to_string(activation)?;
if let Some(last_child_name) = last_child_name {
let element_node =
E4XNode::element(activation.context.gc_context, last_child_name, *xml.node()); // Creating an element requires passing a parent node, unlike creating a text node
let text_node = E4XNode::text(activation.context.gc_context, text, None);
element_node
.append_child(activation.context.gc_context, text_node)
.expect("Appending to an element node should succeed");
xml.node()
.append_child(activation.context.gc_context, element_node)?;
} else {
let node = E4XNode::text(activation.context.gc_context, text, None);
// The text node will be parented in the append_child operation
xml.node()
.append_child(activation.context.gc_context, node)?;
}
};
Ok(this.into())
}
pub fn descendants<'gc>(

View File

@ -0,0 +1,27 @@
package {
import flash.display.MovieClip;
public class Test extends MovieClip {
public function Test() {
XML.prettyPrinting = false;
var xml:XML = <a><child1/><child2/></a>;
trace(xml);
var xmls:XMLList = (<root><child3/><child4/></root>).children();
var appended:XML = xml.appendChild(xmls);
trace(appended);
trace(xml);
trace(xml == appended);
xml.child3 = "4";
trace(xmls);
xml.appendChild("qwerty");
trace(xml);
trace(xml.appendChild({"key":"value"}));
var xml2:XML = <b>abcd</b>;
trace(xml2.appendChild("text1").toXMLString());
xml2 = <b></b>;
trace(xml2.appendChild("text2").toXMLString());
}
}
}

View File

@ -0,0 +1,10 @@
<a><child1/><child2/></a>
<a><child1/><child2/><child3/><child4/></a>
<a><child1/><child2/><child3/><child4/></a>
true
<child3>4</child3>
<child4/>
<a><child1/><child2/><child3>4</child3><child4/><child4>qwerty</child4></a>
<a><child1/><child2/><child3>4</child3><child4/><child4>qwerty</child4><child4>[object Object]</child4></a>
<b>abcdtext1</b>
<b>text2</b>

Binary file not shown.

View File

@ -0,0 +1 @@
num_frames = 1