Bug 1541126 - Invalidate ShadowRoot style data when the document's compat mode changes. r=heycam
authorEmilio Cobos Álvarez <emilio@crisal.io>
Wed, 03 Apr 2019 23:52:19 +0000
changeset 467941 3fcf0136398320330aa0dddfaec1c34d63dad831
parent 467940 625e9335159cefd680bfd517ac7c3310b80a9bf8
child 467942 eaddff053db4dcbb5205e69bb8dbb78fc817c5ff
push id112667
push useraiakab@mozilla.com
push dateThu, 04 Apr 2019 16:12:45 +0000
treeherdermozilla-inbound@230bb363f2f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1541126
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1541126 - Invalidate ShadowRoot style data when the document's compat mode changes. r=heycam This testcase triggers a case which I hoped I wouldn't need to handle: The presence of a shadow root in the tree already by the time our compatibility mode changes. Just invalidate ShadowRoot data when this happens the same way we invalidate the document style data. Differential Revision: https://phabricator.services.mozilla.com/D25928
layout/style/ServoStyleSet.cpp
layout/style/crashtests/1541126.html
layout/style/crashtests/crashtests.list
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -237,16 +237,17 @@ RestyleHint ServoStyleSet::MediumFeature
     SetStylistStyleSheetsDirty();
   }
 
   if (result.mAffectsNonDocumentRules) {
     SetStylistXBLStyleSheetsDirty();
   }
 
   if (rulesChanged) {
+    // TODO(emilio): This could be more granular.
     return RestyleHint::RestyleSubtree();
   }
 
   const bool viewportChanged =
       bool(aReason & MediaFeatureChangeReason::ViewportChange);
   if (result.mUsesViewportUnits && viewportChanged) {
     return RestyleHint::RecascadeSubtree();
   }
@@ -928,41 +929,34 @@ void ServoStyleSet::StyleNewSubtree(Elem
 }
 
 void ServoStyleSet::MarkOriginsDirty(OriginFlags aChangedOrigins) {
   SetStylistStyleSheetsDirty();
   Servo_StyleSet_NoteStyleSheetsChanged(mRawSet.get(), aChangedOrigins);
 }
 
 void ServoStyleSet::SetStylistStyleSheetsDirty() {
-  // Note that there's another hidden mutator of mStylistState for XBL style
-  // sets in MediumFeaturesChanged...
-  //
-  // We really need to stop using a full-blown StyleSet there...
   mStylistState |= StylistState::StyleSheetsDirty;
 
   // We need to invalidate cached style in getComputedStyle for undisplayed
-  // elements, since we don't know if any of the style sheet change that we
-  // do would affect undisplayed elements.
+  // elements, since we don't know if any of the style sheet change that we do
+  // would affect undisplayed elements.
+  //
+  // We don't allow to call getComputedStyle in elements without a pres shell
+  // yet, so it is fine if there's no pres context here.
   if (nsPresContext* presContext = GetPresContext()) {
-    // XBL sheets don't have a pres context, but invalidating the restyle
-    // generation in that case is handled by SetXBLStyleSheetsDirty in the
-    // "master" stylist.
     presContext->RestyleManager()->IncrementUndisplayedRestyleGeneration();
   }
 }
 
 void ServoStyleSet::SetStylistXBLStyleSheetsDirty() {
   mStylistState |= StylistState::XBLStyleSheetsDirty;
-
-  // We need to invalidate cached style in getComputedStyle for undisplayed
-  // elements, since we don't know if any of the style sheet change that we
-  // do would affect undisplayed elements.
-  MOZ_ASSERT(GetPresContext());
-  GetPresContext()->RestyleManager()->IncrementUndisplayedRestyleGeneration();
+  if (nsPresContext* presContext = GetPresContext()) {
+    presContext->RestyleManager()->IncrementUndisplayedRestyleGeneration();
+  }
 }
 
 void ServoStyleSet::RuleAdded(StyleSheet& aSheet, css::Rule& aRule) {
   if (mStyleRuleMap) {
     mStyleRuleMap->RuleAdded(aSheet, aRule);
   }
 
   // FIXME(emilio): Could be more granular based on aRule.
@@ -1137,16 +1131,26 @@ bool ServoStyleSet::EnsureUniqueInnerOnC
 void ServoStyleSet::ClearCachedStyleData() {
   ClearNonInheritingComputedStyles();
   Servo_StyleSet_RebuildCachedData(mRawSet.get());
 }
 
 void ServoStyleSet::CompatibilityModeChanged() {
   Servo_StyleSet_CompatModeChanged(mRawSet.get());
   SetStylistStyleSheetsDirty();
+  bool anyShadow = false;
+  EnumerateShadowRoots(*mDocument, [&](ShadowRoot& aShadowRoot) {
+    if (auto* authorStyles = aShadowRoot.GetServoStyles()) {
+      anyShadow = true;
+      Servo_AuthorStyles_ForceDirty(authorStyles);
+    }
+  });
+  if (anyShadow) {
+    SetStylistXBLStyleSheetsDirty();
+  }
 }
 
 void ServoStyleSet::ClearNonInheritingComputedStyles() {
   for (RefPtr<ComputedStyle>& ptr : mNonInheritingComputedStyles) {
     ptr = nullptr;
   }
 }
 
new file mode 100644
--- /dev/null
+++ b/layout/style/crashtests/1541126.html
@@ -0,0 +1,20 @@
+<html class="reftest-wait">
+<script>
+function eh1() {
+  a.selectionEnd = 1
+}
+function eh2() {
+  var d = c.contentDocument.createRange()
+  d.cloneRange().insertNode(b)
+  requestAnimationFrame(() => {
+    requestAnimationFrame(() => {
+      document.documentElement.className = "";
+    });
+  });
+}
+</script>
+<textarea id="a" onselect="eh2()">
+</textarea>
+<video id="b" controls=""></video>
+<iframe id="c" srcdoc=""></iframe>
+<details ontoggle="eh1()" open="">
--- a/layout/style/crashtests/crashtests.list
+++ b/layout/style/crashtests/crashtests.list
@@ -296,8 +296,9 @@ load 1479681.html
 load 1488817.html
 load 1490012.html
 load 1502893.html
 load 1509989.html
 load 1514086.html
 pref(layout.css.moz-binding.content.enabled,false) load 1517319.html
 load 1533891.html
 load 1533783.html
+load 1541126.html