From 23c09470728ccf3b1bf92237236f4d1c1eb29046 Mon Sep 17 00:00:00 2001 From: Mukilan Thiyagarajan Date: Fri, 8 Aug 2025 17:22:59 +0530 Subject: [PATCH] script: make `Node::xml_serialize` fallible. (#38532) Testing: [Try run][1] did not reveal any test failures. There doesn't seem to be any straightforward failure scenarios that can be triggered in `xml5ever` that are not IO errors and the xml_serialize method simply serializes to a String buffer. [1]: https://github.com/servo/servo/actions/runs/16824267959/job/47657275606l Signed-off-by: Mukilan Thiyagarajan --- components/script/dom/element.rs | 4 ++-- components/script/dom/node.rs | 20 ++++++++++++++------ components/script/dom/shadowroot.rs | 2 ++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 4f044dbc14b..2901ce7ea20 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -3830,7 +3830,7 @@ impl ElementMethods for Element { .html_serialize(ChildrenOnly(Some(qname)), false, vec![], can_gc) } else { self.upcast::() - .xml_serialize(XmlChildrenOnly(Some(qname))) + .xml_serialize(XmlChildrenOnly(Some(qname)))? }; Ok(TrustedHTMLOrNullIsEmptyString::NullIsEmptyString(result)) @@ -3888,7 +3888,7 @@ impl ElementMethods for Element { self.upcast::() .html_serialize(IncludeNode, false, vec![], can_gc) } else { - self.upcast::().xml_serialize(XmlIncludeNode) + self.upcast::().xml_serialize(XmlIncludeNode)? }; Ok(TrustedHTMLOrNullIsEmptyString::NullIsEmptyString(result)) diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 43e623cb72d..0b291618b19 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -3150,17 +3150,25 @@ impl Node { pub(crate) fn xml_serialize( &self, traversal_scope: xml_serialize::TraversalScope, - ) -> DOMString { + ) -> Fallible { let mut writer = vec![]; xml_serialize::serialize( &mut writer, &self, xml_serialize::SerializeOpts { traversal_scope }, ) - .expect("Cannot serialize node"); + .map_err(|error| { + error!("Cannot serialize node: {error}"); + Error::InvalidState + })?; // FIXME(ajeffrey): Directly convert UTF8 to DOMString - DOMString::from(String::from_utf8(writer).unwrap()) + let string = DOMString::from(String::from_utf8(writer).map_err(|error| { + error!("Cannot serialize node: {error}"); + Error::InvalidState + })?); + + Ok(string) } /// @@ -3168,19 +3176,19 @@ impl Node { &self, require_well_formed: bool, can_gc: CanGc, - ) -> DOMString { + ) -> Fallible { // Step 1. Let context document be node's node document. let context_document = self.owner_document(); // Step 2. If context document is an HTML document, return the result of HTML fragment serialization algorithm // with node, false, and « ». if context_document.is_html_document() { - return self.html_serialize( + return Ok(self.html_serialize( html_serialize::TraversalScope::ChildrenOnly(None), false, vec![], can_gc, - ); + )); } // Step 3. Return the XML serialization of node given require well-formed. diff --git a/components/script/dom/shadowroot.rs b/components/script/dom/shadowroot.rs index 4832b26e571..6e59d1af106 100644 --- a/components/script/dom/shadowroot.rs +++ b/components/script/dom/shadowroot.rs @@ -464,6 +464,8 @@ impl ShadowRootMethods for ShadowRoot { // algorithm steps with this and true. self.upcast::() .fragment_serialization_algorithm(true, can_gc) + .inspect_err(|error| warn!("fragment serialization failed: {error:?}")) + .unwrap_or_default() } ///