Repository: servo/servo (language: python)

Issue:
Support ShadowDom
We have two existing issues

- https://github.com/servo/servo/issues/23590
- https://github.com/servo/servo/issues/23591

that are referring to an old spec that doesn't exist anymore. So I will close those so we can refocus here. 

The shadow DOM seems to be specified in various places of the DOM spec, such as:
- https://dom.spec.whatwg.org/#dom-element-attachshadow
- https://dom.spec.whatwg.org/#interface-shadowroot

-----------------

First question: what do we need to support the shadow dom? 

There has been some recent work such as https://github.com/servo/servo/pull/34306 and https://github.com/servo/servo/pull/34298, and it would be good to have a list of TODO's in one issue for work that remains to be done. 

For example, it appears to me that to support the shadow DOM, one needs to implement related concepts such as [`HTMLSlotElement`](https://html.spec.whatwg.org/multipage/scripting.html#the-slot-element) and [`shadow-tree-slots`](https://dom.spec.whatwg.org/#shadow-tree-slots). Since this is a meta issue, this could be the place to list all the various elements(pun intended) needed to implement shadow DOM, and supplement this with standalone issues for individual elements. 

There are also other concepts that rely on the shadow DOM, such as [Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components), and we could list them here as well(if we plan on implementing them). 


Discussion / hints:
@simonwuelker I saw you were active in this space, perhaps you have an idea on how to answer the question above?
@jdm just seeing on the proposed roadmap that you have committed to this. 

Fix patch:
diff --git a/components/script/dom/bindings/codegen/Bindings.conf b/components/script/dom/bindings/codegen/Bindings.conf
index 27bbc202f222b..48d9392465fb2 100644
--- a/components/script/dom/bindings/codegen/Bindings.conf
+++ b/components/script/dom/bindings/codegen/Bindings.conf
@@ -420,7 +420,7 @@ DOMInterfaces = {
 },
 
 'ShadowRoot': {
-    'canGc': ['ElementFromPoint', 'ElementsFromPoint'],
+    'canGc': ['ElementFromPoint', 'ElementsFromPoint', 'SetInnerHTML'],
 },
 
 'StaticRange': {
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 1c6d22c979a64..41aec11ca90d7 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -18,10 +18,8 @@ use dom_struct::dom_struct;
 use embedder_traits::InputMethodType;
 use euclid::default::{Rect, Size2D};
 use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
-use html5ever::serialize::{SerializeOpts, TraversalScope};
 use html5ever::{
-    local_name, namespace_prefix, namespace_url, ns, serialize, LocalName, Namespace, Prefix,
-    QualName,
+    local_name, namespace_prefix, namespace_url, ns, LocalName, Namespace, Prefix, QualName,
 };
 use js::jsapi::Heap;
 use js::jsval::JSVal;
@@ -61,11 +59,9 @@ use style::values::generics::NonNegative;
 use style::values::{computed, specified, AtomIdent, AtomString, CSSFloat};
 use style::{dom_apis, thread_state, ArcSlice, CaseSensitivityExt};
 use style_dom::ElementState;
-use xml5ever::serialize as xmlSerialize;
 use xml5ever::serialize::TraversalScope::{
     ChildrenOnly as XmlChildrenOnly, IncludeNode as XmlIncludeNode,
 };
-use xml5ever::serialize::{SerializeOpts as XmlSerializeOpts, TraversalScope as XmlTraversalScope};
 
 use super::htmltablecolelement::{HTMLTableColElement, HTMLTableColElementLayoutHelpers};
 use crate::dom::activation::Activatable;
@@ -1327,35 +1323,6 @@ impl Element {
         }
     }
 
-    pub fn serialize(&self, traversal_scope: TraversalScope) -> Fallible<DOMString> {
-        let mut writer = vec![];
-        match serialize(
-            &mut writer,
-            &self.upcast::<Node>(),
-            SerializeOpts {
-                traversal_scope,
-                ..Default::default()
-            },
-        ) {
-            // FIXME(ajeffrey): Directly convert UTF8 to DOMString
-            Ok(()) => Ok(DOMString::from(String::from_utf8(writer).unwrap())),
-            Err(_) => panic!("Cannot serialize element"),
-        }
-    }
-
-    #[allow(non_snake_case)]
-    pub fn xmlSerialize(&self, traversal_scope: XmlTraversalScope) -> Fallible<DOMString> {
-        let mut writer = vec![];
-        match xmlSerialize::serialize(
-            &mut writer,
-            &self.upcast::<Node>(),
-            XmlSerializeOpts { traversal_scope },
-        ) {
-            Ok(()) => Ok(DOMString::from(String::from_utf8(writer).unwrap())),
-            Err(_) => panic!("Cannot serialize element"),
-        }
-    }
-
     pub fn root_element(&self) -> DomRoot<Element> {
         if self.node.is_in_doc() {
             self.upcast::<Node>()
@@ -1959,7 +1926,7 @@ impl Element {
         win.scroll_node(node, x, y, behavior, can_gc);
     }
 
-    // https://w3c.github.io/DOM-Parsing/#parsing
+    /// <https://html.spec.whatwg.org/multipage/#fragment-parsing-algorithm-steps>
     pub fn parse_fragment(
         &self,
         markup: DOMString,
@@ -2743,21 +2710,26 @@ impl ElementMethods for Element {
         self.client_rect(can_gc).size.height
     }
 
-    /// <https://w3c.github.io/DOM-Parsing/#widl-Element-innerHTML>
+    /// <https://html.spec.whatwg.org/multipage/#dom-element-innerhtml>
     fn GetInnerHTML(&self) -> Fallible<DOMString> {
         let qname = QualName::new(
             self.prefix().clone(),
             self.namespace().clone(),
             self.local_name().clone(),
         );
-        if document_from_node(self).is_html_document() {
-            self.serialize(ChildrenOnly(Some(qname)))
+
+        let result = if document_from_node(self).is_html_document() {
+            self.upcast::<Node>()
+                .html_serialize(ChildrenOnly(Some(qname)))
         } else {
-            self.xmlSerialize(XmlChildrenOnly(Some(qname)))
-        }
+            self.upcast::<Node>()
+                .xml_serialize(XmlChildrenOnly(Some(qname)))
+        };
+
+        Ok(result)
     }
 
-    /// <https://w3c.github.io/DOM-Parsing/#widl-Element-innerHTML>
+    /// <https://html.spec.whatwg.org/multipage/#dom-element-innerhtml>
     fn SetInnerHTML(&self, value: DOMString, can_gc: CanGc) -> ErrorResult {
         // Step 2.
         // https://github.com/w3c/DOM-Parsing/issues/1
@@ -2787,16 +2759,18 @@ impl ElementMethods for Element {
         Ok(())
     }
 
-    // https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#widl-Element-outerHTML
+    /// <https://html.spec.whatwg.org/multipage/#dom-element-outerhtml>
     fn GetOuterHTML(&self) -> Fallible<DOMString> {
-        if document_from_node(self).is_html_document() {
-            self.serialize(IncludeNode)
+        let result = if document_from_node(self).is_html_document() {
+            self.upcast::<Node>().html_serialize(IncludeNode)
         } else {
-            self.xmlSerialize(XmlIncludeNode)
-        }
+            self.upcast::<Node>().xml_serialize(XmlIncludeNode)
+        };
+
+        Ok(result)
     }
 
-    // https://w3c.github.io/DOM-Parsing/#dom-element-outerhtml
+    /// <https://html.spec.whatwg.org/multipage/#dom-element-outerhtml>
     fn SetOuterHTML(&self, value: DOMString, can_gc: CanGc) -> ErrorResult {
         let context_document = document_from_node(self);
         let context_node = self.upcast::<Node>();
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 3267204fda43d..a102682d8c65a 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -18,7 +18,7 @@ use bitflags::bitflags;
 use devtools_traits::NodeInfo;
 use dom_struct::dom_struct;
 use euclid::default::{Rect, Size2D, Vector2D};
-use html5ever::{namespace_url, ns, Namespace, Prefix, QualName};
+use html5ever::{namespace_url, ns, serialize as html_serialize, Namespace, Prefix, QualName};
 use js::jsapi::JSObject;
 use js::rust::HandleObject;
 use libc::{self, c_void, uintptr_t};
@@ -43,6 +43,7 @@ use style::properties::ComputedValues;
 use style::selector_parser::{SelectorImpl, SelectorParser};
 use style::stylesheets::{Stylesheet, UrlExtraData};
 use uuid::Uuid;
+use xml5ever::serialize as xml_serialize;
 
 use crate::document_loader::DocumentLoader;
 use crate::dom::attr::Attr;
@@ -2448,6 +2449,52 @@ impl Node {
         }
         &*(conversions::private_from_object(object) as *const Self)
     }
+
+    pub fn html_serialize(&self, traversal_scope: html_serialize::TraversalScope) -> DOMString {
+        let mut writer = vec![];
+        html_serialize::serialize(
+            &mut writer,
+            &self,
+            html_serialize::SerializeOpts {
+                traversal_scope,
+                ..Default::default()
+            },
+        )
+        .expect("Cannot serialize node");
+
+        // FIXME(ajeffrey): Directly convert UTF8 to DOMString
+        DOMString::from(String::from_utf8(writer).unwrap())
+    }
+
+    pub fn xml_serialize(&self, traversal_scope: xml_serialize::TraversalScope) -> DOMString {
+        let mut writer = vec![];
+        xml_serialize::serialize(
+            &mut writer,
+            &self,
+            xml_serialize::SerializeOpts { traversal_scope },
+        )
+        .expect("Cannot serialize node");
+
+        // FIXME(ajeffrey): Directly convert UTF8 to DOMString
+        DOMString::from(String::from_utf8(writer).unwrap())
+    }
+
+    /// <https://html.spec.whatwg.org/multipage/#fragment-serializing-algorithm-steps>
+    pub fn fragment_serialization_algorithm(&self, require_well_formed: bool) -> DOMString {
+        // Step 1. Let context document be node's node document.
+        let context_document = document_from_node(self);
+
+        // 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(html_serialize::TraversalScope::ChildrenOnly(None));
+        }
+
+        // Step 3. Return the XML serialization of node given require well-formed.
+        // TODO: xml5ever doesn't seem to want require_well_formed
+        let _ = require_well_formed;
+        self.xml_serialize(xml_serialize::TraversalScope::ChildrenOnly(None))
+    }
 }
 
 impl NodeMethods for Node {
diff --git a/components/script/dom/shadowroot.rs b/components/script/dom/shadowroot.rs
index 22967bb5ad256..d781080686415 100644
--- a/components/script/dom/shadowroot.rs
+++ b/components/script/dom/shadowroot.rs
@@ -18,6 +18,7 @@ use crate::dom::bindings::inheritance::Castable;
 use crate::dom::bindings::num::Finite;
 use crate::dom::bindings::reflector::reflect_dom_object;
 use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
+use crate::dom::bindings::str::DOMString;
 use crate::dom::cssstylesheet::CSSStyleSheet;
 use crate::dom::document::Document;
 use crate::dom::documentfragment::DocumentFragment;
@@ -249,6 +250,34 @@ impl ShadowRootMethods for ShadowRoot {
             )
         })
     }
+
+    /// <https://html.spec.whatwg.org/multipage/#dom-shadowroot-innerhtml>
+    fn InnerHTML(&self) -> DOMString {
+        // ShadowRoot's innerHTML getter steps are to return the result of running fragment serializing
+        // algorithm steps with this and true.
+        self.upcast::<Node>().fragment_serialization_algorithm(true)
+    }
+
+    /// <https://html.spec.whatwg.org/multipage/#dom-shadowroot-innerhtml>
+    fn SetInnerHTML(&self, value: DOMString, can_gc: CanGc) {
+        // TODO Step 1. Let compliantString be the result of invoking the Get Trusted Type compliant string algorithm
+        // with TrustedHTML, this's relevant global object, the given value, "ShadowRoot innerHTML", and "script".
+        let compliant_string = value;
+
+        // Step 2. Let context be this's host.
+        let context = self.Host();
+
+        // Step 3. Let fragment be the result of invoking the fragment parsing algorithm steps with context and
+        // compliantString.
+        let Ok(frag) = context.parse_fragment(compliant_string, can_gc) else {
+            // NOTE: The spec doesn't strictly tell us to bail out here, but
+            // we can't continue if parsing failed
+            return;
+        };
+
+        // Step 4. Replace all with fragment within this.
+        Node::replace_all(Some(frag.upcast()), self.upcast());
+    }
 }
 
 #[allow(unsafe_code)]
