From 23a488be687b000fecbcaf9f8a415c06a021df9c Mon Sep 17 00:00:00 2001 From: ldm0 Date: Wed, 9 Sep 2026 18:38:28 +0800 Subject: [PATCH] fix(domparser): preserve XML content types Extract an independently mergeable topic from wpt-misc-fix at a70a96f9d1e0573cc9721275fc03b78e4c35d3f1. Append only the XML content-type regression to the baseline test module. Use empty XML to exercise the existing parser-error-document path; the original undeclared-prefix input requires a separate namespace parser fix. Content-type and error-document assertions are retained. Source commits: - c8eed633acad222aceaaf0cf88ab194ac20c8e96 Validation: - cargo fmt --all - cargo clippy --workspace --all-targets --all-features -- -D warnings - cargo nextest run --no-fail-fast --- moli-renderer-v8/src/dom_parser.rs | 34 +++++++++++++++++-- .../script_vm/tests/dom_elements/detached.rs | 34 +++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/moli-renderer-v8/src/dom_parser.rs b/moli-renderer-v8/src/dom_parser.rs index df5f7bb4a5..786ed868b1 100644 --- a/moli-renderer-v8/src/dom_parser.rs +++ b/moli-renderer-v8/src/dom_parser.rs @@ -188,7 +188,13 @@ pub(super) fn parse_detached_document_from_string<'s>( } else { materialize_xml_parser_error_document(parsed) }; - build_detached_document(scope, parsed, DetachedDocumentKind::Xml, false) + build_detached_document_with_content_type( + scope, + parsed, + DetachedDocumentKind::Xml, + false, + Some(mime), + ) } fn materialize_xml_parser_error_document(parsed: NativeDom) -> NativeDom { @@ -398,11 +404,33 @@ fn build_detached_document<'s>( kind: DetachedDocumentKind, expose_declarative_shadow_roots: bool, ) -> Option> { - build_detached_document_from_dom_host( + build_detached_document_with_content_type( scope, - DomHost::from_dom(parsed), + parsed, kind, expose_declarative_shadow_roots, + None, + ) +} + +fn build_detached_document_with_content_type<'s>( + scope: &mut v8::PinScope<'s, '_>, + parsed: NativeDom, + kind: DetachedDocumentKind, + expose_declarative_shadow_roots: bool, + content_type: Option<&str>, +) -> Option> { + let _ = expose_declarative_shadow_roots; + let kind = match kind { + DetachedDocumentKind::Html => "html", + DetachedDocumentKind::Xml => "xml", + }; + build_detached_document_object_from_dom_host_with_content_type( + scope, + kind, + DomHost::from_dom(parsed), + content_type, + None, ) } diff --git a/moli-renderer-v8/src/script_vm/tests/dom_elements/detached.rs b/moli-renderer-v8/src/script_vm/tests/dom_elements/detached.rs index ec05de2159..443719fa08 100644 --- a/moli-renderer-v8/src/script_vm/tests/dom_elements/detached.rs +++ b/moli-renderer-v8/src/script_vm/tests/dom_elements/detached.rs @@ -8699,3 +8699,37 @@ fn detached_domparser_adopted_nodes_follow_live_tree_for_children_text_and_mutat r#"{"beforeRemoval":{"firstChildIsHeld":true,"childParentIsForeignRoot":true,"childNodesLength":2,"lastChildType":3,"textContent":"xy","containsHeldChild":true},"afterRemoval":{"removedIsHeld":true,"removedParentIsNull":true,"childNodesLength":1,"firstChildType":3,"textContent":"y","liveBodyText":"y"}}"# ); } + +#[test] +fn domparser_xml_preserves_requested_content_type_for_success_and_error_documents() { + let mut vm = new_storage_test_vm("https://domparser-xml-content-type.test/"); + + let result = vm + .eval( + r#" +(() => { + const parser = new DOMParser(); + return JSON.stringify([ + "text/xml", + "application/xml", + "application/xhtml+xml", + "image/svg+xml" + ].map(contentType => { + const valid = parser.parseFromString("", contentType); + const invalid = parser.parseFromString("", contentType); + return [ + valid.contentType, + invalid.contentType, + invalid.documentElement.localName + ]; + })); +})() +"#, + ) + .expect("DOMParser XML content type probe should evaluate"); + + assert_eq!( + result, + r#"[["text/xml","text/xml","html"],["application/xml","application/xml","html"],["application/xhtml+xml","application/xhtml+xml","html"],["image/svg+xml","image/svg+xml","html"]]"# + ); +}