Fix newly constructed XML trees not actually containing the XML they just parsed.

This commit is contained in:
David Wendt 2019-12-21 23:57:51 -05:00
parent 960e4dad90
commit e47a1d1e38
2 changed files with 22 additions and 12 deletions

View File

@ -8,7 +8,6 @@ use crate::avm1::xml_object::XMLObject;
use crate::avm1::{Avm1, Error, Object, TObject, UpdateContext, Value}; use crate::avm1::{Avm1, Error, Object, TObject, UpdateContext, Value};
use crate::xml::{XMLDocument, XMLNode}; use crate::xml::{XMLDocument, XMLNode};
use gc_arena::MutationContext; use gc_arena::MutationContext;
use std::mem::swap;
/// XMLNode constructor /// XMLNode constructor
pub fn xmlnode_constructor<'gc>( pub fn xmlnode_constructor<'gc>(
@ -25,12 +24,12 @@ pub fn xmlnode_constructor<'gc>(
this.as_xml_node(), this.as_xml_node(),
) { ) {
(Some(Ok(1)), Some(Ok(ref strval)), Some(ref mut this_node)) => { (Some(Ok(1)), Some(Ok(ref strval)), Some(ref mut this_node)) => {
let mut xmlelement = XMLNode::new_text(ac.gc_context, strval, blank_document); let xmlelement = XMLNode::new_text(ac.gc_context, strval, blank_document);
swap(&mut xmlelement, this_node); this_node.swap(ac.gc_context, xmlelement);
} }
(Some(Ok(3)), Some(Ok(ref strval)), Some(ref mut this_node)) => { (Some(Ok(3)), Some(Ok(ref strval)), Some(ref mut this_node)) => {
let mut xmlelement = XMLNode::new_element(ac.gc_context, strval, blank_document)?; let xmlelement = XMLNode::new_element(ac.gc_context, strval, blank_document)?;
swap(&mut xmlelement, this_node); this_node.swap(ac.gc_context, xmlelement);
} }
//Invalid nodetype ID, string value missing, or not an XMLElement //Invalid nodetype ID, string value missing, or not an XMLElement
_ => {} _ => {}
@ -155,13 +154,11 @@ pub fn xml_constructor<'gc>(
) { ) {
(Some(Ok(ref string)), Some(ref mut this_node)) => { (Some(Ok(ref string)), Some(ref mut this_node)) => {
let xmldoc = XMLDocument::from_str(ac.gc_context, string)?; let xmldoc = XMLDocument::from_str(ac.gc_context, string)?;
this_node.swap(ac.gc_context, xmldoc.as_node());
swap(&mut xmldoc.as_node(), this_node);
} }
(None, Some(ref mut this_node)) => { (None, Some(ref mut this_node)) => {
let xmldoc = XMLDocument::new(ac.gc_context); let xmldoc = XMLDocument::new(ac.gc_context);
this_node.swap(ac.gc_context, xmldoc.as_node());
swap(&mut xmldoc.as_node(), this_node);
} }
//Non-string argument or not an XML document //Non-string argument or not an XML document
_ => {} _ => {}
@ -176,7 +173,5 @@ pub fn create_xml_proto<'gc>(
proto: Object<'gc>, proto: Object<'gc>,
_fn_proto: Object<'gc>, _fn_proto: Object<'gc>,
) -> Object<'gc> { ) -> Object<'gc> {
let xml_proto = XMLObject::empty_node(gc_context, Some(proto)); XMLObject::empty_node(gc_context, Some(proto))
xml_proto.into()
} }

View File

@ -9,6 +9,7 @@ use quick_xml::events::{BytesStart, BytesText};
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::fmt; use std::fmt;
use std::mem::swap;
/// Represents a node in the XML tree. /// Represents a node in the XML tree.
#[derive(Copy, Clone, Collect)] #[derive(Copy, Clone, Collect)]
@ -414,6 +415,20 @@ impl<'gc> XMLNode<'gc> {
object.unwrap() object.unwrap()
} }
/// Swap the contents of this node with another one.
///
/// After this function completes, the current `XMLNode` will contain all
/// data present in the `other` node, and vice versa. References to the node
/// within the tree will *not* be updated.
pub fn swap(&mut self, gc_context: MutationContext<'gc, '_>, other: Self) {
if !GcCell::ptr_eq(self.0, other.0) {
swap(
&mut *self.0.write(gc_context),
&mut *other.0.write(gc_context),
);
}
}
} }
impl<'gc> fmt::Debug for XMLNode<'gc> { impl<'gc> fmt::Debug for XMLNode<'gc> {