avm2: Implement a few avmplus XML edge cases

This commit is contained in:
sleepycatcoding 2024-06-02 00:04:39 +03:00
parent 1402a59a20
commit 83cc8cf294
4 changed files with 27 additions and 5 deletions

View File

@ -829,12 +829,24 @@ pub fn replace<'gc>(
// 2. If Type(value) ∉ {XML, XMLList}, let c = ToString(value)
// 3. Else let c be the result of calling the [[DeepCopy]] method of value
let value = if let Some(xml) = value.as_object().and_then(|x| x.as_xml_object()) {
let node = xml.node();
XmlObject::new(node.deep_copy(activation.context.gc_context), activation).into()
xml.deep_copy(activation).into()
} else if let Some(list) = value.as_object().and_then(|x| x.as_xml_list_object()) {
list.deep_copy(activation).into()
} else {
value
// NOTE: Depends on root swf version.
// See https://github.com/adobe/avmplus/blob/858d034a3bd3a54d9b70909386435cf4aec81d21/core/XMLObject.cpp#L1540
if activation.context.swf.version() <= 9 {
// SWF version 9 edge case, call XML constructor.
// https://github.com/adobe/avmplus/blob/858d034a3bd3a54d9b70909386435cf4aec81d21/core/XMLObject.cpp#L2241-L2242
activation
.avm2()
.classes()
.xml
.construct(activation, &[value])?
.into()
} else {
value
}
};
// 4. If ToString(ToUint32(P)) == P

View File

@ -717,6 +717,18 @@ impl<'gc> TObject<'gc> for XmlListObject<'gc> {
E4XNode::text(activation.gc(), "".into(), r)
}
None => E4XNode::text(activation.gc(), "".into(), r),
// NOTE: avmplus edge case.
// See https://github.com/adobe/avmplus/blob/858d034a3bd3a54d9b70909386435cf4aec81d21/core/XMLListObject.cpp#L297-L300
_ if value
.as_object()
.and_then(|x| x.as_xml_object())
.map_or(false, |x| {
x.node().is_text() || x.node().is_attribute()
}) =>
{
E4XNode::text(activation.gc(), "".into(), r)
}
// 2.c.vi. Else let y.[[Class]] = "element"
Some(property) => E4XNode::element(
activation.gc(),

View File

@ -1,2 +1 @@
num_ticks = 1
known_failure = true

View File

@ -1,2 +1 @@
num_ticks = 1
known_failure = true