Backed out changeset 8c89fd37b79d (bug 1544242) for failures in browser_rules_shadowdom_slot_rules.js CLOSED TREE
authorNoemi Erli <nerli@mozilla.com>
Wed, 01 May 2019 22:03:06 +0300
changeset 472151 c7a22f0ea7b4ce3ff379f5be1d1ad3070aa76317
parent 472150 e53475bc9b50b3bfd81cf5db7493433886148e18
child 472152 89d5d74f031b79607e7e68c2a273ffb91d2539bd
child 472155 bb6e8015f9757fb6c638364e9229abf95c1b21d0
push id112980
push usernerli@mozilla.com
push dateWed, 01 May 2019 21:59:08 +0000
treeherdermozilla-inbound@89d5d74f031b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1544242
milestone68.0a1
backs out8c89fd37b79d353a6eb8794f3de11151f6924b26
first release with
nightly linux32
c7a22f0ea7b4 / 68.0a1 / 20190501215533 / files
nightly linux64
c7a22f0ea7b4 / 68.0a1 / 20190501215533 / files
nightly mac
c7a22f0ea7b4 / 68.0a1 / 20190501215533 / files
nightly win32
c7a22f0ea7b4 / 68.0a1 / 20190501215533 / files
nightly win64
c7a22f0ea7b4 / 68.0a1 / 20190501215533 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset 8c89fd37b79d (bug 1544242) for failures in browser_rules_shadowdom_slot_rules.js CLOSED TREE
layout/base/RestyleManager.cpp
layout/base/nsCSSFrameConstructor.cpp
layout/forms/nsButtonFrameRenderer.cpp
layout/generic/nsBlockFrame.cpp
layout/mathml/nsMathMLFrame.cpp
layout/style/ComputedStyle.cpp
layout/style/ComputedStyle.h
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
servo/components/selectors/builder.rs
servo/components/selectors/matching.rs
servo/components/selectors/parser.rs
servo/components/selectors/tree.rs
servo/components/style/dom.rs
servo/components/style/gecko/wrapper.rs
servo/components/style/invalidation/element/element_wrapper.rs
servo/components/style/style_adjuster.rs
servo/components/style/style_resolver.rs
testing/web-platform/tests/css/css-lists/nested-marker-content-ref.html
testing/web-platform/tests/css/css-lists/nested-marker-content.html
testing/web-platform/tests/css/css-lists/nested-marker-dynamic.html
testing/web-platform/tests/css/css-lists/nested-marker-ref.html
testing/web-platform/tests/css/css-lists/nested-marker.html
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -2511,18 +2511,19 @@ static void UpdateBackdropIfNeeded(nsIFr
   MOZ_ASSERT(backdropPlaceholder->IsPlaceholderFrame());
   nsIFrame* backdropFrame =
       nsPlaceholderFrame::GetRealFrameForPlaceholder(backdropPlaceholder);
   MOZ_ASSERT(backdropFrame->IsBackdropFrame());
   MOZ_ASSERT(backdropFrame->Style()->GetPseudoType() ==
              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
   // canvas frame (depending on the `position` value).
   MOZ_ASSERT(backdropFrame->GetParent()->IsViewportFrame() ||
              backdropFrame->GetParent()->IsCanvasFrame());
   nsTArray<nsIFrame*> wrappersToRestyle;
   ServoRestyleState state(aStyleSet, aChangeList, wrappersToRestyle);
@@ -2555,17 +2556,18 @@ static void UpdateOneAdditionalComputedS
                                              ServoRestyleState& aRestyleState) {
   auto pseudoType = aOldContext.GetPseudoType();
   MOZ_ASSERT(pseudoType != PseudoStyleType::NotPseudo);
   MOZ_ASSERT(
       !nsCSSPseudoElements::PseudoElementSupportsUserActionState(pseudoType));
 
   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 =
       aOldContext.CalcStyleDifference(*newStyle, &equalStructs);
   if (!aFrame->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW) &&
       !aFrame->IsColumnSpanInMulticolSubtree()) {
     childHint = NS_RemoveSubsumedHints(childHint,
                                        aRestyleState.ChangesHandledFor(aFrame));
@@ -2752,18 +2754,18 @@ bool RestyleManager::ProcessPostTraversa
     // If we don't have a ::marker pseudo-element, but need it, then
     // reconstruct the frame.  (The opposite situation implies 'display'
     // changes so doesn't need to be handled explicitly here.)
     if (wasRestyled &&
         styleFrame->StyleDisplay()->mDisplay == StyleDisplay::ListItem &&
         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;
       }
     }
   }
 
   // Although we shouldn't generate non-ReconstructFrame hints for elements with
   // no frames, we can still get them here if they were explicitly posted by
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1155,18 +1155,19 @@ void nsFrameConstructorState::ConstructB
   nsContainerFrame* frame = do_QueryFrame(aFrame);
   if (!frame) {
     NS_WARNING("Cannot create backdrop frame for non-container frame");
     return;
   }
 
   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);
 
   nsBackdropFrame* backdropFrame =
       new (mPresShell) nsBackdropFrame(style, mPresShell->GetPresContext());
   backdropFrame->Init(aContent, parentFrame, nullptr);
 
