avm2: Implement XML pretty printing

This commit is contained in:
sleepycatcoding 2023-08-22 12:51:34 +03:00 committed by Aaron Hill
parent 34295f25ff
commit 991976e437
12 changed files with 63 additions and 15 deletions

View File

@ -801,13 +801,21 @@ pub fn escape_element_value(s: AvmString) -> WString {
r r
} }
fn to_xml_string_inner(xml: E4XOrXml, buf: &mut WString) { fn to_xml_string_inner(xml: E4XOrXml, buf: &mut WString, pretty: Option<(u32, u32)>) {
// FIXME: Implement pretty printing and namespace support. // FIXME: Namespace support.
let node = xml.node(); let node = xml.node();
let node_kind = node.kind(); let node_kind = node.kind();
if let Some((indent_level, _)) = pretty {
for _ in 0..indent_level {
buf.push_char(' ');
}
}
let (children, attributes) = match &*node_kind { let (children, attributes) = match &*node_kind {
E4XNodeKind::Text(text) => { E4XNodeKind::Text(text) => {
// FIXME: Spec says to trim XMLWhitespace characters here
buf.push_str(&escape_element_value(*text)); buf.push_str(&escape_element_value(*text));
return; return;
} }
@ -862,8 +870,32 @@ fn to_xml_string_inner(xml: E4XOrXml, buf: &mut WString) {
buf.push_char('>'); buf.push_char('>');
let indent_children = children.len() > 1
|| children.len() == 1 && !matches!(*children[0].kind(), E4XNodeKind::Text(_));
let child_pretty = if let Some((indent_level, pretty_indent)) = pretty {
if indent_children {
Some((indent_level + pretty_indent, pretty_indent))
} else {
None
}
} else {
None
};
for child in children { for child in children {
to_xml_string_inner(E4XOrXml::E4X(*child), buf); if pretty.is_some() && indent_children {
buf.push_char('\n');
}
to_xml_string_inner(E4XOrXml::E4X(*child), buf, child_pretty);
}
if let Some((indent_level, _)) = pretty {
if indent_children {
buf.push_char('\n');
for _ in 0..indent_level {
buf.push_char(' ');
}
}
} }
buf.push_utf8("</"); buf.push_utf8("</");
@ -876,8 +908,35 @@ pub fn to_xml_string<'gc>(
xml: E4XOrXml<'gc>, xml: E4XOrXml<'gc>,
activation: &mut Activation<'_, 'gc>, activation: &mut Activation<'_, 'gc>,
) -> AvmString<'gc> { ) -> AvmString<'gc> {
let pretty_printing = activation
.avm2()
.classes()
.xml
.get_public_property("prettyPrinting", activation)
.expect("prettyPrinting should be set")
.coerce_to_boolean();
let pretty = if pretty_printing {
let pretty_indent = activation
.avm2()
.classes()
.xml
.get_public_property("prettyIndent", activation)
.expect("prettyIndent should be set")
.coerce_to_i32(activation)
.expect("shouldnt error");
// NOTE: Negative values are invalid and are ignored.
if pretty_indent < 0 {
None
} else {
Some((0, pretty_indent as u32))
}
} else {
None
};
let mut buf = WString::new(); let mut buf = WString::new();
to_xml_string_inner(xml, &mut buf); to_xml_string_inner(xml, &mut buf, pretty);
AvmString::new(activation.context.gc_context, buf) AvmString::new(activation.context.gc_context, buf)
} }

View File

@ -1,2 +1 @@
num_ticks = 1 num_ticks = 1
known_failure = true # https://github.com/ruffle-rs/ruffle/issues/12321

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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