diff --git a/components/selectors/matching.rs b/components/selectors/matching.rs index 62cd7ee5448..252a1c11d10 100644 --- a/components/selectors/matching.rs +++ b/components/selectors/matching.rs @@ -532,8 +532,12 @@ fn matches_complex_selector_internal(mut selector_iter: SelectorIter { - (element.parent_element(), - SelectorMatchingResult::NotMatchedGlobally) + if element.blocks_ancestor_combinators() { + (None, SelectorMatchingResult::NotMatchedGlobally) + } else { + (element.parent_element(), + SelectorMatchingResult::NotMatchedGlobally) + } } Combinator::PseudoElement => { (element.pseudo_element_originating_element(), diff --git a/components/selectors/tree.rs b/components/selectors/tree.rs index 99c07c6bf3b..7827dc6bbe6 100644 --- a/components/selectors/tree.rs +++ b/components/selectors/tree.rs @@ -85,4 +85,11 @@ pub trait Element: Sized + Debug { /// Note: this can be false even if `.parent_element()` is `None` /// if the parent node is a `DocumentFragment`. fn is_root(&self) -> bool; + + /// Return true if we want to stop lookup ancestor of the current + /// element while matching complex selectors with descendant/child + /// combinator. + fn blocks_ancestor_combinators(&self) -> bool { + false + } } diff --git a/components/style/gecko/generated/structs_debug.rs b/components/style/gecko/generated/structs_debug.rs index 2d509a1da8a..3b905be39c0 100644 --- a/components/style/gecko/generated/structs_debug.rs +++ b/components/style/gecko/generated/structs_debug.rs @@ -10627,73 +10627,74 @@ pub mod root { mozIsHTML = 18, unresolved = 19, mozNativeAnonymous = 20, - mozSystemMetric = 21, - mozLocaleDir = 22, - mozLWTheme = 23, - mozLWThemeBrightText = 24, - mozLWThemeDarkText = 25, - mozWindowInactive = 26, - mozTableBorderNonzero = 27, - mozBrowserFrame = 28, - scope = 29, - negation = 30, - dir = 31, - link = 32, - mozAnyLink = 33, - anyLink = 34, - visited = 35, - active = 36, - checked = 37, - disabled = 38, - enabled = 39, - focus = 40, - focusWithin = 41, - hover = 42, - mozDragOver = 43, - target = 44, - indeterminate = 45, - mozDevtoolsHighlighted = 46, - mozStyleeditorTransitioning = 47, - fullscreen = 48, - mozFullScreen = 49, - mozFocusRing = 50, - mozBroken = 51, - mozLoading = 52, - mozUserDisabled = 53, - mozSuppressed = 54, - mozHandlerClickToPlay = 55, - mozHandlerVulnerableUpdatable = 56, - mozHandlerVulnerableNoUpdate = 57, - mozHandlerDisabled = 58, - mozHandlerBlocked = 59, - mozHandlerCrashed = 60, - mozMathIncrementScriptLevel = 61, - mozHasDirAttr = 62, - mozDirAttrLTR = 63, - mozDirAttrRTL = 64, - mozDirAttrLikeAuto = 65, - mozAutofill = 66, - mozAutofillPreview = 67, - required = 68, - optional = 69, - valid = 70, - invalid = 71, - inRange = 72, - outOfRange = 73, - defaultPseudo = 74, - placeholderShown = 75, - mozReadOnly = 76, - mozReadWrite = 77, - mozSubmitInvalid = 78, - mozUIInvalid = 79, - mozUIValid = 80, - mozMeterOptimum = 81, - mozMeterSubOptimum = 82, - mozMeterSubSubOptimum = 83, - mozPlaceholder = 84, - Count = 85, - NotPseudo = 86, - MAX = 87, + mozUseShadowTreeRoot = 21, + mozSystemMetric = 22, + mozLocaleDir = 23, + mozLWTheme = 24, + mozLWThemeBrightText = 25, + mozLWThemeDarkText = 26, + mozWindowInactive = 27, + mozTableBorderNonzero = 28, + mozBrowserFrame = 29, + scope = 30, + negation = 31, + dir = 32, + link = 33, + mozAnyLink = 34, + anyLink = 35, + visited = 36, + active = 37, + checked = 38, + disabled = 39, + enabled = 40, + focus = 41, + focusWithin = 42, + hover = 43, + mozDragOver = 44, + target = 45, + indeterminate = 46, + mozDevtoolsHighlighted = 47, + mozStyleeditorTransitioning = 48, + fullscreen = 49, + mozFullScreen = 50, + mozFocusRing = 51, + mozBroken = 52, + mozLoading = 53, + mozUserDisabled = 54, + mozSuppressed = 55, + mozHandlerClickToPlay = 56, + mozHandlerVulnerableUpdatable = 57, + mozHandlerVulnerableNoUpdate = 58, + mozHandlerDisabled = 59, + mozHandlerBlocked = 60, + mozHandlerCrashed = 61, + mozMathIncrementScriptLevel = 62, + mozHasDirAttr = 63, + mozDirAttrLTR = 64, + mozDirAttrRTL = 65, + mozDirAttrLikeAuto = 66, + mozAutofill = 67, + mozAutofillPreview = 68, + required = 69, + optional = 70, + valid = 71, + invalid = 72, + inRange = 73, + outOfRange = 74, + defaultPseudo = 75, + placeholderShown = 76, + mozReadOnly = 77, + mozReadWrite = 78, + mozSubmitInvalid = 79, + mozUIInvalid = 80, + mozUIValid = 81, + mozMeterOptimum = 82, + mozMeterSubOptimum = 83, + mozMeterSubSubOptimum = 84, + mozPlaceholder = 85, + Count = 86, + NotPseudo = 87, + MAX = 88, } #[repr(C)] #[derive(Debug)] diff --git a/components/style/gecko/generated/structs_release.rs b/components/style/gecko/generated/structs_release.rs index e026efef06a..0491f6d678c 100644 --- a/components/style/gecko/generated/structs_release.rs +++ b/components/style/gecko/generated/structs_release.rs @@ -10360,73 +10360,74 @@ pub mod root { mozIsHTML = 18, unresolved = 19, mozNativeAnonymous = 20, - mozSystemMetric = 21, - mozLocaleDir = 22, - mozLWTheme = 23, - mozLWThemeBrightText = 24, - mozLWThemeDarkText = 25, - mozWindowInactive = 26, - mozTableBorderNonzero = 27, - mozBrowserFrame = 28, - scope = 29, - negation = 30, - dir = 31, - link = 32, - mozAnyLink = 33, - anyLink = 34, - visited = 35, - active = 36, - checked = 37, - disabled = 38, - enabled = 39, - focus = 40, - focusWithin = 41, - hover = 42, - mozDragOver = 43, - target = 44, - indeterminate = 45, - mozDevtoolsHighlighted = 46, - mozStyleeditorTransitioning = 47, - fullscreen = 48, - mozFullScreen = 49, - mozFocusRing = 50, - mozBroken = 51, - mozLoading = 52, - mozUserDisabled = 53, - mozSuppressed = 54, - mozHandlerClickToPlay = 55, - mozHandlerVulnerableUpdatable = 56, - mozHandlerVulnerableNoUpdate = 57, - mozHandlerDisabled = 58, - mozHandlerBlocked = 59, - mozHandlerCrashed = 60, - mozMathIncrementScriptLevel = 61, - mozHasDirAttr = 62, - mozDirAttrLTR = 63, - mozDirAttrRTL = 64, - mozDirAttrLikeAuto = 65, - mozAutofill = 66, - mozAutofillPreview = 67, - required = 68, - optional = 69, - valid = 70, - invalid = 71, - inRange = 72, - outOfRange = 73, - defaultPseudo = 74, - placeholderShown = 75, - mozReadOnly = 76, - mozReadWrite = 77, - mozSubmitInvalid = 78, - mozUIInvalid = 79, - mozUIValid = 80, - mozMeterOptimum = 81, - mozMeterSubOptimum = 82, - mozMeterSubSubOptimum = 83, - mozPlaceholder = 84, - Count = 85, - NotPseudo = 86, - MAX = 87, + mozUseShadowTreeRoot = 21, + mozSystemMetric = 22, + mozLocaleDir = 23, + mozLWTheme = 24, + mozLWThemeBrightText = 25, + mozLWThemeDarkText = 26, + mozWindowInactive = 27, + mozTableBorderNonzero = 28, + mozBrowserFrame = 29, + scope = 30, + negation = 31, + dir = 32, + link = 33, + mozAnyLink = 34, + anyLink = 35, + visited = 36, + active = 37, + checked = 38, + disabled = 39, + enabled = 40, + focus = 41, + focusWithin = 42, + hover = 43, + mozDragOver = 44, + target = 45, + indeterminate = 46, + mozDevtoolsHighlighted = 47, + mozStyleeditorTransitioning = 48, + fullscreen = 49, + mozFullScreen = 50, + mozFocusRing = 51, + mozBroken = 52, + mozLoading = 53, + mozUserDisabled = 54, + mozSuppressed = 55, + mozHandlerClickToPlay = 56, + mozHandlerVulnerableUpdatable = 57, + mozHandlerVulnerableNoUpdate = 58, + mozHandlerDisabled = 59, + mozHandlerBlocked = 60, + mozHandlerCrashed = 61, + mozMathIncrementScriptLevel = 62, + mozHasDirAttr = 63, + mozDirAttrLTR = 64, + mozDirAttrRTL = 65, + mozDirAttrLikeAuto = 66, + mozAutofill = 67, + mozAutofillPreview = 68, + required = 69, + optional = 70, + valid = 71, + invalid = 72, + inRange = 73, + outOfRange = 74, + defaultPseudo = 75, + placeholderShown = 76, + mozReadOnly = 77, + mozReadWrite = 78, + mozSubmitInvalid = 79, + mozUIInvalid = 80, + mozUIValid = 81, + mozMeterOptimum = 82, + mozMeterSubOptimum = 83, + mozMeterSubSubOptimum = 84, + mozPlaceholder = 85, + Count = 86, + NotPseudo = 87, + MAX = 88, } #[repr(C)] #[derive(Debug)] diff --git a/components/style/gecko/non_ts_pseudo_class_list.rs b/components/style/gecko/non_ts_pseudo_class_list.rs index a6c3549bafa..8beb8c98493 100644 --- a/components/style/gecko/non_ts_pseudo_class_list.rs +++ b/components/style/gecko/non_ts_pseudo_class_list.rs @@ -111,6 +111,7 @@ macro_rules! apply_non_ts_list { ("-moz-last-node", MozLastNode, lastNode, _, _), ("-moz-only-whitespace", MozOnlyWhitespace, mozOnlyWhitespace, _, _), ("-moz-native-anonymous", MozNativeAnonymous, mozNativeAnonymous, _, PSEUDO_CLASS_INTERNAL), + ("-moz-use-shadow-tree-root", MozUseShadowTreeRoot, mozUseShadowTreeRoot, _, PSEUDO_CLASS_INTERNAL), ("-moz-is-html", MozIsHTML, mozIsHTML, _, _), ("-moz-placeholder", MozPlaceholder, mozPlaceholder, _, _), ], diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index e997486b1d3..424fa60dba3 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -1567,7 +1567,8 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { } NonTSPseudoClass::MozTableBorderNonzero | NonTSPseudoClass::MozBrowserFrame | - NonTSPseudoClass::MozNativeAnonymous => unsafe { + NonTSPseudoClass::MozNativeAnonymous | + NonTSPseudoClass::MozUseShadowTreeRoot => unsafe { Gecko_MatchesElement(pseudo_class.to_gecko_pseudoclasstype().unwrap(), self.0) }, NonTSPseudoClass::MozIsHTML => { @@ -1656,6 +1657,24 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { node_info.mInner.mNamespaceID == (structs::root::kNameSpaceID_XHTML as i32) && node.owner_doc().mType == structs::root::nsIDocument_Type::eHTML } + + fn blocks_ancestor_combinators(&self) -> bool { + use gecko_bindings::structs::NODE_IS_ANONYMOUS_ROOT; + if self.flags() & (NODE_IS_ANONYMOUS_ROOT as u32) == 0 { + return false + } + + match self.parent_element() { + Some(e) => { + // If this element is the shadow root of an use-element shadow + // tree, according to the spec, we should not match rules + // cross the shadow DOM boundary. + e.get_local_name().as_ptr() == atom!("use").as_ptr() && + e.get_namespace() == &*Namespace(atom!("http://www.w3.org/2000/svg")) + }, + None => false, + } + } } /// A few helpers to help with attribute selectors and snapshotting.