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"]]"# + ); +}