diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index d4ed7932dfa..79b783cbfb4 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -542,6 +542,16 @@ impl Element { clonable, can_gc, ); + + // Step 7. If element’s custom element state is "precustomized" or "custom", + // then set shadow’s available to element internals to true. + if matches!( + self.get_custom_element_state(), + CustomElementState::Precustomized | CustomElementState::Custom + ) { + shadow_root.set_available_to_element_internals(true); + } + self.ensure_rare_data().shadow_root = Some(Dom::from_ref(&*shadow_root)); shadow_root .upcast::() diff --git a/components/script/dom/elementinternals.rs b/components/script/dom/elementinternals.rs index 974799dd255..966a4dc1e3e 100644 --- a/components/script/dom/elementinternals.rs +++ b/components/script/dom/elementinternals.rs @@ -23,6 +23,7 @@ use crate::dom::htmlelement::HTMLElement; use crate::dom::htmlformelement::{FormDatum, FormDatumValue, HTMLFormElement}; use crate::dom::node::{Node, NodeTraits}; use crate::dom::nodelist::NodeList; +use crate::dom::shadowroot::ShadowRoot; use crate::dom::validation::{Validatable, is_barred_by_datalist_ancestor}; use crate::dom::validitystate::{ValidationFlags, ValidityState}; use crate::script_runtime::CanGc; @@ -188,6 +189,22 @@ impl ElementInternals { } impl ElementInternalsMethods for ElementInternals { + /// + fn GetShadowRoot(&self) -> Option> { + // Step 1. Let target be this's target element. + // Step 2. If target is not a shadow host, then return null. + // Step 3. Let shadow be target's shadow root. + let shadow = self.target_element.upcast::().shadow_root()?; + + // Step 4. If shadow's available to element internals is false, then return null. + if !shadow.is_available_to_element_internals() { + return None; + } + + // Step 5. Return shadow. + Some(shadow) + } + /// fn SetFormValue( &self, diff --git a/components/script/dom/shadowroot.rs b/components/script/dom/shadowroot.rs index 73d5c13174b..dc33ecc254f 100644 --- a/components/script/dom/shadowroot.rs +++ b/components/script/dom/shadowroot.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use std::cell::Cell; use std::collections::HashMap; use std::collections::hash_map::Entry; @@ -72,6 +73,9 @@ pub(crate) struct ShadowRoot { /// clonable: bool, + /// + available_to_element_internals: Cell, + slots: DomRefCell>>>, } @@ -103,6 +107,7 @@ impl ShadowRoot { mode, slot_assignment_mode, clonable, + available_to_element_internals: Cell::new(false), slots: Default::default(), } } @@ -252,6 +257,15 @@ impl ShadowRoot { pub(crate) fn has_slot_descendants(&self) -> bool { !self.slots.borrow().is_empty() } + + pub(crate) fn set_available_to_element_internals(&self, value: bool) { + self.available_to_element_internals.set(value); + } + + /// + pub(crate) fn is_available_to_element_internals(&self) -> bool { + self.available_to_element_internals.get() + } } impl ShadowRootMethods for ShadowRoot { diff --git a/components/script_bindings/webidls/ElementInternals.webidl b/components/script_bindings/webidls/ElementInternals.webidl index fbb0e720733..b69436e1570 100644 --- a/components/script_bindings/webidls/ElementInternals.webidl +++ b/components/script_bindings/webidls/ElementInternals.webidl @@ -5,6 +5,9 @@ // https://html.spec.whatwg.org/multipage/#elementinternals [Exposed=Window] interface ElementInternals { + // Shadow root access + readonly attribute ShadowRoot? shadowRoot; + // Form-associated custom elements [Throws] undefined setFormValue((File or USVString or FormData)? value, diff --git a/tests/wpt/meta/custom-elements/element-internals-shadowroot.html.ini b/tests/wpt/meta/custom-elements/element-internals-shadowroot.html.ini index 8867cf85984..fb222786f6a 100644 --- a/tests/wpt/meta/custom-elements/element-internals-shadowroot.html.ini +++ b/tests/wpt/meta/custom-elements/element-internals-shadowroot.html.ini @@ -1,10 +1,4 @@ [element-internals-shadowroot.html] expected: ERROR - [ElementInternals.shadowRoot allows access to open shadow root] - expected: FAIL - - [ElementInternals.shadowRoot allows access to closed shadow root] - expected: FAIL - [ElementInternals.shadowRoot doesn't reveal pre-attached closed shadowRoot] expected: FAIL diff --git a/tests/wpt/meta/custom-elements/form-associated/ElementInternals-target-element-is-held-strongly.html.ini b/tests/wpt/meta/custom-elements/form-associated/ElementInternals-target-element-is-held-strongly.html.ini deleted file mode 100644 index 3d81bc9fd8e..00000000000 --- a/tests/wpt/meta/custom-elements/form-associated/ElementInternals-target-element-is-held-strongly.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[ElementInternals-target-element-is-held-strongly.html] - [Target element of ElementsInternals is held strongly and doesn't get GCed if there are no other references] - 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 4023da292a6..5a18c8cc65e 100644 --- a/tests/wpt/meta/html/dom/idlharness.https.html.ini +++ b/tests/wpt/meta/html/dom/idlharness.https.html.ini @@ -4940,9 +4940,6 @@ [OffscreenCanvasRenderingContext2D interface: operation roundRect(unrestricted double, unrestricted double, unrestricted double, unrestricted double, optional (unrestricted double or DOMPointInit or sequence<(unrestricted double or DOMPointInit)>))] expected: FAIL - [ElementInternals interface: attribute shadowRoot] - expected: FAIL - [ElementInternals interface: attribute states] expected: FAIL