fix(dom): serialize XML innerHTML by document mode

This commit is contained in:
ldm0
2026-09-22 21:44:07 +08:00
parent 86f2ab0a33
commit e447211fe2
3 changed files with 81 additions and 4 deletions
@@ -833,10 +833,16 @@ fn node_inner_text(
}
fn node_inner_html(runtime: &JsContextHost, handle: DomHandle) -> Option<String> {
let scripting_enabled_for_node = |node| runtime.node_document_scripting_enabled(node);
runtime
.dom_host()
.get_html(handle, &scripting_enabled_for_node, false, &[])
let dom_host = runtime.dom_host();
if dom_host
.node_document_is_html_document(handle)
.unwrap_or(true)
{
let scripting_enabled_for_node = |node| runtime.node_document_scripting_enabled(node);
dom_host.get_html(handle, &scripting_enabled_for_node, false, &[])
} else {
crate::xml_serializer::serialize_native_inner_html(dom_host, handle)
}
}
fn is_element_or_shadow_root_receiver(runtime: &JsContextHost, handle: DomHandle) -> bool {
@@ -3340,6 +3340,59 @@ fn set_html_unsafe_preserves_declarative_shadow_roots() {
"function|1|true|true|2|input|span|1|em|true|2|true|false|true|true|true|slot|true"
);
}
#[test]
fn set_html_unsafe_in_xml_documents_uses_xml_fragment_serialization() {
let mut vm = new_storage_test_vm("https://set-html-unsafe-xml.test/");
let result = vm
.eval(
r#"
(() => {
const markup = '<p><foo><b><i>test</b></i>';
const xml = document.implementation.createDocument(null, 'root', null);
xml.documentElement.setHTMLUnsafe(markup);
const svg = document.implementation.createDocument(
'http://www.w3.org/2000/svg',
'root',
null
);
svg.documentElement.setHTMLUnsafe(markup);
const liveSvg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
liveSvg.setHTMLUnsafe('<circle></circle>');
return [
xml.contentType,
xml.documentElement.innerHTML,
xml.documentElement.firstChild.namespaceURI,
svg.contentType,
svg.documentElement.innerHTML,
svg.documentElement.firstChild.namespaceURI,
liveSvg.innerHTML,
liveSvg.firstChild.namespaceURI
].join('|');
})()
"#,
)
.expect("setHTMLUnsafe should serialize XML document fragments as XML");
assert_eq!(
result,
concat!(
"application/xml|",
"<p xmlns=\"http://www.w3.org/1999/xhtml\"><foo><b><i>test</i></b></foo></p>|",
"http://www.w3.org/1999/xhtml|",
"image/svg+xml|",
"<p xmlns=\"http://www.w3.org/1999/xhtml\"><foo><b><i>test</i></b></foo></p>|",
"http://www.w3.org/1999/xhtml|",
"<circle></circle>|",
"http://www.w3.org/2000/svg"
)
);
}
#[test]
fn get_html_serializes_shadow_roots_when_requested() {
let mut vm = new_storage_test_vm("https://shadow-get-html.test/");
+18
View File
@@ -109,6 +109,24 @@ pub(crate) fn serialize_native_handle(dom_host: &DomHost, handle: NativeNodeId)
)
}
pub(crate) fn serialize_native_inner_html(
dom_host: &DomHost,
handle: NativeNodeId,
) -> Option<String> {
let child_container = dom_host
.node(handle)?
.as_element()
.and_then(Element::template_contents)
.unwrap_or(handle);
let mut next_generated_prefix = 1;
Some(serialize_native_children(
dom_host,
child_container,
&NamespaceContext::default(),
&mut next_generated_prefix,
))
}
fn serialize_native_node(
dom_host: &DomHost,
handle: NativeNodeId,