avm2: Implement XML.copy

This commit is contained in:
Tom Schuster 2023-03-27 19:57:05 +02:00 committed by Aaron Hill
parent cdba704b4b
commit c0400af1de
3 changed files with 66 additions and 2 deletions

View File

@ -108,6 +108,54 @@ impl<'gc> E4XNode<'gc> {
)) ))
} }
pub fn deep_copy(&self, mc: MutationContext<'gc, '_>) -> Self {
let this = self.0.read();
let kind = match &this.kind {
E4XNodeKind::Text(string) => E4XNodeKind::Text(*string),
E4XNodeKind::CData(string) => E4XNodeKind::CData(*string),
E4XNodeKind::Comment(string) => E4XNodeKind::Comment(*string),
E4XNodeKind::ProcessingInstruction(string) => {
E4XNodeKind::ProcessingInstruction(*string)
}
E4XNodeKind::Attribute(string) => E4XNodeKind::Attribute(*string),
E4XNodeKind::Element {
attributes,
children,
} => E4XNodeKind::Element {
attributes: attributes.iter().map(|attr| attr.deep_copy(mc)).collect(),
children: children.iter().map(|child| child.deep_copy(mc)).collect(),
},
};
let node = E4XNode(GcCell::allocate(
mc,
E4XNodeData {
parent: None,
local_name: this.local_name,
kind,
},
));
if let E4XNodeKind::Element {
attributes,
children,
} = &mut node.0.write(mc).kind
{
for attr in attributes.iter_mut() {
let mut data = attr.0.write(mc);
data.parent = Some(node);
}
for child in children.iter_mut() {
let mut data = child.0.write(mc);
data.parent = Some(node);
}
}
node
}
pub fn remove_all_children(&self, gc_context: MutationContext<'gc, '_>) { pub fn remove_all_children(&self, gc_context: MutationContext<'gc, '_>) {
let mut this = self.0.write(gc_context); let mut this = self.0.write(gc_context);
if let E4XNodeKind::Element { children, .. } = &mut this.kind { if let E4XNodeKind::Element { children, .. } = &mut this.kind {

View File

@ -31,8 +31,9 @@ package {
AS3 native function localName():Object; AS3 native function localName():Object;
AS3 native function toXMLString():String; AS3 native function toXMLString():String;
AS3 native function child(name:Object):XMLList; AS3 native function child(name:Object):XMLList;
AS3 native function parent():*;
AS3 native function children():XMLList; AS3 native function children():XMLList;
AS3 native function copy():XML;
AS3 native function parent():*;
AS3 native function elements(name:*):XMLList; AS3 native function elements(name:*):XMLList;
AS3 native function attributes():XMLList; AS3 native function attributes():XMLList;
AS3 native function attribute(name:*):XMLList; AS3 native function attribute(name:*):XMLList;
@ -75,7 +76,12 @@ package {
var self:XML = this; var self:XML = this;
return self.AS3::children(); return self.AS3::children();
}; };
prototype.copy = function():XML {
var self:XML = this;
return self.AS3::copy();
}
prototype.parent = function():* { prototype.parent = function():* {
var self:XML = this; var self:XML = this;
return self.AS3::parent(); return self.AS3::parent();

View File

@ -149,6 +149,16 @@ pub fn children<'gc>(
Ok(XmlListObject::new(activation, children, Some(xml.into())).into()) Ok(XmlListObject::new(activation, children, Some(xml.into())).into())
} }
pub fn copy<'gc>(
activation: &mut Activation<'_, 'gc>,
this: Option<Object<'gc>>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let xml = this.unwrap().as_xml_object().unwrap();
let node = xml.node();
Ok(XmlObject::new(node.deep_copy(activation.context.gc_context), activation).into())
}
pub fn parent<'gc>( pub fn parent<'gc>(
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
this: Option<Object<'gc>>, this: Option<Object<'gc>>,