diff --git a/components/script/dom/webidls/Element.webidl b/components/script/dom/webidls/Element.webidl
index 4525e4ae9c8bd..99d17117221d4 100644
--- a/components/script/dom/webidls/Element.webidl
+++ b/components/script/dom/webidls/Element.webidl
@@ -121,10 +121,8 @@ partial interface Element {
 
 // https://w3c.github.io/DOM-Parsing/#extensions-to-the-element-interface
 partial interface Element {
-  [CEReactions, Throws]
-  attribute [LegacyNullToEmptyString] DOMString innerHTML;
-  [CEReactions, Throws]
-  attribute [LegacyNullToEmptyString] DOMString outerHTML;
+  [CEReactions, Throws] attribute [LegacyNullToEmptyString] DOMString innerHTML;
+  [CEReactions, Throws] attribute [LegacyNullToEmptyString] DOMString outerHTML;
 };
 
 // https://fullscreen.spec.whatwg.org/#api
diff --git a/components/script/dom/webidls/ShadowRoot.webidl b/components/script/dom/webidls/ShadowRoot.webidl
index c8f3e75401655..a1ecdc5c10fd6 100644
--- a/components/script/dom/webidls/ShadowRoot.webidl
+++ b/components/script/dom/webidls/ShadowRoot.webidl
@@ -16,3 +16,12 @@ enum ShadowRootMode { "open", "closed"};
 // enum SlotAssignmentMode { "manual", "named" };
 
 ShadowRoot includes DocumentOrShadowRoot;
+
+// https://html.spec.whatwg.org/multipage/#dom-parsing-and-serialization
+partial interface ShadowRoot {
+  // [CEReactions] undefined setHTMLUnsafe((TrustedHTML or DOMString) html);
+  // DOMString getHTML(optional GetHTMLOptions options = {});
+
+  // [CEReactions] attribute (TrustedHTML or [LegacyNullToEmptyString] DOMString) innerHTML;
+  [CEReactions] attribute [LegacyNullToEmptyString] DOMString innerHTML;
+};


Test patch:
diff --git a/tests/wpt/meta/css/cssom/getComputedStyle-display-none-001.html.ini b/tests/wpt/meta/css/cssom/getComputedStyle-display-none-001.html.ini
deleted file mode 100644
index 7e1de88282019..0000000000000
--- a/tests/wpt/meta/css/cssom/getComputedStyle-display-none-001.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[getComputedStyle-display-none-001.html]
-  [getComputedStyle gets invalidated in display: none subtrees due to inherited changes to an ancestor shadow host]
-    expected: FAIL
diff --git a/tests/wpt/meta/css/cssom/selectorText-modification-restyle-002.html.ini b/tests/wpt/meta/css/cssom/selectorText-modification-restyle-002.html.ini
deleted file mode 100644
index f91a321b6eaf6..0000000000000
--- a/tests/wpt/meta/css/cssom/selectorText-modification-restyle-002.html.ini
+++ /dev/null
@@ -1,6 +0,0 @@
-[selectorText-modification-restyle-002.html]
-  [Check initial color.]
-    expected: FAIL
-
-  [Check that color changes correctly after shadow stylesheet selector and #container class is changed.]
-    expected: FAIL
diff --git a/tests/wpt/meta/css/selectors/invalidation/host-context-pseudo-class-in-has.html.ini b/tests/wpt/meta/css/selectors/invalidation/host-context-pseudo-class-in-has.html.ini
index bad4fa74e5465..acf292de55e43 100644
--- a/tests/wpt/meta/css/selectors/invalidation/host-context-pseudo-class-in-has.html.ini
+++ b/tests/wpt/meta/css/selectors/invalidation/host-context-pseudo-class-in-has.html.ini
@@ -1,18 +1,6 @@
 [host-context-pseudo-class-in-has.html]
-  [Before adding 'a' to #host_parent: Check #subject1 color]
-    expected: FAIL
-
-  [Before adding 'a' to #host_parent: Check #subject2 color]
-    expected: FAIL
-
   [After adding 'a' to #host_parent: Check #subject1 color]
     expected: FAIL
 
   [After adding 'a' to #host_parent: Check #subject2 color]
-    expected: FAIL
-
-  [After removing 'a' from #host_parent: Check #subject1 color]
-    expected: FAIL
-
-  [After removing 'a' from #host_parent: Check #subject2 color]
-    expected: FAIL
+    expected: FAIL
\ No newline at end of file
diff --git a/tests/wpt/meta/css/selectors/invalidation/host-pseudo-class-in-has.html.ini b/tests/wpt/meta/css/selectors/invalidation/host-pseudo-class-in-has.html.ini
index f42d2f4afaa68..b5071047b91fd 100644
--- a/tests/wpt/meta/css/selectors/invalidation/host-pseudo-class-in-has.html.ini
+++ b/tests/wpt/meta/css/selectors/invalidation/host-pseudo-class-in-has.html.ini
@@ -1,10 +1,4 @@
 [host-pseudo-class-in-has.html]
-  [Before adding 'a' to #host: Check #subject1 color]
-    expected: FAIL
-
-  [Before adding 'a' to #host: Check #subject2 color]
-    expected: FAIL
-
   [After adding 'a' to #host: Check #subject1 color]
     expected: FAIL
 
diff --git a/tests/wpt/meta/css/selectors/is-where-shadow.html.ini b/tests/wpt/meta/css/selectors/is-where-shadow.html.ini
index 70220f3301845..f2cddaa7f36c4 100644
--- a/tests/wpt/meta/css/selectors/is-where-shadow.html.ini
+++ b/tests/wpt/meta/css/selectors/is-where-shadow.html.ini
@@ -1,7 +1,4 @@
 [is-where-shadow.html]
-  [:is() inside :host()]
-    expected: FAIL
-
   [:is() inside :host-context()]
     expected: FAIL
 
diff --git a/tests/wpt/meta/custom-elements/reactions/ShadowRoot.html.ini b/tests/wpt/meta/custom-elements/reactions/ShadowRoot.html.ini
deleted file mode 100644
index 1775c7614ddb8..0000000000000
--- a/tests/wpt/meta/custom-elements/reactions/ShadowRoot.html.ini
+++ /dev/null
@@ -1,9 +0,0 @@
-[ShadowRoot.html]
-  [innerHTML on ShadowRoot must upgrade a custom element]
-    expected: FAIL
-
-  [innerHTML on ShadowRoot must enqueue connectedCallback on newly upgraded custom elements when the shadow root is connected]
-    expected: FAIL
-
-  [innerHTML on ShadowRoot must enqueue disconnectedCallback when removing a custom element]
-    expected: FAIL
diff --git a/tests/wpt/meta/dom/nodes/rootNode.html.ini b/tests/wpt/meta/dom/nodes/rootNode.html.ini
deleted file mode 100644
index 7aa0aa6e66199..0000000000000
--- a/tests/wpt/meta/dom/nodes/rootNode.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[rootNode.html]
-  [getRootNode() must return context object's shadow-including root if options's composed is true, and context object's root otherwise]
-    expected: FAIL
diff --git a/tests/wpt/meta/dom/ranges/Range-intersectsNode-shadow.html.ini b/tests/wpt/meta/dom/ranges/Range-intersectsNode-shadow.html.ini
deleted file mode 100644
index b8cea1bbda744..0000000000000
--- a/tests/wpt/meta/dom/ranges/Range-intersectsNode-shadow.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[Range-intersectsNode-shadow.html]
-  [Range.intersectsNode() doesn't return true for shadow children in other trees]
-    expected: FAIL
diff --git a/tests/wpt/meta/html/dom/elements/global-attributes/lang-attribute-shadow.window.js.ini b/tests/wpt/meta/html/dom/elements/global-attributes/lang-attribute-shadow.window.js.ini
index f87ed866b2437..69d3423ce8748 100644
--- a/tests/wpt/meta/html/dom/elements/global-attributes/lang-attribute-shadow.window.js.ini
+++ b/tests/wpt/meta/html/dom/elements/global-attributes/lang-attribute-shadow.window.js.ini
@@ -1,3 +1,9 @@
 [lang-attribute-shadow.window.html]
   [lang on slot inherits from shadow host]
     expected: FAIL
+
+  [lang only on host]
+    expected: FAIL
+
+  [lang on host and slotted element]
+    expected: FAIL
diff --git a/tests/wpt/meta/html/dom/idlharness.https.html.ini b/tests/wpt/meta/html/dom/idlharness.https.html.ini
index 13e94c6026e63..180782c8a4774 100644
--- a/tests/wpt/meta/html/dom/idlharness.https.html.ini
+++ b/tests/wpt/meta/html/dom/idlharness.https.html.ini
@@ -1691,9 +1691,6 @@
   [ShadowRoot interface: operation getHTML(optional GetHTMLOptions)]
     expected: FAIL
 
-  [ShadowRoot interface: attribute innerHTML]
-    expected: FAIL
-
   [Element interface: operation getHTML(optional GetHTMLOptions)]
     expected: FAIL
 
@@ -6023,9 +6020,6 @@
   [ShadowRoot interface: operation getHTML(optional GetHTMLOptions)]
     expected: FAIL
 
-  [ShadowRoot interface: attribute innerHTML]
-    expected: FAIL
-
   [Element interface: operation setHTMLUnsafe((TrustedHTML or DOMString))]
     expected: FAIL
 
diff --git a/tests/wpt/meta/html/rendering/non-replaced-elements/flow-content-0/slot-element-focusable.tentative.html.ini b/tests/wpt/meta/html/rendering/non-replaced-elements/flow-content-0/slot-element-focusable.tentative.html.ini
index af19c2689cbdc..3b41a3cb0bd38 100644
--- a/tests/wpt/meta/html/rendering/non-replaced-elements/flow-content-0/slot-element-focusable.tentative.html.ini
+++ b/tests/wpt/meta/html/rendering/non-replaced-elements/flow-content-0/slot-element-focusable.tentative.html.ini
@@ -1,4 +1,5 @@
 [slot-element-focusable.tentative.html]
+  expected: CRASH
   [slot element with display: block should be focusable]
     expected: FAIL
 
diff --git a/tests/wpt/meta/shadow-dom/ShadowRoot-interface.html.ini b/tests/wpt/meta/shadow-dom/ShadowRoot-interface.html.ini
index 806344eb89086..6fcd0c00cabee 100644
--- a/tests/wpt/meta/shadow-dom/ShadowRoot-interface.html.ini
+++ b/tests/wpt/meta/shadow-dom/ShadowRoot-interface.html.ini
@@ -1,4 +1,5 @@
 [ShadowRoot-interface.html]
+  expected: CRASH
   [ShadowRoot.activeElement must return the focused element of the context object when shadow root is open.]
     expected: FAIL
 
diff --git a/tests/wpt/meta/shadow-dom/declarative/declarative-shadow-dom-opt-in.html.ini b/tests/wpt/meta/shadow-dom/declarative/declarative-shadow-dom-opt-in.html.ini
index 51bae6a8a7ca7..72cc349d700df 100644
--- a/tests/wpt/meta/shadow-dom/declarative/declarative-shadow-dom-opt-in.html.ini
+++ b/tests/wpt/meta/shadow-dom/declarative/declarative-shadow-dom-opt-in.html.ini
@@ -4,7 +4,7 @@
     expected: FAIL
 
   [innerHTML on shadowRoot]
-    expected: FAIL
+    expected: PASS
 
   [document.write allowed from synchronous script loaded from main document]
     expected: FAIL
diff --git a/tests/wpt/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html.ini b/tests/wpt/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html.ini
deleted file mode 100644
index 057925a0bf951..0000000000000
--- a/tests/wpt/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-009.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[test-009.html]
-  [A_10_01_01_04_01_T01]
-    expected: FAIL
diff --git a/tests/wpt/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html.ini b/tests/wpt/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html.ini
deleted file mode 100644
index 825c2004515bf..0000000000000
--- a/tests/wpt/meta/shadow-dom/untriaged/elements-and-dom-objects/shadowroot-object/shadowroot-attributes/test-010.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[test-010.html]
-  [A_10_01_01_04_02_T01_02]
-    expected: FAIL
diff --git a/tests/wpt/meta/shadow-dom/untriaged/events/event-dispatch/test-002.html.ini b/tests/wpt/meta/shadow-dom/untriaged/events/event-dispatch/test-002.html.ini
deleted file mode 100644
index 651053560792e..0000000000000
--- a/tests/wpt/meta/shadow-dom/untriaged/events/event-dispatch/test-002.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[test-002.html]
-  [A_05_05_02_T01]
-    expected: FAIL
diff --git a/tests/wpt/meta/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html.ini b/tests/wpt/meta/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html.ini
deleted file mode 100644
index 806ccde1f6441..0000000000000
--- a/tests/wpt/meta/shadow-dom/untriaged/events/retargeting-focus-events/test-002.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[test-002.html]
-  [A_05_03_02_T01]
-    expected: FAIL
diff --git a/tests/wpt/meta/shadow-dom/untriaged/events/retargeting-focus-events/test-003.html.ini b/tests/wpt/meta/shadow-dom/untriaged/events/retargeting-focus-events/test-003.html.ini
deleted file mode 100644
index f71563563969a..0000000000000
--- a/tests/wpt/meta/shadow-dom/untriaged/events/retargeting-focus-events/test-003.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[test-003.html]
-  [A_05_03_03_T01]
-    expected: FAIL
diff --git a/tests/wpt/meta/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html.ini b/tests/wpt/meta/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html.ini
index 5c9aa9bdd7dcf..866e5e11ac319 100644
--- a/tests/wpt/meta/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html.ini
+++ b/tests/wpt/meta/shadow-dom/untriaged/shadow-trees/upper-boundary-encapsulation/dom-tree-accessors-001.html.ini
@@ -1,12 +1,6 @@
 [dom-tree-accessors-001.html]
-  [The content of title element in a shadow tree should not be accessible from owner document's "title" attribute.]
-    expected: FAIL
-
   [Elements in a shadow tree should not be accessible from owner document's getElementsByName() method.]
     expected: FAIL
 
   [Elements in a shadow tree should not be accessible from owner document's "all" attribute.]
     expected: FAIL
-
-  [Elements in a shadow tree should not be accessible from owner document's getElementById() method.]
-    expected: FAIL