xml: Turn `remove_child` into `remove_node`

The 2 existing usages of `remove_node` always operated on a child and
its parent: One iterates over all of its children and removes each one,
and the other explicitly grabs the parent of a given node.

As a simplification, `remove_node` operates only on a child node,
without the need for the parent node in addition; it grabs the parent
from the child by itself. As such, it's non-failable.
This commit is contained in:
relrelb 2022-02-21 21:38:07 +02:00 committed by relrelb
parent 73c1be8dcc
commit 7313913127
4 changed files with 16 additions and 39 deletions

View File

@ -99,17 +99,9 @@ fn parse_xml<'gc>(
"".into() "".into()
}; };
let mut node = document.as_node(); let node = document.as_node();
for child in node.children().rev() { for mut child in node.children().rev() {
let result = node.remove_child(activation.context.gc_context, child); child.remove_node(activation.context.gc_context);
if let Err(e) = result {
avm_warn!(
activation,
"XML.parseXML: Error removing node contents: {}",
e
);
return Ok(Value::Undefined);
}
} }
let ignore_whitespace = this let ignore_whitespace = this

View File

@ -194,12 +194,8 @@ fn remove_node<'gc>(
this: Object<'gc>, this: Object<'gc>,
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
if let Some(node) = this.as_xml_node() { if let Some(mut node) = this.as_xml_node() {
if let Some(mut parent) = node.parent() { node.remove_node(activation.context.gc_context);
if let Err(e) = parent.remove_child(activation.context.gc_context, node) {
avm_warn!(activation, "Error in XML.removeNode: {}", e);
}
}
} }
Ok(Value::Undefined) Ok(Value::Undefined)

View File

@ -29,9 +29,6 @@ pub enum Error {
#[error("Not an element")] #[error("Not an element")]
NotAnElement, NotAnElement,
#[error("Target node is not a child of this one!")]
CantRemoveNonChild,
} }
impl From<FromUtf8Error> for Error { impl From<FromUtf8Error> for Error {

View File

@ -435,32 +435,24 @@ impl<'gc> XmlNode<'gc> {
self.insert_child(mc, self.children_len(), child) self.insert_child(mc, self.children_len(), child)
} }
/// Remove a previously added node from this tree. /// Remove this node from its parent.
/// pub fn remove_node(&mut self, mc: MutationContext<'gc, '_>) {
/// If the node is not a child of this one, or this node cannot accept if let Some(parent) = self.parent() {
/// children, then this function yields an error. // This is guaranteed to succeed, as `self` is a child of `parent`.
pub fn remove_child( let position = parent.child_position(*self).unwrap();
&mut self,
mc: MutationContext<'gc, '_>, match &mut *parent.0.write(mc) {
mut child: XmlNode<'gc>, XmlNodeData::DocumentRoot { children, .. }
) -> Result<(), Error> { | XmlNodeData::Element { children, .. } => children.remove(position),
if let Some(position) = self.child_position(child) {
match &mut *self.0.write(mc) {
XmlNodeData::Element { children, .. }
| XmlNodeData::DocumentRoot { children, .. } => children.remove(position),
XmlNodeData::Text { .. } => { XmlNodeData::Text { .. } => {
// This cannot happen, as `adopt_child` refuses to adopt children into text nodes. // This cannot happen, as `adopt_child` refuses to adopt children into text nodes.
unreachable!(); unreachable!();
} }
}; };
child.disown_siblings(mc); self.disown_siblings(mc);
child.disown_parent(mc); self.disown_parent(mc);
} else {
return Err(Error::CantRemoveNonChild);
} }
Ok(())
} }
/// Returns the type of this node as an integer. /// Returns the type of this node as an integer.