зеркало из 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);
|
PseudoStyleType::backdrop);
|
||||||
|
|
||||||
RefPtr<ComputedStyle> newStyle = aStyleSet.ResolvePseudoElementStyle(
|
RefPtr<ComputedStyle> newStyle = aStyleSet.ResolvePseudoElementStyle(
|
||||||
*aFrame->GetContent()->AsElement(), PseudoStyleType::backdrop,
|
aFrame->GetContent()->AsElement(), PseudoStyleType::backdrop,
|
||||||
aFrame->Style());
|
aFrame->Style(),
|
||||||
|
/* aPseudoElement = */ nullptr);
|
||||||
|
|
||||||
// NOTE(emilio): We can't use the changes handled for the owner of the
|
// 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
|
// 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 =
|
RefPtr<ComputedStyle> newStyle =
|
||||||
aRestyleState.StyleSet().ResolvePseudoElementStyle(
|
aRestyleState.StyleSet().ResolvePseudoElementStyle(
|
||||||
*aFrame->GetContent()->AsElement(), pseudoType, aFrame->Style());
|
aFrame->GetContent()->AsElement(), pseudoType, aFrame->Style(),
|
||||||
|
/* aPseudoElement = */ nullptr);
|
||||||
|
|
||||||
uint32_t equalStructs; // Not used, actually.
|
uint32_t equalStructs; // Not used, actually.
|
||||||
nsChangeHint childHint =
|
nsChangeHint childHint =
|
||||||
|
@ -2757,8 +2759,8 @@ bool RestyleManager::ProcessPostTraversal(Element* aElement,
|
||||||
styleFrame->IsBlockFrameOrSubclass() &&
|
styleFrame->IsBlockFrameOrSubclass() &&
|
||||||
!nsLayoutUtils::GetMarkerPseudo(aElement)) {
|
!nsLayoutUtils::GetMarkerPseudo(aElement)) {
|
||||||
RefPtr<ComputedStyle> pseudoStyle =
|
RefPtr<ComputedStyle> pseudoStyle =
|
||||||
aRestyleState.StyleSet().ProbeMarkerPseudoStyle(*aElement,
|
aRestyleState.StyleSet().ProbePseudoElementStyle(
|
||||||
*upToDateStyleIfRestyled);
|
*aElement, PseudoStyleType::marker, upToDateStyleIfRestyled);
|
||||||
if (pseudoStyle) {
|
if (pseudoStyle) {
|
||||||
changeHint |= nsChangeHint_ReconstructFrame;
|
changeHint |= nsChangeHint_ReconstructFrame;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1160,8 +1160,9 @@ void nsFrameConstructorState::ConstructBackdropFrameFor(nsIContent* aContent,
|
||||||
|
|
||||||
RefPtr<ComputedStyle> style =
|
RefPtr<ComputedStyle> style =
|
||||||
mPresShell->StyleSet()->ResolvePseudoElementStyle(
|
mPresShell->StyleSet()->ResolvePseudoElementStyle(
|
||||||
*aContent->AsElement(), PseudoStyleType::backdrop,
|
aContent->AsElement(), PseudoStyleType::backdrop,
|
||||||
/* aParentStyle */ nullptr);
|
/* aParentComputedStyle */ nullptr,
|
||||||
|
/* aPseudoElement */ nullptr);
|
||||||
MOZ_ASSERT(style->StyleDisplay()->mTopLayer == NS_STYLE_TOP_LAYER_TOP);
|
MOZ_ASSERT(style->StyleDisplay()->mTopLayer == NS_STYLE_TOP_LAYER_TOP);
|
||||||
nsContainerFrame* parentFrame =
|
nsContainerFrame* parentFrame =
|
||||||
GetGeometricParent(*style->StyleDisplay(), nullptr);
|
GetGeometricParent(*style->StyleDisplay(), nullptr);
|
||||||
|
@ -1702,27 +1703,24 @@ void nsCSSFrameConstructor::CreateGeneratedContentItem(
|
||||||
ServoStyleSet* styleSet = mPresShell->StyleSet();
|
ServoStyleSet* styleSet = mPresShell->StyleSet();
|
||||||
|
|
||||||
// Probe for the existence of the pseudo-element
|
// 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* elemName = nullptr;
|
||||||
nsAtom* property = nullptr;
|
nsAtom* property = nullptr;
|
||||||
switch (aPseudoElement) {
|
switch (aPseudoElement) {
|
||||||
case PseudoStyleType::before:
|
case PseudoStyleType::before:
|
||||||
pseudoStyle = styleSet->ProbePseudoElementStyle(aOriginatingElement,
|
|
||||||
aPseudoElement, &aStyle);
|
|
||||||
elemName = nsGkAtoms::mozgeneratedcontentbefore;
|
elemName = nsGkAtoms::mozgeneratedcontentbefore;
|
||||||
property = nsGkAtoms::beforePseudoProperty;
|
property = nsGkAtoms::beforePseudoProperty;
|
||||||
break;
|
break;
|
||||||
case PseudoStyleType::after:
|
case PseudoStyleType::after:
|
||||||
pseudoStyle = styleSet->ProbePseudoElementStyle(aOriginatingElement,
|
|
||||||
aPseudoElement, &aStyle);
|
|
||||||
elemName = nsGkAtoms::mozgeneratedcontentafter;
|
elemName = nsGkAtoms::mozgeneratedcontentafter;
|
||||||
property = nsGkAtoms::afterPseudoProperty;
|
property = nsGkAtoms::afterPseudoProperty;
|
||||||
break;
|
break;
|
||||||
case PseudoStyleType::marker:
|
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;
|
elemName = nsGkAtoms::mozgeneratedcontentmarker;
|
||||||
property = nsGkAtoms::markerPseudoProperty;
|
property = nsGkAtoms::markerPseudoProperty;
|
||||||
break;
|
break;
|
||||||
|
@ -1730,10 +1728,6 @@ void nsCSSFrameConstructor::CreateGeneratedContentItem(
|
||||||
MOZ_ASSERT_UNREACHABLE("unexpected aPseudoElement");
|
MOZ_ASSERT_UNREACHABLE("unexpected aPseudoElement");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pseudoStyle) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// |ProbePseudoStyleFor| checked the 'display' property and the
|
// |ProbePseudoStyleFor| checked the 'display' property and the
|
||||||
// |ContentCount()| of the 'content' property for us.
|
// |ContentCount()| of the 'content' property for us.
|
||||||
RefPtr<NodeInfo> nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(
|
RefPtr<NodeInfo> nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(
|
||||||
|
@ -8718,7 +8712,8 @@ already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLetterStyle(
|
||||||
nsIContent* aContent, ComputedStyle* aComputedStyle) {
|
nsIContent* aContent, ComputedStyle* aComputedStyle) {
|
||||||
if (aContent) {
|
if (aContent) {
|
||||||
return mPresShell->StyleSet()->ResolvePseudoElementStyle(
|
return mPresShell->StyleSet()->ResolvePseudoElementStyle(
|
||||||
*aContent->AsElement(), PseudoStyleType::firstLetter, aComputedStyle);
|
aContent->AsElement(), PseudoStyleType::firstLetter, aComputedStyle,
|
||||||
|
nullptr);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -8727,7 +8722,8 @@ already_AddRefed<ComputedStyle> nsCSSFrameConstructor::GetFirstLineStyle(
|
||||||
nsIContent* aContent, ComputedStyle* aComputedStyle) {
|
nsIContent* aContent, ComputedStyle* aComputedStyle) {
|
||||||
if (aContent) {
|
if (aContent) {
|
||||||
return mPresShell->StyleSet()->ResolvePseudoElementStyle(
|
return mPresShell->StyleSet()->ResolvePseudoElementStyle(
|
||||||
*aContent->AsElement(), PseudoStyleType::firstLine, aComputedStyle);
|
aContent->AsElement(), PseudoStyleType::firstLine, aComputedStyle,
|
||||||
|
nullptr);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -500,12 +500,13 @@ ImgDrawResult nsButtonFrameRenderer::PaintBorder(nsDisplayListBuilder* aBuilder,
|
||||||
*/
|
*/
|
||||||
void nsButtonFrameRenderer::ReResolveStyles(nsPresContext* aPresContext) {
|
void nsButtonFrameRenderer::ReResolveStyles(nsPresContext* aPresContext) {
|
||||||
// get all the styles
|
// get all the styles
|
||||||
|
ComputedStyle* context = mFrame->Style();
|
||||||
ServoStyleSet* styleSet = aPresContext->StyleSet();
|
ServoStyleSet* styleSet = aPresContext->StyleSet();
|
||||||
|
|
||||||
// get styles assigned to -moz-focus-inner (ie dotted border on Windows)
|
// get styles assigned to -moz-focus-inner (ie dotted border on Windows)
|
||||||
mInnerFocusStyle = styleSet->ProbePseudoElementStyle(
|
mInnerFocusStyle = styleSet->ProbePseudoElementStyle(
|
||||||
*mFrame->GetContent()->AsElement(), PseudoStyleType::mozFocusInner,
|
*mFrame->GetContent()->AsElement(), PseudoStyleType::mozFocusInner,
|
||||||
mFrame->Style());
|
context);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComputedStyle* nsButtonFrameRenderer::GetComputedStyle(int32_t aIndex) const {
|
ComputedStyle* nsButtonFrameRenderer::GetComputedStyle(int32_t aIndex) const {
|
||||||
|
|
|
@ -5465,7 +5465,8 @@ void nsBlockFrame::UpdateFirstLetterStyle(ServoRestyleState& aRestyleState) {
|
||||||
ComputedStyle* parentStyle = styleParent->Style();
|
ComputedStyle* parentStyle = styleParent->Style();
|
||||||
RefPtr<ComputedStyle> firstLetterStyle =
|
RefPtr<ComputedStyle> firstLetterStyle =
|
||||||
aRestyleState.StyleSet().ResolvePseudoElementStyle(
|
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
|
// Note that we don't need to worry about changehints for the continuation
|
||||||
// styles: those will be handled by the styleParent already.
|
// styles: those will be handled by the styleParent already.
|
||||||
RefPtr<ComputedStyle> continuationStyle =
|
RefPtr<ComputedStyle> continuationStyle =
|
||||||
|
@ -7187,7 +7188,8 @@ void nsBlockFrame::UpdatePseudoElementStyles(ServoRestyleState& aRestyleState) {
|
||||||
ComputedStyle* parentStyle = styleParent->Style();
|
ComputedStyle* parentStyle = styleParent->Style();
|
||||||
RefPtr<ComputedStyle> firstLineStyle =
|
RefPtr<ComputedStyle> firstLineStyle =
|
||||||
aRestyleState.StyleSet().ResolvePseudoElementStyle(
|
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
|
// FIXME(bz): Can we make first-line continuations be non-inheriting anon
|
||||||
// boxes?
|
// boxes?
|
||||||
|
|
|
@ -98,7 +98,7 @@ void nsMathMLFrame::ResolveMathMLCharStyle(nsPresContext* aPresContext,
|
||||||
PseudoStyleType pseudoType = PseudoStyleType::mozMathAnonymous; // savings
|
PseudoStyleType pseudoType = PseudoStyleType::mozMathAnonymous; // savings
|
||||||
RefPtr<ComputedStyle> newComputedStyle;
|
RefPtr<ComputedStyle> newComputedStyle;
|
||||||
newComputedStyle = aPresContext->StyleSet()->ResolvePseudoElementStyle(
|
newComputedStyle = aPresContext->StyleSet()->ResolvePseudoElementStyle(
|
||||||
*aContent->AsElement(), pseudoType, aParentComputedStyle);
|
aContent->AsElement(), pseudoType, aParentComputedStyle, nullptr);
|
||||||
|
|
||||||
aMathMLChar->SetComputedStyle(newComputedStyle);
|
aMathMLChar->SetComputedStyle(newComputedStyle);
|
||||||
}
|
}
|
||||||
|
|
|
@ -374,6 +374,8 @@ Maybe<StyleStructID> ComputedStyle::LookupStruct(const nsACString& aName) {
|
||||||
ComputedStyle* ComputedStyle::GetCachedLazyPseudoStyle(
|
ComputedStyle* ComputedStyle::GetCachedLazyPseudoStyle(
|
||||||
PseudoStyleType aPseudo) const {
|
PseudoStyleType aPseudo) const {
|
||||||
MOZ_ASSERT(PseudoStyle::IsPseudoElement(aPseudo));
|
MOZ_ASSERT(PseudoStyle::IsPseudoElement(aPseudo));
|
||||||
|
MOZ_ASSERT(!IsLazilyCascadedPseudoElement(),
|
||||||
|
"Lazy pseudos can't inherit lazy pseudos");
|
||||||
|
|
||||||
if (nsCSSPseudoElements::PseudoElementSupportsUserActionState(aPseudo)) {
|
if (nsCSSPseudoElements::PseudoElementSupportsUserActionState(aPseudo)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -194,6 +194,8 @@ class ComputedStyle {
|
||||||
void SetCachedLazyPseudoStyle(ComputedStyle* aStyle) {
|
void SetCachedLazyPseudoStyle(ComputedStyle* aStyle) {
|
||||||
MOZ_ASSERT(aStyle->IsPseudoElement());
|
MOZ_ASSERT(aStyle->IsPseudoElement());
|
||||||
MOZ_ASSERT(!GetCachedLazyPseudoStyle(aStyle->GetPseudoType()));
|
MOZ_ASSERT(!GetCachedLazyPseudoStyle(aStyle->GetPseudoType()));
|
||||||
|
MOZ_ASSERT(!IsLazilyCascadedPseudoElement(),
|
||||||
|
"lazy pseudos can't inherit lazy pseudos");
|
||||||
MOZ_ASSERT(aStyle->IsLazilyCascadedPseudoElement());
|
MOZ_ASSERT(aStyle->IsLazilyCascadedPseudoElement());
|
||||||
|
|
||||||
// Since we're caching lazy pseudo styles on the ComputedValues of the
|
// 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(
|
already_AddRefed<ComputedStyle> ServoStyleSet::ResolvePseudoElementStyle(
|
||||||
const Element& aOriginatingElement, PseudoStyleType aType,
|
Element* aOriginatingElement, PseudoStyleType aType,
|
||||||
ComputedStyle* aParentStyle, IsProbe aIsProbe) {
|
ComputedStyle* aParentStyle, Element* aPseudoElement) {
|
||||||
// Runs from frame construction, this should have clean styles already, except
|
// Runs from frame construction, this should have clean styles already, except
|
||||||
// with non-lazy FC...
|
// with non-lazy FC...
|
||||||
UpdateStylistIfNeeded();
|
UpdateStylistIfNeeded();
|
||||||
MOZ_ASSERT(PseudoStyle::IsPseudoElement(aType));
|
MOZ_ASSERT(PseudoStyle::IsPseudoElement(aType));
|
||||||
|
|
||||||
const bool cacheable =
|
RefPtr<ComputedStyle> computedValues;
|
||||||
LazyPseudoIsCacheable(aType, aOriginatingElement, aParentStyle);
|
|
||||||
RefPtr<ComputedStyle> style =
|
|
||||||
cacheable ? aParentStyle->GetCachedLazyPseudoStyle(aType) : nullptr;
|
|
||||||
|
|
||||||
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) {
|
if (!computedValues) {
|
||||||
// FIXME(emilio): Why passing null for probing as the parent style?
|
computedValues = Servo_ResolvePseudoStyle(aOriginatingElement, aType,
|
||||||
//
|
/* is_probe = */ false,
|
||||||
// There are callers which do pass the wrong parent style and it would
|
aParentStyle, mRawSet.get())
|
||||||
// assert (like ComputeSelectionStyle()). That's messy!
|
.Consume();
|
||||||
style = Servo_ResolvePseudoStyle(&aOriginatingElement, aType, isProbe,
|
if (cacheable) {
|
||||||
isProbe ? nullptr : aParentStyle,
|
aParentStyle->SetCachedLazyPseudoStyle(computedValues);
|
||||||
mRawSet.get())
|
}
|
||||||
.Consume();
|
|
||||||
if (!style) {
|
|
||||||
MOZ_ASSERT(isProbe);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (cacheable) {
|
|
||||||
aParentStyle->SetCachedLazyPseudoStyle(style);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(style);
|
MOZ_ASSERT(computedValues);
|
||||||
|
return computedValues.forget();
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<ComputedStyle>
|
already_AddRefed<ComputedStyle>
|
||||||
|
@ -674,35 +657,66 @@ void ServoStyleSet::AddDocStyleSheet(StyleSheet* aSheet) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServoStyleSet::GeneratedContentPseudoExists(
|
already_AddRefed<ComputedStyle> ServoStyleSet::ProbePseudoElementStyle(
|
||||||
const ComputedStyle& aParentStyle, const ComputedStyle& aPseudoStyle) {
|
const Element& aOriginatingElement, PseudoStyleType aType,
|
||||||
auto type = aPseudoStyle.GetPseudoType();
|
ComputedStyle* aParentStyle) {
|
||||||
MOZ_ASSERT(type != PseudoStyleType::NotPseudo);
|
// 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).
|
// ::marker only exist for list items (for now).
|
||||||
if (aParentStyle.StyleDisplay()->mDisplay != StyleDisplay::ListItem) {
|
if (aParentStyle->StyleDisplay()->mDisplay != StyleDisplay::ListItem) {
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// display:none is equivalent to not having the pseudo-element at all.
|
// display:none is equivalent to not having the pseudo-element at all.
|
||||||
if (aPseudoStyle.StyleDisplay()->mDisplay == StyleDisplay::None) {
|
if (computedValues->StyleDisplay()->mDisplay == StyleDisplay::None) {
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For :before and :after pseudo-elements, having display: none or no
|
// For :before and :after pseudo-elements, having display: none or no
|
||||||
// 'content' property is equivalent to not having the pseudo-element
|
// 'content' property is equivalent to not having the pseudo-element
|
||||||
// at all.
|
// at all.
|
||||||
if (type == PseudoStyleType::before || type == PseudoStyleType::after) {
|
bool isBeforeOrAfter =
|
||||||
if (aPseudoStyle.StyleDisplay()->mDisplay == StyleDisplay::None) {
|
aType == PseudoStyleType::before || aType == PseudoStyleType::after;
|
||||||
return false;
|
if (isBeforeOrAfter) {
|
||||||
}
|
const nsStyleDisplay* display = computedValues->StyleDisplay();
|
||||||
if (!aPseudoStyle.StyleContent()->ContentCount()) {
|
const nsStyleContent* content = computedValues->StyleContent();
|
||||||
return false;
|
if (display->mDisplay == StyleDisplay::None ||
|
||||||
|
content->ContentCount() == 0) {
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return computedValues.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServoStyleSet::StyleDocument(ServoTraversalFlags aFlags) {
|
bool ServoStyleSet::StyleDocument(ServoTraversalFlags aFlags) {
|
||||||
|
|
|
@ -168,36 +168,14 @@ class ServoStyleSet {
|
||||||
// matching for them is a first step.)
|
// matching for them is a first step.)
|
||||||
already_AddRefed<ComputedStyle> ResolveStyleForPlaceholder();
|
already_AddRefed<ComputedStyle> ResolveStyleForPlaceholder();
|
||||||
|
|
||||||
// Returns whether a given pseudo-element should exist or not.
|
// Get a ComputedStyle for a pseudo-element. aParentElement must be
|
||||||
static bool GeneratedContentPseudoExists(const ComputedStyle& aParentStyle,
|
// non-null. aPseudoID is the PseudoStyleType for the
|
||||||
const ComputedStyle& aPseudoStyle);
|
// pseudo-element. aPseudoElement must be non-null if the pseudo-element
|
||||||
|
// type is one that allows user action pseudo-classes after it or allows
|
||||||
enum class IsProbe {
|
// style attributes; otherwise, it is ignored.
|
||||||
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.
|
|
||||||
already_AddRefed<ComputedStyle> ResolvePseudoElementStyle(
|
already_AddRefed<ComputedStyle> ResolvePseudoElementStyle(
|
||||||
const dom::Element& aOriginatingElement, PseudoStyleType,
|
dom::Element* aOriginatingElement, PseudoStyleType aType,
|
||||||
ComputedStyle* aParentStyle, IsProbe = IsProbe::No);
|
ComputedStyle* aParentStyle, dom::Element* aPseudoElement);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Resolves style for a (possibly-pseudo) Element without assuming that the
|
// Resolves style for a (possibly-pseudo) Element without assuming that the
|
||||||
// style has been resolved. If the element was unstyled and a new style
|
// style has been resolved. If the element was unstyled and a new style
|
||||||
|
@ -241,6 +219,11 @@ class ServoStyleSet {
|
||||||
|
|
||||||
void AddDocStyleSheet(StyleSheet* aSheet);
|
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
|
* Performs a Servo traversal to compute style for all dirty nodes in the
|
||||||
* document.
|
* document.
|
||||||
|
|
|
@ -84,6 +84,12 @@ impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
|
||||||
self.current_len = 0;
|
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.
|
/// Returns true if combinators have ever been pushed to this builder.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn has_combinators(&self) -> bool {
|
pub fn has_combinators(&self) -> bool {
|
||||||
|
|
|
@ -331,11 +331,10 @@ where
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance to the non-pseudo-element part of the selector.
|
// Advance to the non-pseudo-element part of the selector, but let the
|
||||||
let next_sequence = iter.next_sequence().unwrap();
|
// context note that .
|
||||||
debug_assert_eq!(next_sequence, Combinator::PseudoElement);
|
if iter.next_sequence().is_none() {
|
||||||
if element.is_pseudo_element() {
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -467,13 +466,7 @@ where
|
||||||
}
|
}
|
||||||
Some(current_slot)
|
Some(current_slot)
|
||||||
},
|
},
|
||||||
Combinator::PseudoElement => {
|
Combinator::PseudoElement => element.pseudo_element_originating_element(),
|
||||||
let next_element = element.pseudo_element_originating_element()?;
|
|
||||||
if next_element.is_pseudo_element() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(next_element)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,6 +677,7 @@ where
|
||||||
Component::Slotted(ref selector) => {
|
Component::Slotted(ref selector) => {
|
||||||
// <slots> are never flattened tree slottables.
|
// <slots> are never flattened tree slottables.
|
||||||
!element.is_html_slot_element() &&
|
!element.is_html_slot_element() &&
|
||||||
|
element.assigned_slot().is_some() &&
|
||||||
context.shared.nest(|context| {
|
context.shared.nest(|context| {
|
||||||
matches_complex_selector(selector.iter(), element, context, flags_setter)
|
matches_complex_selector(selector.iter(), element, context, flags_setter)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1998,7 +1998,9 @@ where
|
||||||
},
|
},
|
||||||
SimpleSelectorParseResult::SlottedPseudo(selector) => {
|
SimpleSelectorParseResult::SlottedPseudo(selector) => {
|
||||||
state.insert(SelectorParsingState::AFTER_SLOTTED);
|
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));
|
builder.push_simple_selector(Component::Slotted(selector));
|
||||||
},
|
},
|
||||||
SimpleSelectorParseResult::PseudoElement(p) => {
|
SimpleSelectorParseResult::PseudoElement(p) => {
|
||||||
|
@ -2006,7 +2008,9 @@ where
|
||||||
if !p.accepts_state_pseudo_classes() {
|
if !p.accepts_state_pseudo_classes() {
|
||||||
state.insert(SelectorParsingState::AFTER_NON_STATEFUL_PSEUDO_ELEMENT);
|
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));
|
builder.push_simple_selector(Component::PseudoElement(p));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -2811,10 +2815,7 @@ pub mod tests {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse("::before"),
|
parse("::before"),
|
||||||
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
||||||
vec![
|
vec![Component::PseudoElement(PseudoElement::Before)],
|
||||||
Component::Combinator(Combinator::PseudoElement),
|
|
||||||
Component::PseudoElement(PseudoElement::Before),
|
|
||||||
],
|
|
||||||
specificity(0, 0, 1) | HAS_PSEUDO_BIT,
|
specificity(0, 0, 1) | HAS_PSEUDO_BIT,
|
||||||
)]))
|
)]))
|
||||||
);
|
);
|
||||||
|
@ -2822,7 +2823,6 @@ pub mod tests {
|
||||||
parse("::before:hover"),
|
parse("::before:hover"),
|
||||||
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
||||||
vec![
|
vec![
|
||||||
Component::Combinator(Combinator::PseudoElement),
|
|
||||||
Component::PseudoElement(PseudoElement::Before),
|
Component::PseudoElement(PseudoElement::Before),
|
||||||
Component::NonTSPseudoClass(PseudoClass::Hover),
|
Component::NonTSPseudoClass(PseudoClass::Hover),
|
||||||
],
|
],
|
||||||
|
@ -2833,7 +2833,6 @@ pub mod tests {
|
||||||
parse("::before:hover:hover"),
|
parse("::before:hover:hover"),
|
||||||
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
||||||
vec![
|
vec![
|
||||||
Component::Combinator(Combinator::PseudoElement),
|
|
||||||
Component::PseudoElement(PseudoElement::Before),
|
Component::PseudoElement(PseudoElement::Before),
|
||||||
Component::NonTSPseudoClass(PseudoClass::Hover),
|
Component::NonTSPseudoClass(PseudoClass::Hover),
|
||||||
Component::NonTSPseudoClass(PseudoClass::Hover),
|
Component::NonTSPseudoClass(PseudoClass::Hover),
|
||||||
|
@ -2946,7 +2945,6 @@ pub mod tests {
|
||||||
specificity(0, 0, 0),
|
specificity(0, 0, 0),
|
||||||
)]))
|
)]))
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_ns(":not(svg|*)", &parser),
|
parse_ns(":not(svg|*)", &parser),
|
||||||
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
Ok(SelectorList::from_vec(vec![Selector::from_vec(
|
||||||
|
@ -3021,8 +3019,6 @@ pub mod tests {
|
||||||
Some(&Component::PseudoElement(PseudoElement::Before))
|
Some(&Component::PseudoElement(PseudoElement::Before))
|
||||||
);
|
);
|
||||||
assert_eq!(iter.next(), None);
|
assert_eq!(iter.next(), None);
|
||||||
assert_eq!(iter.next_sequence(), Some(Combinator::PseudoElement));
|
|
||||||
assert_eq!(iter.next(), None);
|
|
||||||
assert_eq!(iter.next_sequence(), 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.
|
/// This is guaranteed to be called in a pseudo-element.
|
||||||
fn pseudo_element_originating_element(&self) -> Option<Self> {
|
fn pseudo_element_originating_element(&self) -> Option<Self> {
|
||||||
debug_assert!(self.is_pseudo_element());
|
|
||||||
self.parent_element()
|
self.parent_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether we're matching on a pseudo-element.
|
|
||||||
fn is_pseudo_element(&self) -> bool;
|
|
||||||
|
|
||||||
/// Skips non-element nodes
|
/// Skips non-element nodes
|
||||||
fn prev_sibling_element(&self) -> Option<Self>;
|
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-backed pseudo-element, in which case we return the originating
|
||||||
/// element.
|
/// element.
|
||||||
fn rule_hash_target(&self) -> Self {
|
fn rule_hash_target(&self) -> Self {
|
||||||
if self.is_pseudo_element() {
|
if self.implemented_pseudo_element().is_some() {
|
||||||
self.pseudo_element_originating_element()
|
self.pseudo_element_originating_element()
|
||||||
.expect("Trying to collect rules for a detached pseudo-element")
|
.expect("Trying to collect rules for a detached pseudo-element")
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1098,7 +1098,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
type TraversalChildrenIterator = GeckoChildrenIterator<'le>;
|
type TraversalChildrenIterator = GeckoChildrenIterator<'le>;
|
||||||
|
|
||||||
fn inheritance_parent(&self) -> Option<Self> {
|
fn inheritance_parent(&self) -> Option<Self> {
|
||||||
if self.is_pseudo_element() {
|
if self.implemented_pseudo_element().is_some() {
|
||||||
return self.pseudo_element_originating_element();
|
return self.pseudo_element_originating_element();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1471,7 +1471,7 @@ impl<'le> TElement for GeckoElement<'le> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn skip_item_display_fixup(&self) -> bool {
|
fn skip_item_display_fixup(&self) -> bool {
|
||||||
debug_assert!(
|
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"
|
"Just don't call me if I'm a pseudo, you should know the answer already"
|
||||||
);
|
);
|
||||||
self.is_root_of_native_anonymous_subtree()
|
self.is_root_of_native_anonymous_subtree()
|
||||||
|
@ -1918,14 +1918,9 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
Some(shadow.host())
|
Some(shadow.host())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn is_pseudo_element(&self) -> bool {
|
|
||||||
self.implemented_pseudo_element().is_some()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn pseudo_element_originating_element(&self) -> Option<Self> {
|
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()?;
|
let parent = self.closest_anon_subtree_root_parent()?;
|
||||||
|
|
||||||
// FIXME(emilio): Special-case for <input type="number">s
|
// FIXME(emilio): Special-case for <input type="number">s
|
||||||
|
|
|
@ -366,10 +366,6 @@ where
|
||||||
self.element.is_root()
|
self.element.is_root()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_pseudo_element(&self) -> bool {
|
|
||||||
self.element.is_pseudo_element()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pseudo_element_originating_element(&self) -> Option<Self> {
|
fn pseudo_element_originating_element(&self) -> Option<Self> {
|
||||||
self.element
|
self.element
|
||||||
.pseudo_element_originating_element()
|
.pseudo_element_originating_element()
|
||||||
|
|
|
@ -734,7 +734,10 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
|
||||||
E: TElement,
|
E: TElement,
|
||||||
{
|
{
|
||||||
if cfg!(debug_assertions) {
|
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)`,
|
// It'd be nice to assert `self.style.pseudo == Some(&pseudo)`,
|
||||||
// but we do resolve ::-moz-list pseudos on ::before / ::after
|
// but we do resolve ::-moz-list pseudos on ::before / ::after
|
||||||
// content, sigh.
|
// content, sigh.
|
||||||
|
|
|
@ -233,7 +233,7 @@ where
|
||||||
|
|
||||||
let mut pseudo_styles = EagerPseudoStyles::default();
|
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() {
|
let layout_parent_style_for_pseudo = if primary_style.style().is_display_contents() {
|
||||||
layout_parent_style
|
layout_parent_style
|
||||||
} else {
|
} else {
|
||||||
|
@ -293,6 +293,10 @@ where
|
||||||
layout_parent_style: Option<&ComputedValues>,
|
layout_parent_style: Option<&ComputedValues>,
|
||||||
pseudo: Option<&PseudoElement>,
|
pseudo: Option<&PseudoElement>,
|
||||||
) -> ResolvedStyle {
|
) -> 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()));
|
debug_assert!(pseudo.map_or(true, |p| p.is_eager()));
|
||||||
|
|
||||||
let implemented_pseudo = self.element.implemented_pseudo_element();
|
let implemented_pseudo = self.element.implemented_pseudo_element();
|
||||||
|
@ -473,8 +477,8 @@ where
|
||||||
);
|
);
|
||||||
debug_assert!(pseudo_element.is_eager());
|
debug_assert!(pseudo_element.is_eager());
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
!self.element.is_pseudo_element(),
|
self.element.implemented_pseudo_element().is_none(),
|
||||||
"Element pseudos can't have any other eager pseudo."
|
"Element pseudos can't have any other pseudo."
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut applicable_declarations = ApplicableDeclarationList::new();
|
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
|
|
Загрузка…
Ссылка в новой задаче