Backed out changeset 8c89fd37b79d (bug 1544242) for failures in browser_rules_shadowdom_slot_rules.js CLOSED TREE

This commit is contained in:
Noemi Erli 2019-05-01 22:03:06 +03:00
Родитель 7fa6125c63
Коммит f1ef21cbc7
23 изменённых файлов: 146 добавлений и 271 удалений

Просмотреть файл

@ -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