mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Implement element.shadowRoot
attribute (#34306)
* Implement Element.shadowRoot attribute Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Remove comments about shadowdom not being exposed for web content This is obviously not the case anymore. Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> * Update WPT expectations Signed-off-by: Simon Wülker <simon.wuelker@arcor.de> --------- Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
parent
c5cf2621b6
commit
527e2d426d
15 changed files with 209 additions and 65 deletions
|
@ -73,11 +73,13 @@ use crate::dom::attr::{Attr, AttrHelpersForLayout};
|
|||
use crate::dom::bindings::cell::{ref_filter_map, DomRefCell, Ref, RefMut};
|
||||
use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::ElementBinding::{ElementMethods, ShadowRootInit};
|
||||
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||
use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRoot_Binding::ShadowRootMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{
|
||||
ShadowRootMethods, ShadowRootMode,
|
||||
};
|
||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::{
|
||||
ScrollBehavior, ScrollToOptions, WindowMethods,
|
||||
};
|
||||
|
@ -507,9 +509,11 @@ impl Element {
|
|||
}
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#dom-element-attachshadow>
|
||||
/// XXX This is not exposed to web content yet. It is meant to be used
|
||||
/// for UA widgets only.
|
||||
pub fn attach_shadow(&self, is_ua_widget: IsUserAgentWidget) -> Fallible<DomRoot<ShadowRoot>> {
|
||||
pub fn attach_shadow(
|
||||
&self,
|
||||
is_ua_widget: IsUserAgentWidget,
|
||||
mode: ShadowRootMode,
|
||||
) -> Fallible<DomRoot<ShadowRoot>> {
|
||||
// Step 1.
|
||||
if self.namespace != ns!(html) {
|
||||
return Err(Error::NotSupported);
|
||||
|
@ -546,7 +550,7 @@ impl Element {
|
|||
}
|
||||
|
||||
// Steps 4, 5 and 6.
|
||||
let shadow_root = ShadowRoot::new(self, &self.node.owner_doc());
|
||||
let shadow_root = ShadowRoot::new(self, &self.node.owner_doc(), mode);
|
||||
self.ensure_rare_data().shadow_root = Some(Dom::from_ref(&*shadow_root));
|
||||
shadow_root
|
||||
.upcast::<Node>()
|
||||
|
@ -3050,11 +3054,29 @@ impl ElementMethods for Element {
|
|||
doc.enter_fullscreen(self, can_gc)
|
||||
}
|
||||
|
||||
// XXX Hidden under dom.shadowdom.enabled pref. Only exposed to be able
|
||||
// to test partial Shadow DOM support for UA widgets.
|
||||
// https://dom.spec.whatwg.org/#dom-element-attachshadow
|
||||
fn AttachShadow(&self) -> Fallible<DomRoot<ShadowRoot>> {
|
||||
self.attach_shadow(IsUserAgentWidget::No)
|
||||
fn AttachShadow(&self, init: &ShadowRootInit) -> Fallible<DomRoot<ShadowRoot>> {
|
||||
// Step 1. Run attach a shadow root with this, init["mode"], init["clonable"], init["serializable"],
|
||||
// init["delegatesFocus"], and init["slotAssignment"].
|
||||
let shadow_root = self.attach_shadow(IsUserAgentWidget::No, init.mode)?;
|
||||
|
||||
// Step 2. Return this’s shadow root.
|
||||
Ok(shadow_root)
|
||||
}
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#dom-element-shadowroot>
|
||||
fn GetShadowRoot(&self) -> Option<DomRoot<ShadowRoot>> {
|
||||
// Step 1. Let shadow be this’s shadow root.
|
||||
let shadow_or_none = self.shadow_root();
|
||||
|
||||
// Step 2. If shadow is null or its mode is "closed", then return null.
|
||||
let shadow = shadow_or_none?;
|
||||
if shadow.Mode() == ShadowRootMode::Closed {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Step 3. Return shadow.
|
||||
Some(shadow)
|
||||
}
|
||||
|
||||
fn GetRole(&self) -> Option<DOMString> {
|
||||
|
|
|
@ -54,6 +54,7 @@ use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorConsta
|
|||
use crate::dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::Navigator_Binding::NavigatorMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::NodeBinding::Node_Binding::NodeMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRootMode;
|
||||
use crate::dom::bindings::codegen::Bindings::TextTrackBinding::{TextTrackKind, TextTrackMode};
|
||||
use crate::dom::bindings::codegen::Bindings::URLBinding::URLMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::Window_Binding::WindowMethods;
|
||||
|
@ -1908,7 +1909,9 @@ impl HTMLMediaElement {
|
|||
// if we are already showing the controls.
|
||||
return;
|
||||
}
|
||||
let shadow_root = element.attach_shadow(IsUserAgentWidget::Yes).unwrap();
|
||||
let shadow_root = element
|
||||
.attach_shadow(IsUserAgentWidget::Yes, ShadowRootMode::Closed)
|
||||
.unwrap();
|
||||
let document = document_from_node(self);
|
||||
let script = HTMLScriptElement::new(
|
||||
local_name!("script"),
|
||||
|
|
|
@ -36,7 +36,7 @@ pub enum IsUserAgentWidget {
|
|||
Yes,
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#interface-shadowroot
|
||||
/// <https://dom.spec.whatwg.org/#interface-shadowroot>
|
||||
#[dom_struct]
|
||||
pub struct ShadowRoot {
|
||||
document_fragment: DocumentFragment,
|
||||
|
@ -48,11 +48,14 @@ pub struct ShadowRoot {
|
|||
author_styles: DomRefCell<AuthorStyles<StyleSheetInDocument>>,
|
||||
stylesheet_list: MutNullableDom<StyleSheetList>,
|
||||
window: Dom<Window>,
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#dom-shadowroot-mode>
|
||||
mode: ShadowRootMode,
|
||||
}
|
||||
|
||||
impl ShadowRoot {
|
||||
#[allow(crown::unrooted_must_root)]
|
||||
fn new_inherited(host: &Element, document: &Document) -> ShadowRoot {
|
||||
fn new_inherited(host: &Element, document: &Document, mode: ShadowRootMode) -> ShadowRoot {
|
||||
let document_fragment = DocumentFragment::new_inherited(document);
|
||||
let node = document_fragment.upcast::<Node>();
|
||||
node.set_flag(NodeFlags::IS_IN_SHADOW_TREE, true);
|
||||
|
@ -60,6 +63,7 @@ impl ShadowRoot {
|
|||
NodeFlags::IS_CONNECTED,
|
||||
host.upcast::<Node>().is_connected(),
|
||||
);
|
||||
|
||||
ShadowRoot {
|
||||
document_fragment,
|
||||
document_or_shadow_root: DocumentOrShadowRoot::new(document.window()),
|
||||
|
@ -68,12 +72,13 @@ impl ShadowRoot {
|
|||
author_styles: DomRefCell::new(AuthorStyles::new()),
|
||||
stylesheet_list: MutNullableDom::new(None),
|
||||
window: Dom::from_ref(document.window()),
|
||||
mode,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(host: &Element, document: &Document) -> DomRoot<ShadowRoot> {
|
||||
pub fn new(host: &Element, document: &Document, mode: ShadowRootMode) -> DomRoot<ShadowRoot> {
|
||||
reflect_dom_object(
|
||||
Box::new(ShadowRoot::new_inherited(host, document)),
|
||||
Box::new(ShadowRoot::new_inherited(host, document, mode)),
|
||||
document.window(),
|
||||
)
|
||||
}
|
||||
|
@ -226,7 +231,7 @@ impl ShadowRootMethods for ShadowRoot {
|
|||
|
||||
/// <https://dom.spec.whatwg.org/#dom-shadowroot-mode>
|
||||
fn Mode(&self) -> ShadowRootMode {
|
||||
ShadowRootMode::Closed
|
||||
self.mode
|
||||
}
|
||||
|
||||
/// <https://dom.spec.whatwg.org/#dom-shadowroot-host>
|
||||
|
|
|
@ -83,7 +83,16 @@ interface Element : Node {
|
|||
[CEReactions, Throws]
|
||||
undefined insertAdjacentHTML(DOMString position, DOMString html);
|
||||
|
||||
[Throws, Pref="dom.shadowdom.enabled"] ShadowRoot attachShadow();
|
||||
[Throws, Pref="dom.shadowdom.enabled"] ShadowRoot attachShadow(ShadowRootInit init);
|
||||
readonly attribute ShadowRoot? shadowRoot;
|
||||
};
|
||||
|
||||
dictionary ShadowRootInit {
|
||||
required ShadowRootMode mode;
|
||||
// boolean delegatesFocus = false;
|
||||
// SlotAssignmentMode slotAssignment = "named";
|
||||
// boolean clonable = false;
|
||||
// boolean serializable = false;
|
||||
};
|
||||
|
||||
// http://dev.w3.org/csswg/cssom-view/#extensions-to-the-element-interface
|
||||
|
|
|
@ -13,5 +13,6 @@ interface ShadowRoot : DocumentFragment {
|
|||
};
|
||||
|
||||
enum ShadowRootMode { "open", "closed"};
|
||||
// enum SlotAssignmentMode { "manual", "named" };
|
||||
|
||||
ShadowRoot includes DocumentOrShadowRoot;
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
[transform-origin-in-shadow.html]
|
||||
expected: ERROR
|
||||
['transform-origin' on <svg> being direct descendant of shadow root]
|
||||
expected: FAIL
|
||||
|
|
12
tests/wpt/meta/dom/idlharness.window.js.ini
vendored
12
tests/wpt/meta/dom/idlharness.window.js.ini
vendored
|
@ -64,9 +64,6 @@
|
|||
[XPathResult interface: constant STRING_TYPE on interface prototype object]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: attribute shadowRoot]
|
||||
expected: FAIL
|
||||
|
||||
[XPathResult interface: document.evaluate("//*", document.body) must inherit property "ORDERED_NODE_ITERATOR_TYPE" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -91,9 +88,6 @@
|
|||
[EventTarget interface: new AbortController().signal must inherit property "removeEventListener(DOMString, EventListener?, optional (EventListenerOptions or boolean))" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: operation attachShadow(ShadowRootInit)]
|
||||
expected: FAIL
|
||||
|
||||
[Document interface: xmlDoc must inherit property "createNSResolver(Node)" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -124,9 +118,6 @@
|
|||
[XPathResult interface: constant UNORDERED_NODE_SNAPSHOT_TYPE on interface prototype object]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: calling attachShadow(ShadowRootInit) on element with too few arguments must throw TypeError]
|
||||
expected: FAIL
|
||||
|
||||
[XPathResult interface: constant ORDERED_NODE_SNAPSHOT_TYPE on interface object]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -511,9 +502,6 @@
|
|||
[Element interface: operation append((Node or DOMString)...)]
|
||||
expected: FAIL
|
||||
|
||||
[Element interface: element must inherit property "shadowRoot" with the proper type]
|
||||
expected: FAIL
|
||||
|
||||
[XPathEvaluator interface: existence and properties of interface prototype object]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
[dialog-focus-shadow-double-nested.html]
|
||||
expected: ERROR
|
||||
expected: CRASH
|
||||
|
|
|
@ -1,2 +1,150 @@
|
|||
[dialog-focus-shadow.html]
|
||||
expected: ERROR
|
||||
[show: No autofocus, no delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: No autofocus, no delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[show: No autofocus, no delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: No autofocus, no delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[show: No autofocus, no delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: No autofocus, no delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[show: No autofocus, yes delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: No autofocus, yes delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[show: No autofocus, yes delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: No autofocus, yes delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[show: No autofocus, yes delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: No autofocus, yes delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus before, no delegatesFocus]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus before, no delegatesFocus]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus before, yes delegatesFocus]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus before, yes delegatesFocus]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus after, no delegatesFocus]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus after, no delegatesFocus]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus after, yes delegatesFocus]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus after, yes delegatesFocus]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus on shadow host, yes delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus on shadow host, yes delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus on shadow host, yes delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus on shadow host, yes delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus on shadow host, yes delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus on shadow host, yes delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus on shadow host, no delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus on shadow host, no delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus on shadow host, no delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus on shadow host, no delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus on shadow host, no delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus on shadow host, no delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus inside shadow tree, yes delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus inside shadow tree, yes delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus inside shadow tree, yes delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus inside shadow tree, yes delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus inside shadow tree, yes delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus inside shadow tree, yes delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus inside shadow tree, no delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus inside shadow tree, no delegatesFocus, no siblings]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus inside shadow tree, no delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus inside shadow tree, no delegatesFocus, sibling before]
|
||||
expected: FAIL
|
||||
|
||||
[show: Autofocus inside shadow tree, no delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Autofocus inside shadow tree, no delegatesFocus, sibling after]
|
||||
expected: FAIL
|
||||
|
||||
[show: Two shadow trees, both delegatesFocus, first tree doesn't have autofocus element, second does]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Two shadow trees, both delegatesFocus, first tree doesn't have autofocus element, second does]
|
||||
expected: FAIL
|
||||
|
||||
[show: No autofocus, no delegatesFocus, slotted target]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: No autofocus, no delegatesFocus, slotted target]
|
||||
expected: FAIL
|
||||
|
||||
[show: Shadowroot on child, no autofocus, no delegatesFocus]
|
||||
expected: FAIL
|
||||
|
||||
[showModal: Shadowroot on child, no autofocus, no delegatesFocus]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
[Element-interface-attachShadow.html]
|
||||
[Element.attachShadow must throw a TypeError if mode is not "open" or "closed"]
|
||||
expected: FAIL
|
||||
|
||||
[Element.attachShadow must throw a NotSupportedError if the context object already hosts a shadow tree]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
[Element-interface-shadowRoot-attribute.html]
|
||||
[shadowRoot must be defined on Element prototype]
|
||||
expected: FAIL
|
||||
|
||||
[shadowRoot attribute must return the open shadow root associated with the element]
|
||||
expected: FAIL
|
||||
|
||||
[shadowRoot attribute must return null if the shadow root attached to the element is closed]
|
||||
expected: FAIL
|
|
@ -4,6 +4,3 @@
|
|||
|
||||
[cloneNode on a shadow root in closed mode must throw a NotSupportedError]
|
||||
expected: FAIL
|
||||
|
||||
[cloneNode on an element with an open shadow root should not clone its shadow root]
|
||||
expected: FAIL
|
||||
|
|
|
@ -56,8 +56,5 @@
|
|||
[Declarative Shadow DOM: template containing declarative shadow root and UA shadow root]
|
||||
expected: FAIL
|
||||
|
||||
[Declarative Shadow DOM: declarative shadow roots are not supported by the template element]
|
||||
expected: FAIL
|
||||
|
||||
[Declarative Shadow DOM: explicit test that exceptions are not thrown]
|
||||
expected: FAIL
|
||||
|
|
|
@ -8,15 +8,9 @@
|
|||
[:focus applies to host with delegatesFocus=true when an element in a nested shadow tree with delegatesFocus=true is focused]
|
||||
expected: FAIL
|
||||
|
||||
[:focus should be removed from hosts with delegatesFocus=true when none of the elements in a nested shadow tree with delegatesFocus=true is focused]
|
||||
expected: FAIL
|
||||
|
||||
[:focus applies to host with delegatesFocus=true when an element in a nested shadow tree with delegatesFocus=false is focused]
|
||||
expected: FAIL
|
||||
|
||||
[:focus should be removed from hosts with delegatesFocus=true when none of the elements in a nested shadow tree with delegatesFocus=false is focused]
|
||||
expected: FAIL
|
||||
|
||||
[:focus applies to host with delegatesFocus=false when the shadow root's descendant has focus]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -26,11 +20,5 @@
|
|||
[:focus applies to host with delegatesFocus=false when an element in a nested shadow tree with delegatesFocus=true is focused]
|
||||
expected: FAIL
|
||||
|
||||
[:focus should be removed from hosts with delegatesFocus=false when none of the elements in a nested shadow tree with delegatesFocus=true is focused]
|
||||
expected: FAIL
|
||||
|
||||
[:focus applies to host with delegatesFocus=false when an element in a nested shadow tree with delegatesFocus=false is focused]
|
||||
expected: FAIL
|
||||
|
||||
[:focus should be removed from hosts with delegatesFocus=false when none of the elements in a nested shadow tree with delegatesFocus=false is focused]
|
||||
expected: FAIL
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[test-006.html]
|
||||
[A_10_02_01_06_T01]
|
||||
expected: FAIL
|
Loading…
Add table
Add a link
Reference in a new issue