@@ -1697,48 +1698,41 @@ void nsCSSFrameConstructor::CreateGenera
     // Video frames and date time control frames may not be leafs when backed by
     // an UA widget, but we still don't want to expose generated content.
     return;
   }
 
   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;
     default:
       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(
       elemName, nullptr, kNameSpaceID_None, nsINode::ELEMENT_NODE);
   RefPtr<Element> container;
   nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo.forget());
   if (NS_FAILED(rv)) {
     return;
@@ -8713,26 +8707,28 @@ bool nsCSSFrameConstructor::DestroyFrame
 //////////////////////////////////////////////////////////////////////
 
 // Block frame construction code
 
 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;
 }
 
 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;
 }
 
 // Predicate to see if a given content (block element) has
 // first-letter style applied to it.
 bool nsCSSFrameConstructor::ShouldHaveFirstLetterStyle(
     nsIContent* aContent, ComputedStyle* aComputedStyle) {
--- a/layout/forms/nsButtonFrameRenderer.cpp
+++ b/layout/forms/nsButtonFrameRenderer.cpp
@@ -495,22 +495,23 @@ ImgDrawResult nsButtonFrameRenderer::Pai
   return result;
 }
 
 /**
  * Call this when styles change
  */
 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 {
   switch (aIndex) {
     case NS_BUTTON_RENDERER_FOCUS_INNER_CONTEXT_INDEX:
       return mInnerFocusStyle;
     default:
       return nullptr;
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -5460,17 +5460,18 @@ void nsBlockFrame::UpdateFirstLetterStyl
   if (inFlowFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
     inFlowFrame = inFlowFrame->GetPlaceholderFrame();
   }
   nsIFrame* styleParent = CorrectStyleParentFrame(inFlowFrame->GetParent(),
                                                   PseudoStyleType::firstLetter);
   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 =
       aRestyleState.StyleSet().ResolveStyleForFirstLetterContinuation(
           parentStyle);
   UpdateStyleOfOwnedChildFrame(letterFrame, firstLetterStyle, aRestyleState,
                                Some(continuationStyle.get()));
 
@@ -7182,17 +7183,18 @@ void nsBlockFrame::UpdatePseudoElementSt
 
   if (nsIFrame* firstLineFrame = GetFirstLineFrame()) {
     nsIFrame* styleParent = CorrectStyleParentFrame(firstLineFrame->GetParent(),
                                                     PseudoStyleType::firstLine);
 
     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?
     RefPtr<ComputedStyle> continuationStyle =
         aRestyleState.StyleSet().ResolveInheritingAnonymousBoxStyle(
             PseudoStyleType::mozLineFrame, parentStyle);
 
     UpdateStyleOfOwnedChildFrame(firstLineFrame, firstLineStyle, aRestyleState,
--- a/layout/mathml/nsMathMLFrame.cpp
+++ b/layout/mathml/nsMathMLFrame.cpp
@@ -93,17 +93,17 @@ nsMathMLFrame::UpdatePresentationData(ui
 /* static */
 void nsMathMLFrame::ResolveMathMLCharStyle(nsPresContext* aPresContext,
                                            nsIContent* aContent,
                                            ComputedStyle* aParentComputedStyle,
                                            nsMathMLChar* aMathMLChar) {
   PseudoStyleType pseudoType = PseudoStyleType::mozMathAnonymous;  // savings
   RefPtr<ComputedStyle> newComputedStyle;
   newComputedStyle = aPresContext->StyleSet()->ResolvePseudoElementStyle(
-      *aContent->AsElement(), pseudoType, aParentComputedStyle);
+      aContent->AsElement(), pseudoType, aParentComputedStyle, nullptr);
 
   aMathMLChar->SetComputedStyle(newComputedStyle);
 }
 
 /* static */
 void nsMathMLFrame::GetEmbellishDataFrom(nsIFrame* aFrame,
                                          nsEmbellishData& aEmbellishData) {
   // initialize OUT params
--- a/layout/style/ComputedStyle.cpp
+++ b/layout/style/ComputedStyle.cpp
@@ -369,16 +369,18 @@ Maybe<StyleStructID> ComputedStyle::Look
 #  undef STYLE_STRUCT
   return Nothing();
 }
 #endif  // DEBUG
 
 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;
   }
 
   return mCachedInheritingStyles.Lookup(aPseudo);
 }
 
--- a/layout/style/ComputedStyle.h
+++ b/layout/style/ComputedStyle.h
@@ -189,16 +189,18 @@ class ComputedStyle {
     mCachedInheritingStyles.Insert(aStyle);
   }
 
   ComputedStyle* GetCachedLazyPseudoStyle(PseudoStyleType aPseudo) const;
 
   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
     // originating element, we can assume that we either have the same
     // originating element, or that they were at least similar enough to share
     // the same ComputedValues, which means that they would match the same
     // pseudo rules. This allows us to avoid matching selectors and checking
     // the rule node before deciding to share.
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -435,65 +435,48 @@ static inline bool LazyPseudoIsCacheable
                                          ComputedStyle* aParentStyle) {
   return aParentStyle &&
          !nsCSSPseudoElements::IsEagerlyCascadedInServo(aType) &&
          aOriginatingElement.HasServoData() &&
          !Servo_Element_IsPrimaryStyleReusedViaRuleNode(&aOriginatingElement);
 }
 
 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;
-
-  const bool isProbe = aIsProbe == IsProbe::Yes;
+  RefPtr<ComputedStyle> computedValues;
 
-  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 (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 (!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>
 ServoStyleSet::ResolveInheritingAnonymousBoxStyle(PseudoStyleType aType,
                                                   ComputedStyle* aParentStyle) {
   MOZ_ASSERT(PseudoStyle::IsInheritingAnonBox(aType));
   MOZ_ASSERT_IF(aParentStyle, !StylistNeedsUpdate());
 
@@ -669,45 +652,76 @@ void ServoStyleSet::AddDocStyleSheet(Sty
     SetStylistStyleSheetsDirty();
   }
 
   if (mStyleRuleMap) {
     mStyleRuleMap->SheetAdded(*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();
+
+  // 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);
 
-  if (type == PseudoStyleType::marker) {
+  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) {
   AUTO_PROFILER_LABEL_CATEGORY_PAIR(LAYOUT_StyleComputation);
   MOZ_ASSERT(GetPresContext(), "Styling a document without a shell?");
 
   if (!mDocument->GetServoRestyleRoot()) {
     return false;
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -163,46 +163,24 @@ class ServoStyleSet {
   // The returned ComputedStyle will have nsCSSAnonBoxes::oofPlaceholder() as
   // its pseudo.
   //
   // (Perhaps nsCSSAnonBoxes::oofPaceholder() should go away and we shouldn't
   // even create ComputedStyle for placeholders.  However, not doing any rule
   // 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
   // was resolved, it is not stored in the DOM. (That is, the element remains
   // unstyled.)
   //
   // TODO(emilio): Element argument should be `const`.
   already_AddRefed<ComputedStyle> ResolveStyleLazily(
@@ -236,16 +214,21 @@ class ServoStyleSet {
   void AppendAllNonDocumentAuthorSheets(nsTArray<StyleSheet*>& aArray) const;
 
   void RemoveDocStyleSheet(StyleSheet* aSheet) {
     RemoveStyleSheet(StyleOrigin::Author, 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
    * document.
    *
    * This will traverse all of the document's style roots (that is, its document
    * element, and the roots of the document-level native anonymous content).
    *
    * We specify |ForCSSRuleChanges| to try to update all CSS animations
--- a/servo/components/selectors/builder.rs
+++ b/servo/components/selectors/builder.rs
@@ -79,16 +79,22 @@ impl<Impl: SelectorImpl> SelectorBuilder
     /// Completes the current compound selector and starts a new one, delimited
     /// by the given combinator.
     #[inline(always)]
     pub fn push_combinator(&mut self, c: Combinator) {
         self.combinators.push((c, self.current_len));
         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 {
         !self.combinators.is_empty()
     }
 
     /// Consumes the builder, producing a Selector.
     #[inline(always)]
--- a/servo/components/selectors/matching.rs
+++ b/servo/components/selectors/matching.rs
@@ -326,21 +326,20 @@ where
         if let Some(s) = iter.next() {
             debug_assert!(
                 matches!(*s, Component::NonTSPseudoClass(..)),
                 "Someone messed up pseudo-element parsing"
             );
             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;
         }
     }
 
     let result =
         matches_complex_selector_internal(iter, element, context, flags_setter, Rightmost::Yes);
 
     match result {
         SelectorMatchingResult::Matched => true,
@@ -462,23 +461,17 @@ where
                 .map_or(true, |s| s.is_html_slot_element()));
             let scope = context.current_host?;
             let mut current_slot = element.assigned_slot()?;
             while current_slot.containing_shadow_host().unwrap().opaque() != scope {
                 current_slot = current_slot.assigned_slot()?;
             }
             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(),
     }
 }
 
 fn matches_complex_selector_internal<E, F>(
     mut selector_iter: SelectorIter<E::Impl>,
     element: &E,
     context: &mut MatchingContext<E::Impl>,
     flags_setter: &mut F,
@@ -679,16 +672,17 @@ where
     debug_assert!(context.shared.is_nested() || !context.shared.in_negation());
 
     match *selector {
         Component::Combinator(_) => unreachable!(),
         Component::Part(ref part) => element.is_part(part),
         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)
                 })
         },
         Component::PseudoElement(ref pseudo) => {
             element.match_pseudo_element(pseudo, context.shared)
         },
         Component::LocalName(ref local_name) => matches_local_name(element, local_name),
--- a/servo/components/selectors/parser.rs
+++ b/servo/components/selectors/parser.rs
@@ -1993,25 +1993,29 @@ where
             },
             SimpleSelectorParseResult::PartPseudo(part_name) => {
                 state.insert(SelectorParsingState::AFTER_PART);
                 builder.push_combinator(Combinator::Part);
                 builder.push_simple_selector(Component::Part(part_name));
             },
             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) => {
                 state.insert(SelectorParsingState::AFTER_PSEUDO_ELEMENT);
                 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));
             },
         }
     }
     if empty {
         // An empty selector is invalid.
         Ok(None)
     } else {
@@ -2806,39 +2810,34 @@ pub mod tests {
                 }],
                 specificity(0, 1, 0),
             )]))
         );
         // https://github.com/mozilla/servo/issues/1723
         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,
             )]))
         );
         assert_eq!(
             parse("::before:hover"),
             Ok(SelectorList::from_vec(vec![Selector::from_vec(
                 vec![
-                    Component::Combinator(Combinator::PseudoElement),
                     Component::PseudoElement(PseudoElement::Before),
                     Component::NonTSPseudoClass(PseudoClass::Hover),
                 ],
                 specificity(0, 1, 1) | HAS_PSEUDO_BIT,
             )]))
         );
         assert_eq!(
             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),
                 ],
                 specificity(0, 2, 1) | HAS_PSEUDO_BIT,
             )]))
         );
         assert!(parse("::before:hover:lang(foo)").is_err());
