From d8b7195c751f417ec471dcf51244c6eebe33e010 Mon Sep 17 00:00:00 2001 From: Steven Novaryo <65610990+stevennovaryo@users.noreply.github.com> Date: Tue, 24 Dec 2024 11:36:57 +0800 Subject: [PATCH] Add check for valid custom element name in element::attach_shadow (#34749) * Add valid custom element name check Signed-off-by: stevennovaryo * Update wpt test expectation Signed-off-by: stevennovaryo --------- Signed-off-by: stevennovaryo --- .../script/dom/customelementregistry.rs | 3 +- components/script/dom/element.rs | 70 +++++++++++++------ .../selectors/invalidation/part-dir.html.ini | 6 +- .../selectors/invalidation/part-lang.html.ini | 6 +- .../ElementInternals-validation.html.ini | 3 - .../disabled-delegatesFocus.html.ini | 3 +- .../tentative/slotchange-events.html.ini | 1 - ...anslate-inherit-no-parent-element.html.ini | 6 -- ...owRoot-prototype-elementFromPoint.html.ini | 1 + ...rface-attachShadow-custom-element.html.ini | 9 --- ...seEvent-prototype-offsetX-offsetY.html.ini | 2 +- .../shadow-dom/innerHTML-setter.xhtml.ini | 6 +- .../slotchange-customelements.html.ini | 3 +- 13 files changed, 70 insertions(+), 49 deletions(-) delete mode 100644 tests/wpt/meta/html/dom/elements/global-attributes/translate-inherit-no-parent-element.html.ini diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs index c1e0c15a949..5e71738fb7d 100644 --- a/components/script/dom/customelementregistry.rs +++ b/components/script/dom/customelementregistry.rs @@ -1318,7 +1318,8 @@ fn is_potential_custom_element_char(c: char) -> bool { ('\u{37F}'..='\u{1FFF}').contains(&c) || ('\u{200C}'..='\u{200D}').contains(&c) || ('\u{203F}'..='\u{2040}').contains(&c) || - ('\u{2070}'..='\u{2FEF}').contains(&c) || + ('\u{2070}'..='\u{218F}').contains(&c) || + ('\u{2C00}'..='\u{2FEF}').contains(&c) || ('\u{3001}'..='\u{D7FF}').contains(&c) || ('\u{F900}'..='\u{FDCF}').contains(&c) || ('\u{FDF0}'..='\u{FFFD}').contains(&c) || diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 2bef3e3508f..b84e6739f9e 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -62,6 +62,7 @@ use xml5ever::serialize::TraversalScope::{ ChildrenOnly as XmlChildrenOnly, IncludeNode as XmlIncludeNode, }; +use super::customelementregistry::is_valid_custom_element_name; use super::htmltablecolelement::{HTMLTableColElement, HTMLTableColElementLayoutHelpers}; use crate::dom::activation::Activatable; use crate::dom::attr::{Attr, AttrHelpersForLayout}; @@ -511,35 +512,24 @@ impl Element { clonable: bool, ) -> Fallible> { // Step 1. + // If element’s namespace is not the HTML namespace, + // then throw a "NotSupportedError" DOMException. if self.namespace != ns!(html) { return Err(Error::NotSupported); } // Step 2. - match self.local_name() { - &local_name!("article") | - &local_name!("aside") | - &local_name!("blockquote") | - &local_name!("body") | - &local_name!("div") | - &local_name!("footer") | - &local_name!("h1") | - &local_name!("h2") | - &local_name!("h3") | - &local_name!("h4") | - &local_name!("h5") | - &local_name!("h6") | - &local_name!("header") | - &local_name!("main") | - &local_name!("nav") | - &local_name!("p") | - &local_name!("section") | - &local_name!("span") => {}, - &local_name!("video") | &local_name!("audio") - if is_ua_widget == IsUserAgentWidget::Yes => {}, - _ => return Err(Error::NotSupported), - }; + // If element’s local name is not a valid shadow host name, + // then throw a "NotSupportedError" DOMException. + if !is_valid_shadow_host_name(self.local_name()) { + match self.local_name() { + &local_name!("video") | &local_name!("audio") + if is_ua_widget == IsUserAgentWidget::Yes => {}, + _ => return Err(Error::NotSupported), + } + } + // TODO: Update the following steps to align with the newer spec. // Step 3. if self.is_shadow_host() { return Err(Error::InvalidState); @@ -614,6 +604,40 @@ impl Element { } } +/// +#[inline] +pub fn is_valid_shadow_host_name(name: &LocalName) -> bool { + // > A valid shadow host name is: + // > - a valid custom element name + if is_valid_custom_element_name(name) { + return true; + } + + // > - "article", "aside", "blockquote", "body", "div", "footer", "h1", "h2", "h3", + // > "h4", "h5", "h6", "header", "main", "nav", "p", "section", or "span" + matches!( + name, + &local_name!("article") | + &local_name!("aside") | + &local_name!("blockquote") | + &local_name!("body") | + &local_name!("div") | + &local_name!("footer") | + &local_name!("h1") | + &local_name!("h2") | + &local_name!("h3") | + &local_name!("h4") | + &local_name!("h5") | + &local_name!("h6") | + &local_name!("header") | + &local_name!("main") | + &local_name!("nav") | + &local_name!("p") | + &local_name!("section") | + &local_name!("span") + ) +} + #[inline] pub fn get_attr_for_layout<'dom>( elem: LayoutDom<'dom, Element>, diff --git a/tests/wpt/meta/css/selectors/invalidation/part-dir.html.ini b/tests/wpt/meta/css/selectors/invalidation/part-dir.html.ini index 282bbbc4feb..1a49bec1aaf 100644 --- a/tests/wpt/meta/css/selectors/invalidation/part-dir.html.ini +++ b/tests/wpt/meta/css/selectors/invalidation/part-dir.html.ini @@ -1,2 +1,6 @@ [part-dir.html] - expected: ERROR + [::part():dir() invalidation] + expected: FAIL + + [::part():dir() invalidation from setAttribute] + expected: FAIL diff --git a/tests/wpt/meta/css/selectors/invalidation/part-lang.html.ini b/tests/wpt/meta/css/selectors/invalidation/part-lang.html.ini index 397cee29510..43cf3f01230 100644 --- a/tests/wpt/meta/css/selectors/invalidation/part-lang.html.ini +++ b/tests/wpt/meta/css/selectors/invalidation/part-lang.html.ini @@ -1,2 +1,6 @@ [part-lang.html] - expected: ERROR + [::part():lang() invalidation] + expected: FAIL + + [::part():lang() invalidation from setAttribute] + expected: FAIL diff --git a/tests/wpt/meta/custom-elements/form-associated/ElementInternals-validation.html.ini b/tests/wpt/meta/custom-elements/form-associated/ElementInternals-validation.html.ini index f5db65164cf..fc8edf0cab7 100644 --- a/tests/wpt/meta/custom-elements/form-associated/ElementInternals-validation.html.ini +++ b/tests/wpt/meta/custom-elements/form-associated/ElementInternals-validation.html.ini @@ -1,6 +1,3 @@ [ElementInternals-validation.html] - ["anchor" argument of setValidity()] - expected: FAIL - [Custom control affects :valid :invalid for FORM and FIELDSET] expected: FAIL diff --git a/tests/wpt/meta/custom-elements/form-associated/disabled-delegatesFocus.html.ini b/tests/wpt/meta/custom-elements/form-associated/disabled-delegatesFocus.html.ini index 46943b32055..79baedc0b86 100644 --- a/tests/wpt/meta/custom-elements/form-associated/disabled-delegatesFocus.html.ini +++ b/tests/wpt/meta/custom-elements/form-associated/disabled-delegatesFocus.html.ini @@ -1,2 +1,3 @@ [disabled-delegatesFocus.html] - expected: ERROR + [Focus events fire on disabled form-associated custom elements with delegatesFocus] + expected: FAIL diff --git a/tests/wpt/meta/dom/nodes/moveBefore/tentative/slotchange-events.html.ini b/tests/wpt/meta/dom/nodes/moveBefore/tentative/slotchange-events.html.ini index 891a10d6042..a1c704d0690 100644 --- a/tests/wpt/meta/dom/nodes/moveBefore/tentative/slotchange-events.html.ini +++ b/tests/wpt/meta/dom/nodes/moveBefore/tentative/slotchange-events.html.ini @@ -1,5 +1,4 @@ [slotchange-events.html] - expected: ERROR [Moving default content into a slot fires 'slotchange' event] expected: FAIL diff --git a/tests/wpt/meta/html/dom/elements/global-attributes/translate-inherit-no-parent-element.html.ini b/tests/wpt/meta/html/dom/elements/global-attributes/translate-inherit-no-parent-element.html.ini deleted file mode 100644 index 42f3ddcbbbd..00000000000 --- a/tests/wpt/meta/html/dom/elements/global-attributes/translate-inherit-no-parent-element.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[translate-inherit-no-parent-element.html] - [ShadowRoot parent node whose shadow host has translate=yes] - expected: FAIL - - [ShadowRoot parent node whose shadow host has translate=no] - expected: FAIL diff --git a/tests/wpt/meta/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html.ini b/tests/wpt/meta/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html.ini index 6768ee2f80c..400218db28a 100644 --- a/tests/wpt/meta/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html.ini +++ b/tests/wpt/meta/shadow-dom/DocumentOrShadowRoot-prototype-elementFromPoint.html.ini @@ -1,4 +1,5 @@ [DocumentOrShadowRoot-prototype-elementFromPoint.html] + expected: CRASH [document.elementFromPoint and shadow.ElementFromPoint must return the shadow host of the hit-tested text node when the hit-tested text node is a direct child of the root and the host has display: inline] expected: FAIL diff --git a/tests/wpt/meta/shadow-dom/Element-interface-attachShadow-custom-element.html.ini b/tests/wpt/meta/shadow-dom/Element-interface-attachShadow-custom-element.html.ini index 6fe5d3fea55..aa68710fb42 100644 --- a/tests/wpt/meta/shadow-dom/Element-interface-attachShadow-custom-element.html.ini +++ b/tests/wpt/meta/shadow-dom/Element-interface-attachShadow-custom-element.html.ini @@ -1,15 +1,6 @@ [Element-interface-attachShadow-custom-element.html] - [Element.attachShadow must create an instance of ShadowRoot for autonomous custom elements] - expected: FAIL - - [Element.attachShadow must create an instance of ShadowRoot for undefined autonomous custom elements] - expected: FAIL - [Element.attachShadow for an autonomous custom element with disabledFeatures=["shadow"\] should throw a NotSupportedError] expected: FAIL [Element.attachShadow for a customized built-in element with disabledFeatures=["shadow"\] should throw a NotSupportedError] expected: FAIL - - [Element.attachShadow for a custom element with disabledFeatures=["SHADOW"\] should not throw a NotSupportedError] - expected: FAIL diff --git a/tests/wpt/meta/shadow-dom/MouseEvent-prototype-offsetX-offsetY.html.ini b/tests/wpt/meta/shadow-dom/MouseEvent-prototype-offsetX-offsetY.html.ini index 5a34f035218..4b44502efa0 100644 --- a/tests/wpt/meta/shadow-dom/MouseEvent-prototype-offsetX-offsetY.html.ini +++ b/tests/wpt/meta/shadow-dom/MouseEvent-prototype-offsetX-offsetY.html.ini @@ -1,4 +1,4 @@ [MouseEvent-prototype-offsetX-offsetY.html] - expected: ERROR + expected: CRASH [MouseEvent's offsetX and offsetY attributes must be relative to the target.] expected: FAIL diff --git a/tests/wpt/meta/shadow-dom/innerHTML-setter.xhtml.ini b/tests/wpt/meta/shadow-dom/innerHTML-setter.xhtml.ini index 0fd47ee26c4..8d763a2f0f1 100644 --- a/tests/wpt/meta/shadow-dom/innerHTML-setter.xhtml.ini +++ b/tests/wpt/meta/shadow-dom/innerHTML-setter.xhtml.ini @@ -1,2 +1,6 @@ [innerHTML-setter.xhtml] - expected: ERROR + [InnerHTML behavior on custom element in default 'foo' namespace] + expected: FAIL + + [InnerHTML behavior with prefixes on custom element] + expected: FAIL diff --git a/tests/wpt/meta/shadow-dom/slotchange-customelements.html.ini b/tests/wpt/meta/shadow-dom/slotchange-customelements.html.ini index 501acdec58b..830cdaa2cac 100644 --- a/tests/wpt/meta/shadow-dom/slotchange-customelements.html.ini +++ b/tests/wpt/meta/shadow-dom/slotchange-customelements.html.ini @@ -1,2 +1,3 @@ [slotchange-customelements.html] - expected: ERROR + [slotchange must fire on initialization of custom elements with slotted children] + expected: FAIL