From 28c8c1df0ca54299f5e5a88c102ef4653e2d4494 Mon Sep 17 00:00:00 2001 From: batu_hoang <55729155+longvatrong111@users.noreply.github.com> Date: Mon, 17 Mar 2025 17:41:34 +0800 Subject: [PATCH] Implement declarative shadow dom (#34964) * Implement declarative shadow dom Signed-off-by: batu_hoang * Set allowDeclarativeShadowRoots false for innerHTML Signed-off-by: batu_hoang * Enable allowDeclarativeShadowRoots for Document Signed-off-by: batu_hoang * Expose HTMLTemplateElement to js Signed-off-by: batu_hoang * Implemenet setHTMLUnsafe and add more test cases Signed-off-by: batu_hoang * Declarative shadow dom: minor updates and expected test result update Signed-off-by: batu_hoang * Shadow-dom: add more test cases Signed-off-by: batu_hoang * Update comments according to the spec Signed-off-by: batu_hoang * Bump html5ever version Signed-off-by: batu_hoang --------- Signed-off-by: batu_hoang --- components/script/dom/document.rs | 19 + components/script/dom/domimplementation.rs | 1 + components/script/dom/domparser.rs | 2 + components/script/dom/element.rs | 35 +- components/script/dom/htmltemplateelement.rs | 38 +- components/script/dom/node.rs | 1 + components/script/dom/servoparser/mod.rs | 101 +- components/script/dom/shadowroot.rs | 8 + components/script/dom/xmldocument.rs | 1 + components/script/dom/xmlhttprequest.rs | 1 + components/script/script_thread.rs | 1 + .../script_bindings/codegen/Bindings.conf | 2 +- .../script_bindings/webidls/Element.webidl | 2 + .../webidls/HTMLTemplateElement.webidl | 4 + .../function-shadow-container.html.ini | 9 - .../css/css-mixins/function-shadow.html.ini | 33 - ...ee-element-at-nonsubject-position.html.ini | 78 +- ...-tree-element-at-subject-position.html.ini | 48 +- ...stomElements-exceptions.tentative.html.ini | 3 - .../meta/html/dom/idlharness.https.html.ini | 39 - .../form-indexed-element-shadow.html.ini | 3 - ...-shadowrootmode-img-src.tentative.html.ini | 3 - ...ootmode-link-stylesheet.tentative.html.ini | 3 - ...adowrootmode-script-src.tentative.html.ini | 3 - .../Element-setHTMLUnsafe-04.html.ini | 3 - .../setHTMLUnsafe-CEReactions.html.ini | 3 - .../setHTMLUnsafe-xml.html.ini | 6 - .../setHTMLUnsafe.html.ini | 9 - .../cross-shadow-boundary-6.html.ini | 2 - .../tentative/Range-isPointInRange.html.ini | 3 - ...on-getComposedRanges-range-update.html.ini | 9 +- .../tentative/Selection-isCollapsed.html.ini | 12 +- ...lightRegistry-highlightsFromPoint.html.ini | 3 - ...declarative-shadow-dom-attachment.html.ini | 1740 ----------------- .../declarative-shadow-dom-basic.html.ini | 51 - .../declarative-shadow-dom-opt-in.html.ini | 15 - .../declarative-shadow-dom-repeats-2.html.ini | 3 - .../declarative-shadow-dom-repeats.html.ini | 3 - .../declarative-with-disabled-shadow.html.ini | 3 + .../innerhtml-before-closing-tag.html.ini | 2 - .../move-template-before-closing-tag.html.ini | 6 - .../declarative/script-access.html.ini | 2 - ...fsetLeft-across-shadow-boundaries.html.ini | 3 + .../shadow-dom/shadow-root-clonable.html.ini | 9 - 44 files changed, 360 insertions(+), 1965 deletions(-) delete mode 100644 tests/wpt/meta/css/css-mixins/function-shadow-container.html.ini delete mode 100644 tests/wpt/meta/css/css-mixins/function-shadow.html.ini delete mode 100644 tests/wpt/meta/html/semantics/forms/the-form-element/form-indexed-element-shadow.html.ini delete mode 100644 tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-img-src.tentative.html.ini delete mode 100644 tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-link-stylesheet.tentative.html.ini delete mode 100644 tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-script-src.tentative.html.ini delete mode 100644 tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/Element-setHTMLUnsafe-04.html.ini delete mode 100644 tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe-xml.html.ini delete mode 100644 tests/wpt/meta/selection/shadow-dom/cross-shadow-boundary-6.html.ini delete mode 100644 tests/wpt/meta/shadow-dom/declarative/declarative-shadow-dom-repeats-2.html.ini create mode 100644 tests/wpt/meta/shadow-dom/declarative/declarative-with-disabled-shadow.html.ini delete mode 100644 tests/wpt/meta/shadow-dom/declarative/innerhtml-before-closing-tag.html.ini delete mode 100644 tests/wpt/meta/shadow-dom/declarative/move-template-before-closing-tag.html.ini delete mode 100644 tests/wpt/meta/shadow-dom/declarative/script-access.html.ini delete mode 100644 tests/wpt/meta/shadow-dom/shadow-root-clonable.html.ini diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index c7343e889a9..dc53e50d65f 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -513,6 +513,8 @@ pub(crate) struct Document { status_code: Option, /// is_initial_about_blank: Cell, + /// + allow_declarative_shadow_roots: Cell, /// #[no_trace] inherited_insecure_requests_policy: Cell>, @@ -3590,6 +3592,7 @@ impl Document { status_code: Option, canceller: FetchCanceller, is_initial_about_blank: bool, + allow_declarative_shadow_roots: bool, inherited_insecure_requests_policy: Option, ) -> Document { let url = url.unwrap_or_else(|| ServoUrl::parse("about:blank").unwrap()); @@ -3740,6 +3743,7 @@ impl Document { visibility_state: Cell::new(DocumentVisibilityState::Hidden), status_code, is_initial_about_blank: Cell::new(is_initial_about_blank), + allow_declarative_shadow_roots: Cell::new(allow_declarative_shadow_roots), inherited_insecure_requests_policy: Cell::new(inherited_insecure_requests_policy), intersection_observer_task_queued: Cell::new(false), } @@ -3874,6 +3878,7 @@ impl Document { status_code: Option, canceller: FetchCanceller, is_initial_about_blank: bool, + allow_declarative_shadow_roots: bool, inherited_insecure_requests_policy: Option, can_gc: CanGc, ) -> DomRoot { @@ -3893,6 +3898,7 @@ impl Document { status_code, canceller, is_initial_about_blank, + allow_declarative_shadow_roots, inherited_insecure_requests_policy, can_gc, ) @@ -3915,6 +3921,7 @@ impl Document { status_code: Option, canceller: FetchCanceller, is_initial_about_blank: bool, + allow_declarative_shadow_roots: bool, inherited_insecure_requests_policy: Option, can_gc: CanGc, ) -> DomRoot { @@ -3934,6 +3941,7 @@ impl Document { status_code, canceller, is_initial_about_blank, + allow_declarative_shadow_roots, inherited_insecure_requests_policy, )), window, @@ -4066,6 +4074,7 @@ impl Document { None, Default::default(), false, + self.allow_declarative_shadow_roots(), Some(self.insecure_requests_policy()), can_gc, ); @@ -4598,6 +4607,15 @@ impl Document { pub(crate) fn is_initial_about_blank(&self) -> bool { self.is_initial_about_blank.get() } + + /// + pub fn allow_declarative_shadow_roots(&self) -> bool { + self.allow_declarative_shadow_roots.get() + } + + pub fn set_allow_declarative_shadow_roots(&self, value: bool) { + self.allow_declarative_shadow_roots.set(value) + } } impl ProfilerMetadataFactory for Document { @@ -4636,6 +4654,7 @@ impl DocumentMethods for Document { None, Default::default(), false, + doc.allow_declarative_shadow_roots(), Some(doc.insecure_requests_policy()), can_gc, )) diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs index 8d455f8c00a..09916e9a4dc 100644 --- a/components/script/dom/domimplementation.rs +++ b/components/script/dom/domimplementation.rs @@ -174,6 +174,7 @@ impl DOMImplementationMethods for DOMImplementation { None, Default::default(), false, + self.document.allow_declarative_shadow_roots(), Some(self.document.insecure_requests_policy()), can_gc, ); diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs index 5945c77023d..42782420bda 100644 --- a/components/script/dom/domparser.rs +++ b/components/script/dom/domparser.rs @@ -88,6 +88,7 @@ impl DOMParserMethods for DOMParser { None, Default::default(), false, + false, Some(doc.insecure_requests_policy()), can_gc, ); @@ -111,6 +112,7 @@ impl DOMParserMethods for DOMParser { None, Default::default(), false, + false, Some(doc.insecure_requests_policy()), can_gc, ); diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 2b06da5b6ce..b85db3bd255 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -2076,7 +2076,7 @@ impl Element { ) -> Fallible> { // Steps 1-2. // TODO(#11995): XML case. - let new_children = ServoParser::parse_html_fragment(self, markup, can_gc); + let new_children = ServoParser::parse_html_fragment(self, markup, false, can_gc); // Step 3. // See https://github.com/w3c/DOM-Parsing/issues/61. let context_document = { @@ -2857,6 +2857,39 @@ impl ElementMethods for Element { self.client_rect(can_gc).size.height } + /// + fn SetHTMLUnsafe(&self, html: DOMString, can_gc: CanGc) { + // Step 2. Let target be this's template contents if this is a template element; otherwise this. + let target = if let Some(template) = self.downcast::() { + DomRoot::upcast(template.Content(can_gc)) + } else { + DomRoot::from_ref(self.upcast()) + }; + + // Step 3. Unsafely set HTML given target, this, and compliantHTML. + // Let newChildren be the result of the HTML fragment parsing algorithm. + let new_children = ServoParser::parse_html_fragment(self, html, true, can_gc); + + let context_document = { + if let Some(template) = self.downcast::() { + template.Content(can_gc).upcast::().owner_doc() + } else { + self.owner_document() + } + }; + + // Let fragment be a new DocumentFragment whose node document is contextElement's node document. + let frag = DocumentFragment::new(&context_document, can_gc); + + // For each node in newChildren, append node to fragment. + for child in new_children { + frag.upcast::().AppendChild(&child).unwrap(); + } + + // Replace all with fragment within target. + Node::replace_all(Some(frag.upcast()), &target); + } + /// fn GetInnerHTML(&self) -> Fallible { let qname = QualName::new( diff --git a/components/script/dom/htmltemplateelement.rs b/components/script/dom/htmltemplateelement.rs index 9a69c2c27f8..ef577504090 100644 --- a/components/script/dom/htmltemplateelement.rs +++ b/components/script/dom/htmltemplateelement.rs @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use dom_struct::dom_struct; -use html5ever::{LocalName, Prefix}; +use html5ever::{LocalName, Prefix, namespace_url}; use js::rust::HandleObject; use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; @@ -11,6 +11,7 @@ use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTem use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::root::{DomRoot, MutNullableDom}; +use crate::dom::bindings::str::DOMString; use crate::dom::document::Document; use crate::dom::documentfragment::DocumentFragment; use crate::dom::htmlelement::HTMLElement; @@ -58,9 +59,44 @@ impl HTMLTemplateElement { n.upcast::().set_weird_parser_insertion_mode(); n } + + pub(crate) fn set_contents(&self, document_fragment: Option<&DocumentFragment>) { + self.contents.set(document_fragment); + } } +#[allow(unused_doc_comments)] impl HTMLTemplateElementMethods for HTMLTemplateElement { + /// + make_enumerated_getter!( + ShadowRootMode, + "shadowrootmode", + "open" | "closed", + missing => "", + invalid => "" + ); + + /// + make_atomic_setter!(SetShadowRootMode, "shadowrootmode"); + + /// + make_bool_getter!(ShadowRootDelegatesFocus, "shadowrootdelegatesfocus"); + + /// + make_bool_setter!(SetShadowRootDelegatesFocus, "shadowrootdelegatesfocus"); + + /// + make_bool_getter!(ShadowRootClonable, "shadowrootclonable"); + + /// + make_bool_setter!(SetShadowRootClonable, "shadowrootclonable"); + + /// + make_bool_getter!(ShadowRootSerializable, "shadowrootserializable"); + + /// + make_bool_setter!(SetShadowRootSerializable, "shadowrootserializable"); + /// fn Content(&self, can_gc: CanGc) -> DomRoot { self.contents.or_init(|| { diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 6326b59f62d..ca1a1b21123 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -2637,6 +2637,7 @@ impl Node { document.status_code(), Default::default(), false, + document.allow_declarative_shadow_roots(), Some(document.insecure_requests_policy()), can_gc, ); diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index 16501234b66..64cff0ab71a 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -44,6 +44,9 @@ use crate::dom::bindings::codegen::Bindings::DocumentBinding::{ use crate::dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods; use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; +use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{ + ShadowRootMode, SlotAssignmentMode, +}; use crate::dom::bindings::inheritance::Castable; use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object}; @@ -53,6 +56,7 @@ use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::characterdata::CharacterData; use crate::dom::comment::Comment; use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument}; +use crate::dom::documentfragment::DocumentFragment; use crate::dom::documenttype::DocumentType; use crate::dom::element::{CustomElementCreationMode, Element, ElementCreator}; use crate::dom::htmlformelement::{FormControlElementHelpers, HTMLFormElement}; @@ -64,6 +68,7 @@ use crate::dom::node::{Node, ShadowIncluding}; use crate::dom::performanceentry::PerformanceEntry; use crate::dom::performancenavigationtiming::PerformanceNavigationTiming; use crate::dom::processinginstruction::ProcessingInstruction; +use crate::dom::shadowroot::IsUserAgentWidget; use crate::dom::text::Text; use crate::dom::virtualmethods::vtable_for; use crate::network_listener::PreInvoke; @@ -191,6 +196,7 @@ impl ServoParser { pub(crate) fn parse_html_fragment( context: &Element, input: DOMString, + allow_declarative_shadow_roots: bool, can_gc: CanGc, ) -> impl Iterator> + use<'_> { let context_node = context.upcast::(); @@ -218,6 +224,7 @@ impl ServoParser { None, Default::default(), false, + allow_declarative_shadow_roots, Some(context_document.insecure_requests_policy()), can_gc, ); @@ -1184,18 +1191,23 @@ impl TreeSink for Sink { &self, name: QualName, attrs: Vec, - _flags: ElementFlags, + flags: ElementFlags, ) -> Dom { let attrs = attrs .into_iter() .map(|attr| ElementAttribute::new(attr.name, DOMString::from(String::from(attr.value)))) .collect(); + let parsing_algorithm = if flags.template { + ParsingAlgorithm::Fragment + } else { + self.parsing_algorithm + }; let element = create_element_for_token( name, attrs, &self.document, ElementCreator::ParserCreated(self.current_line.get()), - self.parsing_algorithm, + parsing_algorithm, CanGc::note(), ); Dom::from_ref(element.upcast()) @@ -1381,6 +1393,91 @@ impl TreeSink for Sink { let node = DomRoot::from_ref(&**node); vtable_for(&node).pop(); } + + fn allow_declarative_shadow_roots(&self, intended_parent: &Dom) -> bool { + intended_parent.owner_doc().allow_declarative_shadow_roots() + } + + /// + /// A start tag whose tag name is "template" + /// Attach shadow path + fn attach_declarative_shadow( + &self, + host: &Dom, + template: &Dom, + attrs: Vec, + ) -> Result<(), String> { + let host_element = host.downcast::().unwrap(); + + if host_element.shadow_root().is_some() { + return Err(String::from("Already in a shadow host")); + } + + let template_element = template.downcast::().unwrap(); + + // Step 3. Let mode be template start tag's shadowrootmode attribute's value. + // Step 4. Let clonable be true if template start tag has a shadowrootclonable attribute; otherwise false. + // Step 5. Let delegatesfocus be true if template start tag + // has a shadowrootdelegatesfocus attribute; otherwise false. + // Step 6. Let serializable be true if template start tag + // has a shadowrootserializable attribute; otherwise false. + let mut shadow_root_mode = ShadowRootMode::Open; + let mut clonable = false; + let mut _delegatesfocus = false; + let mut _serializable = false; + + let attrs: Vec = attrs + .clone() + .into_iter() + .map(|attr| ElementAttribute::new(attr.name, DOMString::from(String::from(attr.value)))) + .collect(); + + attrs + .iter() + .for_each(|attr: &ElementAttribute| match attr.name.local { + local_name!("shadowrootmode") => { + if attr.value.str().eq_ignore_ascii_case("open") { + shadow_root_mode = ShadowRootMode::Open; + } else if attr.value.str().eq_ignore_ascii_case("closed") { + shadow_root_mode = ShadowRootMode::Closed; + } else { + unreachable!("shadowrootmode value is not open nor closed"); + } + }, + local_name!("shadowrootclonable") => { + clonable = true; + }, + local_name!("shadowrootdelegatesfocus") => { + _delegatesfocus = true; + }, + local_name!("shadowrootserializable") => { + _serializable = true; + }, + _ => {}, + }); + + // Step 8.1. Attach a shadow root with declarative shadow host element, + // mode, clonable, serializable, delegatesFocus, and "named". + match host_element.attach_shadow( + IsUserAgentWidget::No, + shadow_root_mode, + clonable, + SlotAssignmentMode::Manual, + CanGc::note(), + ) { + Ok(shadow_root) => { + // Step 8.3. Set shadow's declarative to true. + shadow_root.set_declarative(true); + + // Set 8.4. Set template's template contents property to shadow. + let shadow = shadow_root.upcast::(); + template_element.set_contents(Some(shadow)); + + Ok(()) + }, + Err(_) => Err(String::from("Attaching shadow fails")), + } + } } /// diff --git a/components/script/dom/shadowroot.rs b/components/script/dom/shadowroot.rs index 121f2e3de17..39383493873 100644 --- a/components/script/dom/shadowroot.rs +++ b/components/script/dom/shadowroot.rs @@ -79,6 +79,9 @@ pub(crate) struct ShadowRoot { slots: DomRefCell>>>, is_user_agent_widget: bool, + + /// + declarative: Cell, } impl ShadowRoot { @@ -113,6 +116,7 @@ impl ShadowRoot { available_to_element_internals: Cell::new(false), slots: Default::default(), is_user_agent_widget: is_user_agent_widget == IsUserAgentWidget::Yes, + declarative: Cell::new(false), } } @@ -276,6 +280,10 @@ impl ShadowRoot { pub(crate) fn is_user_agent_widget(&self) -> bool { self.is_user_agent_widget } + + pub(crate) fn set_declarative(&self, declarative: bool) { + self.declarative.set(declarative); + } } impl ShadowRootMethods for ShadowRoot { diff --git a/components/script/dom/xmldocument.rs b/components/script/dom/xmldocument.rs index fdf7d9f75f8..e438c7780b8 100644 --- a/components/script/dom/xmldocument.rs +++ b/components/script/dom/xmldocument.rs @@ -60,6 +60,7 @@ impl XMLDocument { None, Default::default(), false, + false, inherited_insecure_requests_policy, ), } diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 4cd7a3a3cd0..fca2eea4f58 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -1508,6 +1508,7 @@ impl XMLHttpRequest { None, Default::default(), false, + false, Some(doc.insecure_requests_policy()), can_gc, ) diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index d9655939e48..234183d1e08 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -3193,6 +3193,7 @@ impl ScriptThread { Some(metadata.status.raw_code()), incomplete.canceller, is_initial_about_blank, + true, incomplete.load_data.inherited_insecure_requests_policy, can_gc, ); diff --git a/components/script_bindings/codegen/Bindings.conf b/components/script_bindings/codegen/Bindings.conf index f33b0b13e6c..dfd281417f3 100644 --- a/components/script_bindings/codegen/Bindings.conf +++ b/components/script_bindings/codegen/Bindings.conf @@ -186,7 +186,7 @@ DOMInterfaces = { }, 'Element': { - 'canGc': ['SetInnerHTML', 'SetOuterHTML', 'InsertAdjacentHTML', 'GetClientRects', 'GetBoundingClientRect', 'InsertAdjacentText', 'ToggleAttribute', 'SetAttribute', 'SetAttributeNS', 'SetId','SetClassName','Prepend','Append','ReplaceChildren','Before','After','ReplaceWith', 'SetRole', 'SetAriaAtomic', 'SetAriaAutoComplete', 'SetAriaBrailleLabel', 'SetAriaBrailleRoleDescription', 'SetAriaBusy', 'SetAriaChecked', 'SetAriaColCount', 'SetAriaColIndex', 'SetAriaColIndexText', 'SetAriaColSpan', 'SetAriaCurrent', 'SetAriaDescription', 'SetAriaDisabled', 'SetAriaExpanded', 'SetAriaHasPopup', 'SetAriaHidden', 'SetAriaInvalid', 'SetAriaKeyShortcuts', 'SetAriaLabel', 'SetAriaLevel', 'SetAriaLive', 'SetAriaModal', 'SetAriaMultiLine', 'SetAriaMultiSelectable', 'SetAriaOrientation', 'SetAriaPlaceholder', 'SetAriaPosInSet', 'SetAriaPressed','SetAriaReadOnly', 'SetAriaRelevant', 'SetAriaRequired', 'SetAriaRoleDescription', 'SetAriaRowCount', 'SetAriaRowIndex', 'SetAriaRowIndexText', 'SetAriaRowSpan', 'SetAriaSelected', 'SetAriaSetSize','SetAriaSort', 'SetAriaValueMax', 'SetAriaValueMin', 'SetAriaValueNow', 'SetAriaValueText', 'SetScrollTop', 'SetScrollLeft', 'Scroll', 'Scroll_', 'ScrollBy', 'ScrollBy_', 'ScrollWidth', 'ScrollHeight', 'ScrollTop', 'ScrollLeft', 'ClientTop', 'ClientLeft', 'ClientWidth', 'ClientHeight', 'RequestFullscreen'], + 'canGc': ['SetHTMLUnsafe', 'SetInnerHTML', 'SetOuterHTML', 'InsertAdjacentHTML', 'GetClientRects', 'GetBoundingClientRect', 'InsertAdjacentText', 'ToggleAttribute', 'SetAttribute', 'SetAttributeNS', 'SetId','SetClassName','Prepend','Append','ReplaceChildren','Before','After','ReplaceWith', 'SetRole', 'SetAriaAtomic', 'SetAriaAutoComplete', 'SetAriaBrailleLabel', 'SetAriaBrailleRoleDescription', 'SetAriaBusy', 'SetAriaChecked', 'SetAriaColCount', 'SetAriaColIndex', 'SetAriaColIndexText', 'SetAriaColSpan', 'SetAriaCurrent', 'SetAriaDescription', 'SetAriaDisabled', 'SetAriaExpanded', 'SetAriaHasPopup', 'SetAriaHidden', 'SetAriaInvalid', 'SetAriaKeyShortcuts', 'SetAriaLabel', 'SetAriaLevel', 'SetAriaLive', 'SetAriaModal', 'SetAriaMultiLine', 'SetAriaMultiSelectable', 'SetAriaOrientation', 'SetAriaPlaceholder', 'SetAriaPosInSet', 'SetAriaPressed','SetAriaReadOnly', 'SetAriaRelevant', 'SetAriaRequired', 'SetAriaRoleDescription', 'SetAriaRowCount', 'SetAriaRowIndex', 'SetAriaRowIndexText', 'SetAriaRowSpan', 'SetAriaSelected', 'SetAriaSetSize','SetAriaSort', 'SetAriaValueMax', 'SetAriaValueMin', 'SetAriaValueNow', 'SetAriaValueText', 'SetScrollTop', 'SetScrollLeft', 'Scroll', 'Scroll_', 'ScrollBy', 'ScrollBy_', 'ScrollWidth', 'ScrollHeight', 'ScrollTop', 'ScrollLeft', 'ClientTop', 'ClientLeft', 'ClientWidth', 'ClientHeight', 'RequestFullscreen'], }, 'ElementInternals': { diff --git a/components/script_bindings/webidls/Element.webidl b/components/script_bindings/webidls/Element.webidl index 845728b110d..ba6d2d44204 100644 --- a/components/script_bindings/webidls/Element.webidl +++ b/components/script_bindings/webidls/Element.webidl @@ -122,6 +122,8 @@ partial interface Element { // https://w3c.github.io/DOM-Parsing/#extensions-to-the-element-interface partial interface Element { + [CEReactions] undefined setHTMLUnsafe(DOMString html); + [CEReactions, Throws] attribute [LegacyNullToEmptyString] DOMString innerHTML; [CEReactions, Throws] attribute [LegacyNullToEmptyString] DOMString outerHTML; }; diff --git a/components/script_bindings/webidls/HTMLTemplateElement.webidl b/components/script_bindings/webidls/HTMLTemplateElement.webidl index b71d37f4914..4db3283e1c5 100644 --- a/components/script_bindings/webidls/HTMLTemplateElement.webidl +++ b/components/script_bindings/webidls/HTMLTemplateElement.webidl @@ -8,4 +8,8 @@ interface HTMLTemplateElement : HTMLElement { [HTMLConstructor] constructor(); readonly attribute DocumentFragment content; + [CEReactions] attribute DOMString shadowRootMode; + [CEReactions] attribute boolean shadowRootDelegatesFocus; + [CEReactions] attribute boolean shadowRootClonable; + [CEReactions] attribute boolean shadowRootSerializable; }; diff --git a/tests/wpt/meta/css/css-mixins/function-shadow-container.html.ini b/tests/wpt/meta/css/css-mixins/function-shadow-container.html.ini deleted file mode 100644 index 251105dd6e0..00000000000 --- a/tests/wpt/meta/css/css-mixins/function-shadow-container.html.ini +++ /dev/null @@ -1,9 +0,0 @@ -[function-shadow-container.html] - [Can query named container in shadow] - expected: FAIL - - [::part() can not see inner named containers] - expected: FAIL - - [::slotted() can see inner named containers] - expected: FAIL diff --git a/tests/wpt/meta/css/css-mixins/function-shadow.html.ini b/tests/wpt/meta/css/css-mixins/function-shadow.html.ini deleted file mode 100644 index fe145697d0e..00000000000 --- a/tests/wpt/meta/css/css-mixins/function-shadow.html.ini +++ /dev/null @@ -1,33 +0,0 @@ -[function-shadow.html] - [@function works inside shadow] - expected: FAIL - - [Looking up document-global function] - expected: FAIL - - [@function works inside nested shadow] - expected: FAIL - - [@function defined in outer shadow is visible] - expected: FAIL - - [Combining functions from various scopes] - expected: FAIL - - [::part() can not see inner functions] - expected: FAIL - - [::slotted() can see inner functions] - expected: FAIL - - [:host can see inner functions] - expected: FAIL - - [Outer functions can't see inner functions] - expected: FAIL - - [Outer functions can't see inner functions (local vars)] - expected: FAIL - - [Function with same name in different scopes] - expected: FAIL diff --git a/tests/wpt/meta/css/selectors/invalidation/host-has-shadow-tree-element-at-nonsubject-position.html.ini b/tests/wpt/meta/css/selectors/invalidation/host-has-shadow-tree-element-at-nonsubject-position.html.ini index 5447455d504..422d56eeb97 100644 --- a/tests/wpt/meta/css/selectors/invalidation/host-has-shadow-tree-element-at-nonsubject-position.html.ini +++ b/tests/wpt/meta/css/selectors/invalidation/host-has-shadow-tree-element-at-nonsubject-position.html.ini @@ -1,2 +1,78 @@ [host-has-shadow-tree-element-at-nonsubject-position.html] - expected: ERROR + [Initial color] + expected: FAIL + + [Add .descendant to #shadow_child] + expected: FAIL + + [Remove .descendant from #shadow_child] + expected: FAIL + + [Add .descendant to #shadow_descendant] + expected: FAIL + + [Add .ancestor to #shadow_child:has(.descendant)] + expected: FAIL + + [Remove .ancestor from #shadow_child:has(.descendant)] + expected: FAIL + + [Add .child to #shadow_child:has(.descendant)] + expected: FAIL + + [Remove .child from #shadow_child:has(.descendant)] + expected: FAIL + + [Remove .descendant from #shadow_descendant] + expected: FAIL + + [Add .child to #shadow_child] + expected: FAIL + + [Add .grand_child to #shadow_descendant] + expected: FAIL + + [Add .host_context to #host] + expected: FAIL + + [Add .descendant to #shadow_descendant.grand_child] + expected: FAIL + + [Remove .descendant from #shadow_descendant.grand_child] + expected: FAIL + + [Remove .grand_child from #shadow_descendant] + expected: FAIL + + [Remove .child from #shadow_child] + expected: FAIL + + [Add .child to #shadow_descendant] + expected: FAIL + + [Remove .child from #shadow_descendant] + expected: FAIL + + [Insert #first_child.descendant to shadow root] + expected: FAIL + + [Remove #first_child.descendant from shadow root] + expected: FAIL + + [Insert #last_child.descendant to shadow root] + expected: FAIL + + [Remove #last_child.descendant from shadow root] + expected: FAIL + + [Insert #child_in_middle.descendant before #shadow_child] + expected: FAIL + + [Remove #child_in_middle.descendant from shadow root] + expected: FAIL + + [Insert #grand_child.descendant before #shadow_descendant] + expected: FAIL + + [Remove #grand_child.descendant from shadow tree] + expected: FAIL diff --git a/tests/wpt/meta/css/selectors/invalidation/host-has-shadow-tree-element-at-subject-position.html.ini b/tests/wpt/meta/css/selectors/invalidation/host-has-shadow-tree-element-at-subject-position.html.ini index d7a08061d8f..63a35c8fc5d 100644 --- a/tests/wpt/meta/css/selectors/invalidation/host-has-shadow-tree-element-at-subject-position.html.ini +++ b/tests/wpt/meta/css/selectors/invalidation/host-has-shadow-tree-element-at-subject-position.html.ini @@ -1,2 +1,48 @@ [host-has-shadow-tree-element-at-subject-position.html] - expected: ERROR + [Add .descendant to #shadow_child] + expected: FAIL + + [Add .descendant to #shadow_descendant] + expected: FAIL + + [Add .ancestor to #shadow_child:has(.descendant)] + expected: FAIL + + [Remove .ancestor from #shadow_child:has(.descendant)] + expected: FAIL + + [Add .child to #shadow_child:has(.descendant)] + expected: FAIL + + [Remove .child from #shadow_child:has(.descendant)] + expected: FAIL + + [Add .child to #shadow_child] + expected: FAIL + + [Add .grand_child to #shadow_descendant] + expected: FAIL + + [Add .host_context to #host] + expected: FAIL + + [Add .descendant to #shadow_descendant.grand_child] + expected: FAIL + + [Remove .descendant from #shadow_descendant.grand_child] + expected: FAIL + + [Remove .grand_child from #shadow_descendant] + expected: FAIL + + [Insert #first_child.descendant to shadow root] + expected: FAIL + + [Insert #last_child.descendant to shadow root] + expected: FAIL + + [Insert #child_in_middle.descendant before #shadow_child] + expected: FAIL + + [Insert #grand_child.descendant before #shadow_descendant] + expected: FAIL diff --git a/tests/wpt/meta/custom-elements/revamped-scoped-registry/Element-customElements-exceptions.tentative.html.ini b/tests/wpt/meta/custom-elements/revamped-scoped-registry/Element-customElements-exceptions.tentative.html.ini index 6aef765fdfa..cc6e13e2874 100644 --- a/tests/wpt/meta/custom-elements/revamped-scoped-registry/Element-customElements-exceptions.tentative.html.ini +++ b/tests/wpt/meta/custom-elements/revamped-scoped-registry/Element-customElements-exceptions.tentative.html.ini @@ -4,6 +4,3 @@ [customElements on a failed custom element created by setting innerHTML should return the associated scoped registry] expected: FAIL - - [customElements on a failed custom element created by parser should return the specified custom regsitry] - 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 0ee42474317..e30c6e3ca8c 100644 --- a/tests/wpt/meta/html/dom/idlharness.https.html.ini +++ b/tests/wpt/meta/html/dom/idlharness.https.html.ini @@ -4613,12 +4613,6 @@ [DOMStringList interface: calling contains(DOMString) on location.ancestorOrigins with too few arguments must throw TypeError] expected: FAIL - [Element interface: document.createElement("noscript") must inherit property "setHTMLUnsafe((TrustedHTML or DOMString))" with the proper type] - expected: FAIL - - [Element interface: calling setHTMLUnsafe((TrustedHTML or DOMString)) on document.createElement("noscript") with too few arguments must throw TypeError] - expected: FAIL - [Element interface: document.createElement("noscript") must inherit property "getHTML(optional GetHTMLOptions)" with the proper type] expected: FAIL @@ -5927,9 +5921,6 @@ [ShadowRoot interface: operation getHTML(optional GetHTMLOptions)] expected: FAIL - [Element interface: operation setHTMLUnsafe((TrustedHTML or DOMString))] - expected: FAIL - [Element interface: operation getHTML(optional GetHTMLOptions)] expected: FAIL @@ -5975,12 +5966,6 @@ [OffscreenCanvasRenderingContext2D interface: attribute lang] expected: FAIL - [Element interface: document.createElement("div") must inherit property "setHTMLUnsafe((TrustedHTML or DOMString))" with the proper type] - expected: FAIL - - [Element interface: calling setHTMLUnsafe((TrustedHTML or DOMString)) on document.createElement("div") with too few arguments must throw TypeError] - expected: FAIL - [Element interface: document.createElement("div") must inherit property "getHTML(optional GetHTMLOptions)" with the proper type] expected: FAIL @@ -7810,30 +7795,6 @@ [HTMLScriptElement interface: calling supports(DOMString) on document.createElement("script") with too few arguments must throw TypeError] expected: FAIL - [HTMLTemplateElement interface: attribute shadowRootMode] - expected: FAIL - - [HTMLTemplateElement interface: attribute shadowRootDelegatesFocus] - expected: FAIL - - [HTMLTemplateElement interface: attribute shadowRootClonable] - expected: FAIL - - [HTMLTemplateElement interface: attribute shadowRootSerializable] - expected: FAIL - - [HTMLTemplateElement interface: document.createElement("template") must inherit property "shadowRootMode" with the proper type] - expected: FAIL - - [HTMLTemplateElement interface: document.createElement("template") must inherit property "shadowRootDelegatesFocus" with the proper type] - expected: FAIL - - [HTMLTemplateElement interface: document.createElement("template") must inherit property "shadowRootClonable" with the proper type] - expected: FAIL - - [HTMLTemplateElement interface: document.createElement("template") must inherit property "shadowRootSerializable" with the proper type] - expected: FAIL - [HTMLMarqueeElement interface: existence and properties of interface object] expected: FAIL diff --git a/tests/wpt/meta/html/semantics/forms/the-form-element/form-indexed-element-shadow.html.ini b/tests/wpt/meta/html/semantics/forms/the-form-element/form-indexed-element-shadow.html.ini deleted file mode 100644 index 1dcebc9a5ff..00000000000 --- a/tests/wpt/meta/html/semantics/forms/the-form-element/form-indexed-element-shadow.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[form-indexed-element-shadow.html] - [form.elements: indexed access reflects DOM order, not flat tree] - expected: FAIL diff --git a/tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-img-src.tentative.html.ini b/tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-img-src.tentative.html.ini deleted file mode 100644 index 44bf28c68d5..00000000000 --- a/tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-img-src.tentative.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[template-shadowrootmode-img-src.tentative.html] - [Speculative parsing, page load: template-shadowrootmode-img-src] - expected: FAIL diff --git a/tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-link-stylesheet.tentative.html.ini b/tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-link-stylesheet.tentative.html.ini deleted file mode 100644 index 1f6a4e81ee4..00000000000 --- a/tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-link-stylesheet.tentative.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[template-shadowrootmode-link-stylesheet.tentative.html] - [Speculative parsing, page load: template-shadowrootmode-link-stylesheet] - expected: FAIL diff --git a/tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-script-src.tentative.html.ini b/tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-script-src.tentative.html.ini deleted file mode 100644 index 57838549b9d..00000000000 --- a/tests/wpt/meta/html/syntax/speculative-parsing/generated/page-load/template-shadowrootmode-script-src.tentative.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[template-shadowrootmode-script-src.tentative.html] - [Speculative parsing, page load: template-shadowrootmode-script-src] - expected: FAIL diff --git a/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/Element-setHTMLUnsafe-04.html.ini b/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/Element-setHTMLUnsafe-04.html.ini deleted file mode 100644 index 21cd15a9db1..00000000000 --- a/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/Element-setHTMLUnsafe-04.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[Element-setHTMLUnsafe-04.html] - [setHTMLUnsafe should leave the removed children alone.] - expected: FAIL diff --git a/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe-CEReactions.html.ini b/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe-CEReactions.html.ini index 179192d4826..d0b3986d561 100644 --- a/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe-CEReactions.html.ini +++ b/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe-CEReactions.html.ini @@ -1,6 +1,3 @@ [setHTMLUnsafe-CEReactions.html] - [Element.setHTMLUnsafe should trigger custom element reactions.] - expected: FAIL - [ShadowRoot.setHTMLUnsafe should trigger custom element reactions.] expected: FAIL diff --git a/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe-xml.html.ini b/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe-xml.html.ini deleted file mode 100644 index 8a4e2ea78e5..00000000000 --- a/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe-xml.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[setHTMLUnsafe-xml.html] - [setHTMLUnsafe should still parse HTML even in XML documents.] - expected: FAIL - - [setHTMLUnsafe should still parse HTML even in SVG documents.] - expected: FAIL diff --git a/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe.html.ini b/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe.html.ini index 0856c7132c2..850b529ff76 100644 --- a/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe.html.ini +++ b/tests/wpt/meta/html/webappapis/dynamic-markup-insertion/html-unsafe-methods/setHTMLUnsafe.html.ini @@ -1,15 +1,6 @@ [setHTMLUnsafe.html] - [Element: setHTMLUnsafe with no shadowdom.] - expected: FAIL - - [Element: setHTMLUnsafe with shadowdom.] - expected: FAIL - [ShadowRoot: setHTMLUnsafe with no shadowdom.] expected: FAIL [ShadowRoot: setHTMLUnsafe with shadowdom.] expected: FAIL - - [template.setHTMLUnsafe() should modify template content fragment rather than actual children.] - expected: FAIL diff --git a/tests/wpt/meta/selection/shadow-dom/cross-shadow-boundary-6.html.ini b/tests/wpt/meta/selection/shadow-dom/cross-shadow-boundary-6.html.ini deleted file mode 100644 index 7d43321b3c8..00000000000 --- a/tests/wpt/meta/selection/shadow-dom/cross-shadow-boundary-6.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[cross-shadow-boundary-6.html] - expected: TIMEOUT diff --git a/tests/wpt/meta/selection/shadow-dom/tentative/Range-isPointInRange.html.ini b/tests/wpt/meta/selection/shadow-dom/tentative/Range-isPointInRange.html.ini index d406bfaf706..ec035279471 100644 --- a/tests/wpt/meta/selection/shadow-dom/tentative/Range-isPointInRange.html.ini +++ b/tests/wpt/meta/selection/shadow-dom/tentative/Range-isPointInRange.html.ini @@ -1,6 +1,3 @@ [Range-isPointInRange.html] [isPointInRange() test for collapsed selection] expected: FAIL - - [isPointInRange() test for non-collapsed selection] - expected: FAIL diff --git a/tests/wpt/meta/selection/shadow-dom/tentative/Selection-getComposedRanges-range-update.html.ini b/tests/wpt/meta/selection/shadow-dom/tentative/Selection-getComposedRanges-range-update.html.ini index f08fa168226..842fc01b392 100644 --- a/tests/wpt/meta/selection/shadow-dom/tentative/Selection-getComposedRanges-range-update.html.ini +++ b/tests/wpt/meta/selection/shadow-dom/tentative/Selection-getComposedRanges-range-update.html.ini @@ -1,2 +1,9 @@ [Selection-getComposedRanges-range-update.html] - expected: ERROR + [modify getRangeAt() range.] + expected: FAIL + + [modify createRange() range added to selection after setEnd call.] + expected: FAIL + + [modify createRange() range added to selection before setStart/setEnd calls.] + expected: FAIL diff --git a/tests/wpt/meta/selection/shadow-dom/tentative/Selection-isCollapsed.html.ini b/tests/wpt/meta/selection/shadow-dom/tentative/Selection-isCollapsed.html.ini index 66003985326..33fa63b1b8f 100644 --- a/tests/wpt/meta/selection/shadow-dom/tentative/Selection-isCollapsed.html.ini +++ b/tests/wpt/meta/selection/shadow-dom/tentative/Selection-isCollapsed.html.ini @@ -1,2 +1,12 @@ [Selection-isCollapsed.html] - expected: ERROR + [Selection in light tree is not collapsed] + expected: FAIL + + [Selection in shadow tree is not collapsed] + expected: FAIL + + [Selection between light and shadow tree is not valid and is collapsed. Composed range is not collapsed] + expected: FAIL + + [Selection between two shadow trees is not valid and is collapsed. Composed range is not collapsed] + expected: FAIL diff --git a/tests/wpt/meta/shadow-dom/HighlightRegistry-highlightsFromPoint.html.ini b/tests/wpt/meta/shadow-dom/HighlightRegistry-highlightsFromPoint.html.ini index 22d63011dfb..8f2dbdcd1dd 100644 --- a/tests/wpt/meta/shadow-dom/HighlightRegistry-highlightsFromPoint.html.ini +++ b/tests/wpt/meta/shadow-dom/HighlightRegistry-highlightsFromPoint.html.ini @@ -1,7 +1,4 @@ [HighlightRegistry-highlightsFromPoint.html] - [CSS.highlights.highlightsFromPoint() should throw when called with nodes that are not ShadowRoot objects in options.] - expected: FAIL - [CSS.highlights.highlightsFromPoint() returns Highlights present at a given point inside a shadow tree in the right order.] expected: FAIL diff --git a/tests/wpt/meta/shadow-dom/declarative/declarative-shadow-dom-attachment.html.ini b/tests/wpt/meta/shadow-dom/declarative/declarative-shadow-dom-attachment.html.ini index 4a35ff289d7..99619c27f10 100644 --- a/tests/wpt/meta/shadow-dom/declarative/declarative-shadow-dom-attachment.html.ini +++ b/tests/wpt/meta/shadow-dom/declarative/declarative-shadow-dom-attachment.html.ini @@ -50,279 +50,6 @@ [Declarative Shadow DOM as a child of , with mode=open, delegatesFocus=false. Should be safelisted.] expected: FAIL - [Declarative Shadow DOM as a child of , with mode=open, delegatesFocus=false. Should be disallowed.] - expected: FAIL - - [Declarative Shadow DOM as a child of , with mode=open, delegatesFocus=false. Should be disallowed.] - expected: FAIL - - [Declarative Shadow DOM as a child of
, with mode=open, delegatesFocus=false. Should be disallowed.] - expected: FAIL - - [Declarative Shadow DOM as a child of , with mode=open, delegatesFocus=false. Should be disallowed.] - expected: FAIL - - [Declarative Shadow DOM as a child of