@@ -2941,17 +2940,16 @@ pub mod tests {
                 vec![Component::Negation(
                     vec![Component::ExplicitUniversalType]
                         .into_boxed_slice()
                         .into(),
                 )],
                 specificity(0, 0, 0),
             )]))
         );
-
         assert_eq!(
             parse_ns(":not(svg|*)", &parser),
             Ok(SelectorList::from_vec(vec![Selector::from_vec(
                 vec![Component::Negation(
                     vec![
                         Component::Namespace(DummyAtom("svg".into()), SVG.into()),
                         Component::ExplicitUniversalType,
                     ]
@@ -3016,18 +3014,16 @@ pub mod tests {
         let selector = &parse("::before").unwrap().0[0];
         assert!(selector.is_universal());
         let mut iter = selector.iter();
         assert_eq!(
             iter.next(),
             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);
     }
 
     struct TestVisitor {
         seen: Vec<String>,
     }
 
     impl SelectorVisitor for TestVisitor {
--- a/servo/components/selectors/tree.rs
+++ b/servo/components/selectors/tree.rs
@@ -42,23 +42,19 @@ pub trait Element: Sized + Clone + Debug
     /// The host of the containing shadow root, if any.
     fn containing_shadow_host(&self) -> Option<Self>;
 
     /// The parent of a given pseudo-element, after matching a pseudo-element
     /// selector.
     ///
     /// 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>;
 
     /// Skips non-element nodes
     fn next_sibling_element(&self) -> Option<Self>;
 
     fn is_html_element_in_html_document(&self) -> bool;
 
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -774,17 +774,17 @@ pub trait TElement:
 
     /// Return the element which we can use to look up rules in the selector
     /// maps.
     ///
     /// This is always the element itself, except in the case where we are an
     /// 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 {
             *self
         }
     }
 
     /// Executes the callback for each applicable style rule data which isn't
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -1093,17 +1093,17 @@ impl structs::FontSizePrefs {
 }
 
 impl<'le> TElement for GeckoElement<'le> {
     type ConcreteNode = GeckoNode<'le>;
     type FontMetricsProvider = GeckoFontMetricsProvider;
     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();
         }
 
         self.as_node()
             .flattened_tree_parent()
             .and_then(|n| n.as_element())
     }
 
@@ -1466,17 +1466,17 @@ impl<'le> TElement for GeckoElement<'le>
                 true
             });
         }
     }
 
     #[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()
     }
 
     unsafe fn set_selector_flags(&self, flags: ElementSelectorFlags) {
         debug_assert!(!flags.is_empty());
         self.set_flags(selector_flags_to_node_flags(flags));
@@ -1914,23 +1914,18 @@ impl<'le> ::selectors::Element for Gecko
 
     #[inline]
     fn containing_shadow_host(&self) -> Option<Self> {
         let shadow = self.containing_shadow()?;
         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
         // pseudo-elements, which are nested NAC. Probably nsNumberControlFrame
         // should instead inherit from nsTextControlFrame, and then this could
         // go away.
         if let Some(PseudoElement::MozNumberText) = parent.implemented_pseudo_element() {
             debug_assert_eq!(
--- a/servo/components/style/invalidation/element/element_wrapper.rs
+++ b/servo/components/style/invalidation/element/element_wrapper.rs
@@ -361,20 +361,16 @@ where
     fn is_empty(&self) -> bool {
         self.element.is_empty()
     }
 
     fn is_root(&self) -> bool {
         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()
             .map(|e| ElementWrapper::new(e, self.snapshot_map))
     }
 
     fn assigned_slot(&self) -> Option<Self> {
         self.element
--- a/servo/components/style/style_adjuster.rs
+++ b/servo/components/style/style_adjuster.rs
@@ -729,17 +729,20 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
     /// When comparing to Gecko, this is similar to the work done by
     /// `ComputedStyle::ApplyStyleFixups`, plus some parts of
     /// `nsStyleSet::GetContext`.
     pub fn adjust<E>(&mut self, layout_parent_style: &ComputedValues, element: Option<E>)
     where
         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.
                 debug_assert!(self.style.pseudo.is_some(), "Someone really messed up");
             }
         }
         // FIXME(emilio): The apply_declarations callsite in Servo's
         // animation, and the font stuff for Gecko
--- a/servo/components/style/style_resolver.rs
+++ b/servo/components/style/style_resolver.rs
@@ -228,17 +228,17 @@ where
         &mut self,
         parent_style: Option<&ComputedValues>,
         layout_parent_style: Option<&ComputedValues>,
     ) -> ResolvedElementStyles {
         let primary_style = self.resolve_primary_style(parent_style, layout_parent_style);
 
         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 {
                 Some(primary_style.style())
             };
             SelectorImpl::each_eagerly_cascaded_pseudo_element(|pseudo| {
                 let pseudo_style = self.resolve_pseudo_style(
                     &pseudo,
@@ -288,16 +288,20 @@ where
 
     fn cascade_style_and_visited(
         &mut self,
         inputs: CascadeInputs,
         parent_style: Option<&ComputedValues>,
         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();
         let pseudo = pseudo.or(implemented_pseudo.as_ref());
 
         let mut conditions = Default::default();
         let values = self.context.shared.stylist.cascade_style_and_visited(
             Some(self.element),
@@ -468,18 +472,18 @@ where
         visited_handling: VisitedHandlingMode,
     ) -> Option<StrongRuleNode> {
         debug!(
             "Match pseudo {:?} for {:?}, visited: {:?}",
             self.element, pseudo_element, visited_handling
         );
         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();
 
         let stylist = &self.context.shared.stylist;
 
         if !self
             .element
deleted file mode 100644
--- a/testing/web-platform/tests/css/css-lists/nested-marker-content-ref.html
+++ /dev/null
@@ -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>
deleted file mode 100644
--- a/testing/web-platform/tests/css/css-lists/nested-marker-content.html
+++ /dev/null
@@ -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
deleted file mode 100644
--- a/testing/web-platform/tests/css/css-lists/nested-marker-dynamic.html
+++ /dev/null
@@ -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>
deleted file mode 100644
--- a/testing/web-platform/tests/css/css-lists/nested-marker-ref.html
+++ /dev/null
@@ -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>
deleted file mode 100644
--- a/testing/web-platform/tests/css/css-lists/nested-marker.html
+++ /dev/null
@@ -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