зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 8c89fd37b79d (bug 1544242) for failures in browser_rules_shadowdom_slot_rules.js CLOSED TREE
This commit is contained in:
Родитель
7fa6125c63
Коммит
f1ef21cbc7
|
@ -2516,8 +2516,9 @@ static void UpdateBackdropIfNeeded(nsIFrame* aFrame, ServoStyleSet& aStyleSet,
|
|||
PseudoStyleType::backdrop);
|
||||
|
||||
RefPtr<ComputedStyle> newStyle = aStyleSet.ResolvePseudoElementStyle(
|
||||
*aFrame->GetContent()->AsElement(), PseudoStyleType::backdrop,
|
||||
aFrame->Style());
|
||||
aFrame->GetContent()->AsElement(), PseudoStyleType::backdrop,
|
||||
aFrame->Style(),
|
||||
/* aPseudoElement = */ nullptr);
|
||||
|
||||
// NOTE(emilio): We can't use the changes handled for the owner of the
|
||||
// backdrop frame, since it's out of flow, and parented to the viewport or
|
||||
|
@ -2560,7 +2561,8 @@ static void UpdateOneAdditionalComputedStyle(nsIFrame* aFrame, uint32_t aIndex,
|
|||
|
||||
RefPtr<ComputedStyle> newStyle =
|
||||
aRestyleState.StyleSet().ResolvePseudoElementStyle(
|
||||
*aFrame->GetContent()->AsElement(), pseudoType, aFrame->Style());
|
||||
aFrame->GetContent()->AsElement(), pseudoType, aFrame->Style(),
|
||||
/* aPseudoElement = */ nullptr);
|
||||
|
||||
uint32_t equalStructs; // Not used, actually.
|
||||
nsChangeHint childHint =
|
||||
|
@ -2757,8 +2759,8 @@ bool RestyleManager::ProcessPostTraversal(Element* aElement,
|
|||
styleFrame->IsBlockFrameOrSubclass() &&
|
||||
!nsLayoutUtils::GetMarkerPseudo(aElement)) {
|
||||
RefPtr<ComputedStyle> pseudoStyle =
|
||||
aRestyleState.StyleSet().ProbeMarkerPseudoStyle(*aElement,
|
||||
*upToDateStyleIfRestyled);
|
||||
aRestyleState.StyleSet().ProbePseudoElementStyle(
|
||||
*aElement, PseudoStyleType::marker, upToDateStyleIfRestyled);
|
||||
if (pseudoStyle) {
|
||||
changeHint |= nsChangeHint_ReconstructFrame;
|
||||
}
|
||||
|
|
|
@ -1160,8 +1160,9 @@ void nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent,
|
|||
|
||||
RefPtr<ComputedStyle> style =
|
||||
mPresShell->StyleSet()->ResolvePseudoElementStyle(
|
||||
*aContent->AsElement(), PseudoStyleType::backdrop,
|
||||
/* aParentStyle */ nullptr);
|
||||
aContent->AsElement(), PseudoStyleType::backdrop,
|
||||
/* aParentComputedStyle */ nullptr,
|
||||
/* aPseudoElement */ nullptr);
|
||||
MOZ_ASSERT(style->StyleDisplay()->mTopLayer == NS_STYLE_TOP_LAYER_TOP);
|
||||
nsContainerFrame* parentFrame =
|
||||
GetGeometricParent(*style->StyleDisplay(), nullptr);
|
||||
|
@ -1702,27 +1703,24 @@ void nsCSSFrameConstructor::CreateGeneratedContentItem(
|
|||
ServoStyleSet* styleSet = mPresShell->StyleSet();
|
||||
|
||||
// Probe for the existence of the pseudo-element
|
||||
RefPtr<ComputedStyle> pseudoStyle;
|
||||
RefPtr<ComputedStyle> pseudoStyle = styleSet->ProbePseudoElementStyle(
|
||||
aOriginatingElement, aPseudoElement, &aStyle);
|
||||
if (!pseudoStyle) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAtom* elemName = nullptr;
|
||||
nsAtom* property = nullptr;
|
||||
switch (aPseudoElement) {
|
||||
case PseudoStyleType::before:
|
||||
pseudoStyle = styleSet->ProbePseudoElementStyle(aOriginatingElement,
|
||||
aPseudoElement, &aStyle);
|
||||
elemName = nsGkAtoms::mozgeneratedcontentbefore;
|
||||
property = nsGkAtoms::beforePseudoProperty;
|
||||
break;
|
||||
case PseudoStyleType::after:
|
||||
pseudoStyle = styleSet->ProbePseudoElementStyle(aOriginatingElement,
|
||||
aPseudoElement, &aStyle);
|
||||
elemName = nsGkAtoms::mozgeneratedcontentafter;
|
||||
property = nsGkAtoms::afterPseudoProperty;
|
||||
break;
|
||||
case PseudoStyleType::marker:
|
||||
// We want to get a marker style even if we match no rules, but we still
|
||||
// want to check the result of GeneratedContentPseudoExists.
|
||||
pseudoStyle = styleSet->ProbeMarkerPseudoStyle(aOriginatingElement,
|
||||
aStyle);
|
||||
elemName = nsGkAtoms::mozgeneratedcontentmarker;
|
||||
property = nsGkAtoms::markerPseudoProperty;
|
||||
break;
|
||||
|
@ -1730,10 +1728,6 @@ void nsCSSFrameConstructor::CreateGeneratedContentItem(
|
|||
MOZ_ASSERT_UNREACHABLE("unexpected aPseudoElement");
|
||||
}
|
||||
|
||||
if (!pseudoStyle) {
|
||||
return;
|
||||
}
|
||||
|
||||
// |ProbePseudoStyleFor| checked the 'display' property and the
|
||||
// |ContentCount()| of the 'content' property for us.
|
||||
RefPtr<NodeInfo> nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(
|
||||
|
@ -8718,7 +8712,8 @@ already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLetterStyle(
|
|||
nsIContent* aContent, ComputedStyle* aComputedStyle) {
|
||||
if (aContent) {
|
||||
return mPresShell->StyleSet()->ResolvePseudoElementStyle(
|
||||
*aContent->AsElement(), PseudoStyleType::firstLetter, aComputedStyle);
|
||||
aContent->AsElement(), PseudoStyleType::firstLetter, aComputedStyle,
|
||||
nullptr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -8727,7 +8722,8 @@ already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLineStyle(
|
|||
nsIContent* aContent, ComputedStyle* aComputedStyle) {
|
||||
if (aContent) {
|
||||
return mPresShell->StyleSet()->ResolvePseudoElementStyle(
|
||||
*aContent->AsElement(), PseudoStyleType::firstLine, aComputedStyle);
|
||||
aContent->AsElement(), PseudoStyleType::firstLine, aComputedStyle,
|
||||
nullptr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -500,12 +500,13 @@ ImgDrawResult nsButtonFrameRenderer::PaintBorder(nsDisplayListBuilder* aBuilder,
|
|||
*/
|
||||
void nsButtonFrameRenderer::ReResolveStyles(nsPresContext* aPresContext) {
|
||||
// get all the styles
|
||||
ComputedStyle* context = mFrame->Style();
|
||||
ServoStyleSet* styleSet = aPresContext->StyleSet();
|
||||
|
||||
// get styles assigned to -moz-focus-inner (ie dotted border on Windows)
|
||||
mInnerFocusStyle = styleSet->ProbePseudoElementStyle(
|
||||
*mFrame->GetContent()->AsElement(), PseudoStyleType::mozFocusInner,
|
||||
mFrame->Style());
|
||||
context);
|
||||
}
|
||||
|
||||
ComputedStyle* nsButtonFrameRenderer::GetComputedStyle(int32_t aIndex) const {
|
||||
|
|
|
@ -5465,7 +5465,8 @@ void nsBlockFrame::UpdateFirstLetterStyle(ServoRestyleState& aRestyleState) {
|
|||
ComputedStyle* parentStyle = styleParent->Style();
|
||||
RefPtr<ComputedStyle> firstLetterStyle =
|
||||
aRestyleState.StyleSet().ResolvePseudoElementStyle(
|
||||
*mContent->AsElement(), PseudoStyleType::firstLetter, parentStyle);
|
||||
mContent->AsElement(), PseudoStyleType::firstLetter, parentStyle,
|
||||
nullptr);
|
||||
// Note that we don't need to worry about changehints for the continuation
|
||||
// styles: those will be handled by the styleParent already.
|
||||
RefPtr<ComputedStyle> continuationStyle =
|
||||
|
@ -7187,7 +7188,8 @@ void nsBlockFrame::UpdatePseudoElementStyles(ServoRestyleState& aRestyleState) {
|
|||
ComputedStyle* parentStyle = styleParent->Style();
|
||||
RefPtr<ComputedStyle> firstLineStyle =
|
||||
aRestyleState.StyleSet().ResolvePseudoElementStyle(
|
||||
*mContent->AsElement(), PseudoStyleType::firstLine, parentStyle);
|
||||
mContent->AsElement(), PseudoStyleType::firstLine, parentStyle,
|
||||
nullptr);
|
||||
|
||||
// FIXME(bz): Can we make first-line continuations be non-inheriting anon
|
||||
// boxes?
|
||||
|
|
|
@ -98,7 +98,7 @@ void nsMathMLFrame::ResolveMathMLCharStyle(nsPresContext* aPresContext,
|
|||
PseudoStyleType pseudoType = PseudoStyleType::mozMathAnonymous; // savings
|
||||
RefPtr<ComputedStyle> newComputedStyle;
|
||||
newComputedStyle = aPresContext->StyleSet()->ResolvePseudoElementStyle(
|
||||
*aContent->AsElement(), pseudoType, aParentComputedStyle);
|
||||
aContent->AsElement(), pseudoType, aParentComputedStyle, nullptr);
|
||||
|
||||
aMathMLChar->SetComputedStyle(newComputedStyle);
|
||||
}
|
||||
|
|
|
@ -374,6 +374,8 @@ Maybe<StyleStructID> ComputedStyle::LookupStruct(const nsACString& aName) {
|
|||
ComputedStyle* ComputedStyle::GetCachedLazyPseudoStyle(
|
||||
PseudoStyleType aPseudo) const {
|
||||
MOZ_ASSERT(PseudoStyle::IsPseudoElement(aPseudo));
|
||||
MOZ_ASSERT(!IsLazilyCascadedPseudoElement(),
|
||||
"Lazy pseudos can't inherit lazy pseudos");
|
||||
|
||||
if (nsCSSPseudoElements::PseudoElementSupportsUserActionState(aPseudo)) {
|
||||
return nullptr;
|
||||
|
|
|
@ -194,6 +194,8 @@ class ComputedStyle {
|
|||
void SetCachedLazyPseudoStyle(ComputedStyle* aStyle) {
|
||||
MOZ_ASSERT(aStyle->IsPseudoElement());
|
||||
MOZ_ASSERT(!GetCachedLazyPseudoStyle(aStyle->GetPseudoType()));
|
||||
MOZ_ASSERT(!IsLazilyCascadedPseudoElement(),
|
||||
"lazy pseudos can't inherit lazy pseudos");
|
||||
MOZ_ASSERT(aStyle->IsLazilyCascadedPseudoElement());
|
||||
|
||||
// Since we're caching lazy pseudo styles on the ComputedValues of the
|
||||
|
|
|
@ -440,55 +440,38 @@ static inline bool LazyPseudoIsCacheable(PseudoStyleType aType,
|
|||
}
|
||||
|
||||
already_AddRefed<ComputedStyle> ServoStyleSet::ResolvePseudoElementStyle(
|
||||
const Element& aOriginatingElement, PseudoStyleType aType,
|
||||
ComputedStyle* aParentStyle, IsProbe aIsProbe) {
|
||||
Element* aOriginatingElement, PseudoStyleType aType,
|
||||
ComputedStyle* aParentStyle, Element* aPseudoElement) {
|
||||
// Runs from frame construction, this should have clean styles already, except
|
||||
// with non-lazy FC...
|
||||
UpdateStylistIfNeeded();
|
||||
MOZ_ASSERT(PseudoStyle::IsPseudoElement(aType));
|
||||
|
||||
const bool cacheable =
|
||||
LazyPseudoIsCacheable(aType, aOriginatingElement, aParentStyle);
|
||||
RefPtr<ComputedStyle> style =
|
||||
cacheable ? aParentStyle->GetCachedLazyPseudoStyle(aType) : nullptr;
|
||||
RefPtr<ComputedStyle> computedValues;
|
||||
|
||||
const bool isProbe = aIsProbe == IsProbe::Yes;
|
||||
if (aPseudoElement) {
|
||||
MOZ_ASSERT(aType == aPseudoElement->GetPseudoElementType());
|
||||
computedValues =
|
||||
Servo_ResolveStyle(aPseudoElement, mRawSet.get()).Consume();
|
||||
} else {
|
||||
bool cacheable =
|
||||
LazyPseudoIsCacheable(aType, *aOriginatingElement, aParentStyle);
|
||||
computedValues =
|
||||
cacheable ? aParentStyle->GetCachedLazyPseudoStyle(aType) : nullptr;
|
||||
|
||||
if (!style) {
|
||||
// FIXME(emilio): Why passing null for probing as the parent style?
|
||||
//
|
||||
// There are callers which do pass the wrong parent style and it would
|
||||
// assert (like ComputeSelectionStyle()). That's messy!
|
||||
style = Servo_ResolvePseudoStyle(&aOriginatingElement, aType, isProbe,
|
||||
isProbe ? nullptr : aParentStyle,
|
||||
mRawSet.get())
|
||||
.Consume();
|
||||
if (!style) {
|
||||
MOZ_ASSERT(isProbe);
|
||||
return nullptr;
|
||||
}
|
||||
if (cacheable) {
|
||||
aParentStyle->SetCachedLazyPseudoStyle(style);
|
||||
if (!computedValues) {
|
||||
computedValues = Servo_ResolvePseudoStyle(aOriginatingElement, aType,
|
||||
/* is_probe = */ false,
|
||||
aParentStyle, mRawSet.get())
|
||||
.Consume();
|
||||
if (cacheable) {
|
||||
aParentStyle->SetCachedLazyPseudoStyle(computedValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(style);
|
||||
|
||||
if (isProbe && !GeneratedContentPseudoExists(*aParentStyle, *style)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return style.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ComputedStyle> ServoStyleSet::ProbeMarkerPseudoStyle(
|
||||
const dom::Element& aOriginatingElement, ComputedStyle& aParentStyle) {
|
||||
RefPtr<ComputedStyle> markerStyle = ResolvePseudoElementStyle(
|
||||
aOriginatingElement, PseudoStyleType::marker, &aParentStyle);
|
||||
if (!GeneratedContentPseudoExists(aParentStyle, *markerStyle)) {
|
||||
return nullptr;
|
||||
}
|
||||
return markerStyle.forget();
|
||||
MOZ_ASSERT(computedValues);
|
||||
return computedValues.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ComputedStyle>
|
||||
|
@ -674,35 +657,66 @@ void ServoStyleSet::AddDocStyleSheet(StyleSheet* aSheet) {
|
|||
}
|
||||
}
|
||||
|
||||
bool ServoStyleSet::GeneratedContentPseudoExists(
|
||||
const ComputedStyle& aParentStyle, const ComputedStyle& aPseudoStyle) {
|
||||
auto type = aPseudoStyle.GetPseudoType();
|
||||
MOZ_ASSERT(type != PseudoStyleType::NotPseudo);
|
||||
already_AddRefed<ComputedStyle> ServoStyleSet::ProbePseudoElementStyle(
|
||||
const Element& aOriginatingElement, PseudoStyleType aType,
|
||||
ComputedStyle* aParentStyle) {
|
||||
// Runs from frame construction, this should have clean styles already, except
|
||||
// with non-lazy FC...
|
||||
UpdateStylistIfNeeded();
|
||||
|
||||
if (type == PseudoStyleType::marker) {
|
||||
// NB: We ignore aParentStyle, because in some cases
|
||||
// (first-line/first-letter on anonymous box blocks) Gecko passes something
|
||||
// nonsensical there. In all other cases we want to inherit directly from
|
||||
// aOriginatingElement's styles anyway.
|
||||
MOZ_ASSERT(PseudoStyle::IsPseudoElement(aType));
|
||||
|
||||
bool cacheable =
|
||||
LazyPseudoIsCacheable(aType, aOriginatingElement, aParentStyle);
|
||||
|
||||
RefPtr<ComputedStyle> computedValues =
|
||||
cacheable ? aParentStyle->GetCachedLazyPseudoStyle(aType) : nullptr;
|
||||
if (!computedValues) {
|
||||
computedValues =
|
||||
Servo_ResolvePseudoStyle(&aOriginatingElement, aType,
|
||||
/* is_probe = */ true, nullptr, mRawSet.get())
|
||||
.Consume();
|
||||
if (!computedValues) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (cacheable) {
|
||||
// NB: We don't need to worry about the before/after handling below
|
||||
// because those are eager and thus not |cacheable| anyway.
|
||||
aParentStyle->SetCachedLazyPseudoStyle(computedValues);
|
||||
}
|
||||
}
|
||||
|
||||
if (aType == PseudoStyleType::marker) {
|
||||
// ::marker only exist for list items (for now).
|
||||
if (aParentStyle.StyleDisplay()->mDisplay != StyleDisplay::ListItem) {
|
||||
return false;
|
||||
if (aParentStyle->StyleDisplay()->mDisplay != StyleDisplay::ListItem) {
|
||||
return nullptr;
|
||||
}
|
||||
// display:none is equivalent to not having the pseudo-element at all.
|
||||
if (aPseudoStyle.StyleDisplay()->mDisplay == StyleDisplay::None) {
|
||||
return false;
|
||||
if (computedValues->StyleDisplay()->mDisplay == StyleDisplay::None) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// For :before and :after pseudo-elements, having display: none or no
|
||||
// 'content' property is equivalent to not having the pseudo-element
|
||||
// at all.
|
||||
if (type == PseudoStyleType::before || type == PseudoStyleType::after) {
|
||||
if (aPseudoStyle.StyleDisplay()->mDisplay == StyleDisplay::None) {
|
||||
return false;
|
||||
}
|
||||
if (!aPseudoStyle.StyleContent()->ContentCount()) {
|
||||
return false;
|
||||
bool isBeforeOrAfter =
|
||||
aType == PseudoStyleType::before || aType == PseudoStyleType::after;
|
||||
if (isBeforeOrAfter) {
|
||||
const nsStyleDisplay* display = computedValues->StyleDisplay();
|
||||
const nsStyleContent* content = computedValues->StyleContent();
|
||||
if (display->mDisplay == StyleDisplay::None ||
|
||||
content->ContentCount() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return computedValues.forget();
|
||||
}
|
||||
|
||||
bool ServoStyleSet::StyleDocument(ServoTraversalFlags aFlags) {
|
||||
|
|
|
@ -168,36 +168,14 @@ class ServoStyleSet {
|
|||
// matching for them is a first step.)
|
||||
already_AddRefed<ComputedStyle> ResolveStyleForPlaceholder();
|
||||
|
||||
// Returns whether a given pseudo-element should exist or not.
|
||||
static bool GeneratedContentPseudoExists(const ComputedStyle& aParentStyle,
|
||||
const ComputedStyle& aPseudoStyle);
|
||||
|
||||
enum class IsProbe {
|
||||
No,
|
||||
Yes,
|
||||
};
|
||||
|
||||
// Get a style for a pseudo-element.
|
||||
//
|
||||
// If IsProbe is Yes, then no style is returned if there are no rules matching
|
||||
// for the pseudo-element, or GeneratedContentPseudoExists returns false.
|
||||
//
|
||||
// If IsProbe is No, then the style is guaranteed to be non-null.
|
||||
// Get a ComputedStyle for a pseudo-element. aParentElement must be
|
||||
// non-null. aPseudoID is the PseudoStyleType for the
|
||||
// pseudo-element. aPseudoElement must be non-null if the pseudo-element
|
||||
// type is one that allows user action pseudo-classes after it or allows
|
||||
// style attributes; otherwise, it is ignored.
|
||||
already_AddRefed<ComputedStyle> ResolvePseudoElementStyle(
|
||||
const dom::Element& aOriginatingElement, PseudoStyleType,
|
||||
ComputedStyle* aParentStyle, IsProbe = IsProbe::No);
|
||||
|
||||
already_AddRefed<ComputedStyle> ProbePseudoElementStyle(
|
||||
const dom::Element& aOriginatingElement, PseudoStyleType aType,
|
||||
ComputedStyle* aParentStyle) {
|
||||
return ResolvePseudoElementStyle(aOriginatingElement, aType, aParentStyle,
|
||||
IsProbe::Yes);
|
||||
}
|
||||
|
||||
// A special one for ::marker since we don want to get a style if no rules
|
||||
// match, but we want to also check GeneratedContentPseudoExists.
|
||||
already_AddRefed<ComputedStyle> ProbeMarkerPseudoStyle(
|
||||
const dom::Element& aOriginatingElement, ComputedStyle& aParentStyle);
|
||||
dom::Element* aOriginatingElement, PseudoStyleType aType,
|
||||
ComputedStyle* aParentStyle, dom::Element* aPseudoElement);
|
||||
|
||||
// Resolves style for a (possibly-pseudo) Element without assuming that the
|
||||
// style has been resolved. If the element was unstyled and a new style
|
||||
|
@ -241,6 +219,11 @@ class ServoStyleSet {
|
|||
|
||||
void AddDocStyleSheet(StyleSheet* aSheet);
|
||||
|
||||
// check whether there is ::before/::after style for an element
|
||||
already_AddRefed<ComputedStyle> ProbePseudoElementStyle(
|
||||
const dom::Element& aOriginatingElement, PseudoStyleType aType,
|
||||
ComputedStyle* aParentStyle);
|
||||
|
||||
/**
|
||||
* Performs a Servo traversal to compute style for all dirty nodes in the
|
||||
* document.
|
||||
|
|
|
@ -84,6 +84,12 @@ impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
|
|||
self.current_len = 0;
|
||||
}
|
||||
|
||||
/// Returns true if no simple selectors have ever been pushed to this builder.
|
||||
#[inline(always)]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.simple_selectors.is_empty()
|
||||
}
|
||||
|
||||
/// Returns true if combinators have ever been pushed to this builder.
|
||||
#[inline(always)]
|
||||
pub fn has_combinators(&self) -> bool {
|
||||
|
|
|
@ -331,11 +331,10 @@ where
|
|||
return false;
|
||||
}
|
||||
|
||||
// Advance to the non-pseudo-element part of the selector.
|
||||
let next_sequence = iter.next_sequence().unwrap();
|
||||
debug_assert_eq!(next_sequence, Combinator::PseudoElement);
|
||||
if element.is_pseudo_element() {
|
||||
return false;
|
||||
// Advance to the non-pseudo-element part of the selector, but let the
|
||||
// context note that .
|
||||
if iter.next_sequence().is_none() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -467,13 +466,7 @@ where
|
|||
}
|
||||
Some(current_slot)
|
||||
},
|
||||
Combinator::PseudoElement => {
|
||||
let next_element = element.pseudo_element_originating_element()?;
|
||||
if next_element.is_pseudo_element() {
|
||||
return None;
|
||||
}
|
||||
Some(next_element)
|
||||
}
|
||||
Combinator::PseudoElement => element.pseudo_element_originating_element(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -684,6 +677,7 @@ where
|
|||
Component::Slotted(ref selector) => {
|
||||
// <slots> are never flattened tree slottables.
|
||||
!element.is_html_slot_element() &&
|
||||
element.assigned_slot().is_some() &&
|
||||
context.shared.nest(|context| {
|
||||
matches_complex_selector(selector.iter(), element, context, flags_setter)
|
||||
})
|
||||
|
|
|
@ -1998,7 +1998,9 @@ where
|
|||
},
|
||||
SimpleSelectorParseResult::SlottedPseudo(selector) => {
|
||||
state.insert(SelectorParsingState::AFTER_SLOTTED);
|
||||
builder.push_combinator(Combinator::SlotAssignment);
|
||||
if !builder.is_empty() {
|
||||
builder.push_combinator(Combinator::SlotAssignment);
|
||||
}
|
||||
builder.push_simple_selector(Component::Slotted(selector));
|
||||
},
|
||||
SimpleSelectorParseResult::PseudoElement(p) => {
|
||||
|
@ -2006,7 +2008,9 @@ where
|
|||
if !p.accepts_state_pseudo_classes() {
|
||||
state.insert(SelectorParsingState::AFTER_NON_STATEFUL_PSEUDO_ELEMENT);
|
||||
}
|
||||
builder.push_combinator(Combinator::PseudoElement);
|
||||
if !builder.is_empty() {
|
||||
builder.push_combinator(Combinator::PseudoElement);
|
||||
}
|
||||
builder.push_simple_selector(Component::PseudoElement(p));
|
||||
},
|
||||
}
|
||||
|
@ -2811,10 +2815,7 @@ pub mod tests {
|
|||
assert_eq!(
|
||||
parse("::before"),
|
||||
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
||||
vec![
|
||||
Component::Combinator(Combinator::PseudoElement),
|
||||
Component::PseudoElement(PseudoElement::Before),
|
||||
],
|
||||
vec![Component::PseudoElement(PseudoElement::Before)],
|
||||
specificity(0, 0, 1) | HAS_PSEUDO_BIT,
|
||||
)]))
|
||||
);
|
||||
|
@ -2822,7 +2823,6 @@ pub mod tests {
|
|||
parse("::before:hover"),
|
||||
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
||||
vec![
|
||||
Component::Combinator(Combinator::PseudoElement),
|
||||
Component::PseudoElement(PseudoElement::Before),
|
||||
Component::NonTSPseudoClass(PseudoClass::Hover),
|
||||
],
|
||||
|
@ -2833,7 +2833,6 @@ pub mod tests {
|
|||
parse("::before:hover:hover"),
|
||||
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
||||
vec![
|
||||
Component::Combinator(Combinator::PseudoElement),
|
||||
Component::PseudoElement(PseudoElement::Before),
|
||||
Component::NonTSPseudoClass(PseudoClass::Hover),
|
||||
Component::NonTSPseudoClass(PseudoClass::Hover),
|
||||
|
@ -2946,7 +2945,6 @@ pub mod tests {
|
|||
specificity(0, 0, 0),
|
||||
)]))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
parse_ns(":not(svg|*)", &parser),
|
||||
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
||||
|
@ -3021,8 +3019,6 @@ pub mod tests {
|
|||
Some(&Component::PseudoElement(PseudoElement::Before))
|
||||
);
|
||||
assert_eq!(iter.next(), None);
|
||||
assert_eq!(iter.next_sequence(), Some(Combinator::PseudoElement));
|
||||
assert_eq!(iter.next(), None);
|
||||
assert_eq!(iter.next_sequence(), None);
|
||||
}
|
||||
|
||||
|
|
|
@ -47,13 +47,9 @@ pub trait Element: Sized + Clone + Debug {
|
|||
///
|
||||
/// This is guaranteed to be called in a pseudo-element.
|
||||
fn pseudo_element_originating_element(&self) -> Option<Self> {
|
||||
debug_assert!(self.is_pseudo_element());
|
||||
self.parent_element()
|
||||
}
|
||||
|
||||
/// Whether we're matching on a pseudo-element.
|
||||
fn is_pseudo_element(&self) -> bool;
|
||||
|
||||
/// Skips non-element nodes
|
||||
fn prev_sibling_element(&self) -> Option<Self>;
|
||||
|
||||
|
|
|
@ -779,7 +779,7 @@ pub trait TElement:
|
|||
/// element-backed pseudo-element, in which case we return the originating
|
||||
/// element.
|
||||
fn rule_hash_target(&self) -> Self {
|
||||
if self.is_pseudo_element() {
|
||||
if self.implemented_pseudo_element().is_some() {
|
||||
self.pseudo_element_originating_element()
|
||||
.expect("Trying to collect rules for a detached pseudo-element")
|
||||
} else {
|
||||
|
|
|
@ -1098,7 +1098,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
type TraversalChildrenIterator = GeckoChildrenIterator<'le>;
|
||||
|
||||
fn inheritance_parent(&self) -> Option<Self> {
|
||||
if self.is_pseudo_element() {
|
||||
if self.implemented_pseudo_element().is_some() {
|
||||
return self.pseudo_element_originating_element();
|
||||
}
|
||||
|
||||
|
@ -1471,7 +1471,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
|||
#[inline]
|
||||
fn skip_item_display_fixup(&self) -> bool {
|
||||
debug_assert!(
|
||||
!self.is_pseudo_element(),
|
||||
self.implemented_pseudo_element().is_none(),
|
||||
"Just don't call me if I'm a pseudo, you should know the answer already"
|
||||
);
|
||||
self.is_root_of_native_anonymous_subtree()
|
||||
|
@ -1918,14 +1918,9 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
|||
Some(shadow.host())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_pseudo_element(&self) -> bool {
|
||||
self.implemented_pseudo_element().is_some()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pseudo_element_originating_element(&self) -> Option<Self> {
|
||||
debug_assert!(self.is_pseudo_element());
|
||||
debug_assert!(self.implemented_pseudo_element().is_some());
|
||||
let parent = self.closest_anon_subtree_root_parent()?;
|
||||
|
||||
// FIXME(emilio): Special-case for <input type="number">s
|
||||
|
|
|
@ -366,10 +366,6 @@ where
|
|||
self.element.is_root()
|
||||
}
|
||||
|
||||
fn is_pseudo_element(&self) -> bool {
|
||||
self.element.is_pseudo_element()
|
||||
}
|
||||
|
||||
fn pseudo_element_originating_element(&self) -> Option<Self> {
|
||||
self.element
|
||||
.pseudo_element_originating_element()
|
||||
|
|
|
@ -734,7 +734,10 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
|||
E: TElement,
|
||||
{
|
||||
if cfg!(debug_assertions) {
|
||||
if element.map_or(false, |e| e.is_pseudo_element()) {
|
||||
if element
|
||||
.and_then(|e| e.implemented_pseudo_element())
|
||||
.is_some()
|
||||
{
|
||||
// It'd be nice to assert `self.style.pseudo == Some(&pseudo)`,
|
||||
// but we do resolve ::-moz-list pseudos on ::before / ::after
|
||||
// content, sigh.
|
||||
|
|
|
@ -233,7 +233,7 @@ where
|
|||
|
||||
let mut pseudo_styles = EagerPseudoStyles::default();
|
||||
|
||||
if !self.element.is_pseudo_element() {
|
||||
if self.element.implemented_pseudo_element().is_none() {
|
||||
let layout_parent_style_for_pseudo = if primary_style.style().is_display_contents() {
|
||||
layout_parent_style
|
||||
} else {
|
||||
|
@ -293,6 +293,10 @@ where
|
|||
layout_parent_style: Option<&ComputedValues>,
|
||||
pseudo: Option<&PseudoElement>,
|
||||
) -> ResolvedStyle {
|
||||
debug_assert!(
|
||||
self.element.implemented_pseudo_element().is_none() || pseudo.is_none(),
|
||||
"Pseudo-elements can't have other pseudos!"
|
||||
);
|
||||
debug_assert!(pseudo.map_or(true, |p| p.is_eager()));
|
||||
|
||||
let implemented_pseudo = self.element.implemented_pseudo_element();
|
||||
|
@ -473,8 +477,8 @@ where
|
|||
);
|
||||
debug_assert!(pseudo_element.is_eager());
|
||||
debug_assert!(
|
||||
!self.element.is_pseudo_element(),
|
||||
"Element pseudos can't have any other eager pseudo."
|
||||
self.element.implemented_pseudo_element().is_none(),
|
||||
"Element pseudos can't have any other pseudo."
|
||||
);
|
||||
|
||||
let mut applicable_declarations = ApplicableDeclarationList::new();
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
<!doctype html>
|
||||
<title>CSS Test Reference</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-lists/#list-item">
|
||||
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<link rel="author" href="https://mozilla.org" title="Mozilla">
|
||||
<style>
|
||||
div {
|
||||
display: inline-block;
|
||||
}
|
||||
div div {
|
||||
list-style-type: initial;
|
||||
display: list-item;
|
||||
}
|
||||
li {
|
||||
list-style-type: none;
|
||||
}
|
||||
</style>
|
||||
<ul>
|
||||
<li><div><div>Foo</div></div>Bar
|
||||
<script>
|
||||
// 100px from the ref.
|
||||
document.querySelector("ul").style.marginLeft = 100 - document.querySelector("div div").offsetWidth + "px";
|
||||
</script>
|
|
@ -1,17 +0,0 @@
|
|||
<!doctype html>
|
||||
<title>CSS Test: Nested ::marker with `content` property generates another ::marker</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-lists/#list-item">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1539171">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1543758">
|
||||
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<link rel="author" href="https://mozilla.org" title="Mozilla">
|
||||
<link rel="match" href="nested-marker-content-ref.html">
|
||||
<style>
|
||||
ul { margin-left: 100px }
|
||||
::marker {
|
||||
display: list-item;
|
||||
content: "Foo";
|
||||
}
|
||||
</style>
|
||||
<ul>
|
||||
<li>Bar
|
|
@ -1,36 +0,0 @@
|
|||
<!doctype html>
|
||||
<title>::marker pseudo-elements generated by ::before and ::after are not addressable by selectors</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-lists/#list-item">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1539171">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1543758">
|
||||
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<link rel="author" href="https://mozilla.org" title="Mozilla">
|
||||
<link rel="match" href="nested-marker-ref.html">
|
||||
<style>
|
||||
li, ::marker {
|
||||
color: red;
|
||||
}
|
||||
li::before, li::after {
|
||||
display: list-item;
|
||||
content: "Before";
|
||||
}
|
||||
li::after {
|
||||
content: "After";
|
||||
}
|
||||
.tweak::marker {
|
||||
color: blue;
|
||||
}
|
||||
.tweak, .tweak::before, .tweak::after {
|
||||
color: initial;
|
||||
}
|
||||
</style>
|
||||
<ol>
|
||||
<li>Foo
|
||||
<li>Bar
|
||||
<script>
|
||||
window.onload = function() {
|
||||
document.body.offsetTop;
|
||||
for (let li of document.querySelectorAll("li"))
|
||||
li.classList.add("tweak");
|
||||
}
|
||||
</script>
|
|
@ -1,15 +0,0 @@
|
|||
<!doctype html>
|
||||
<title>CSS test reference</title>
|
||||
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<link rel="author" href="https://mozilla.org" title="Mozilla">
|
||||
<style>
|
||||
li::marker {
|
||||
color: blue;
|
||||
}
|
||||
div {
|
||||
display: list-item;
|
||||
}
|
||||
</style>
|
||||
<ol>
|
||||
<li><div>Before</div>Foo<div>After</div>
|
||||
<li><div>Before</div>Bar<div>After</div>
|
|
@ -1,26 +0,0 @@
|
|||
<!doctype html>
|
||||
<title>::marker pseudo-elements generated by ::before and ::after are not addressable by global selectors</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-lists/#list-item">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1539171">
|
||||
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1543758">
|
||||
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
|
||||
<link rel="author" href="https://mozilla.org" title="Mozilla">
|
||||
<link rel="match" href="nested-marker-ref.html">
|
||||
<style>
|
||||
::marker {
|
||||
color: red;
|
||||
}
|
||||
li::marker {
|
||||
color: blue;
|
||||
}
|
||||
li::before, li::after {
|
||||
display: list-item;
|
||||
content: "Before";
|
||||
}
|
||||
li::after {
|
||||
content: "After";
|
||||
}
|
||||
</style>
|
||||
<ol>
|
||||
<li>Foo
|
||||
<li>Bar
|
Загрузка…
Ссылка в новой задаче