avm2: Reimplement XML.appendChild in terms of [[Get]] and [[Put]]
This commit is contained in:
parent
7cec9ed969
commit
08d6a7b648
|
@ -430,65 +430,23 @@ pub fn append_child<'gc>(
|
||||||
let child = args.get_value(0);
|
let child = args.get_value(0);
|
||||||
let child = crate::avm2::e4x::maybe_escape_child(activation, child)?;
|
let child = crate::avm2::e4x::maybe_escape_child(activation, child)?;
|
||||||
|
|
||||||
if let Some(child) = child.as_object().and_then(|o| o.as_xml_object()) {
|
// 1. Let children be the result of calling the [[Get]] method of x with argument "*"
|
||||||
xml.node()
|
let name = Multiname::any(activation.gc());
|
||||||
.append_child(activation.context.gc_context, *child.node())?;
|
let children = xml.get_property_local(&name, activation)?;
|
||||||
} 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 {
|
|
||||||
// Appending a non-XML/XMLList object
|
|
||||||
let (last_child_namespace, last_child_name) =
|
|
||||||
if let E4XNodeKind::Element { children, .. } = &*xml.node().kind() {
|
|
||||||
let num_children = children.len();
|
|
||||||
|
|
||||||
match num_children {
|
// 2. Call the [[Put]] method of children with arguments children.[[Length]] and child
|
||||||
0 => (None, None),
|
let xml_list = children
|
||||||
_ => (
|
.as_object()
|
||||||
children[num_children - 1].namespace(),
|
.and_then(|o| o.as_xml_list_object())
|
||||||
children[num_children - 1].local_name(),
|
.expect("Should have an XMLList");
|
||||||
),
|
let length = xml_list.length();
|
||||||
}
|
let name = Multiname::new(
|
||||||
} else {
|
activation.avm2().public_namespace,
|
||||||
// FIXME - figure out exactly when appending is allowed in FP,
|
AvmString::new_utf8(activation.context.gc_context, length.to_string()),
|
||||||
// and throw the proper AVM error.
|
);
|
||||||
return Err(Error::RustError(
|
xml_list.set_property_local(&name, child, activation)?;
|
||||||
format!(
|
|
||||||
"Cannot append child {child:?} to node {:?}",
|
|
||||||
xml.node().kind()
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
));
|
|
||||||
};
|
|
||||||
|
|
||||||
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_namespace,
|
|
||||||
last_child_name,
|
|
||||||
Some(*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)?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// 3. Return x
|
||||||
Ok(this.into())
|
Ok(this.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue