Bug 1402442: Properly remove display: contents pseudo-frames. r=mats
authorEmilio Cobos Álvarez <emilio@crisal.io>
Mon, 25 Sep 2017 18:25:29 +0200
changeset 435598 faa69ac1c14b79838cc0aac842b470a110542ebd
parent 435597 959244bbe99d26f84cb516bb12ca43060c3298c6
child 435599 b8f4938f37d9a2ac2aadeec28fd45bbf12362234
push id8114
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 16:33:21 +0000
treeherdermozilla-beta@73e0d89a540f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs1402442
milestone58.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 1402442: Properly remove display: contents pseudo-frames. r=mats MozReview-Commit-ID: 4pjVLQfv3YR Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
layout/base/nsCSSFrameConstructor.cpp
testing/web-platform/meta/MANIFEST.json
testing/web-platform/meta/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html.ini
testing/web-platform/tests/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001-ref.html
testing/web-platform/tests/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1693,16 +1693,27 @@ nsCSSFrameConstructor::NotifyDestroyingF
     CountersDirty();
   }
 
   RestyleManager()->NotifyDestroyingFrame(aFrame);
 
   nsFrameManager::NotifyDestroyingFrame(aFrame);
 }
 
+static bool
+HasGeneratedContent(const nsIContent* aChild)
+{
+  if (!aChild->MayHaveAnonymousChildren()) {
+    return false;
+  }
+
+  return nsLayoutUtils::GetBeforeFrame(aChild) ||
+         nsLayoutUtils::GetAfterFrame(aChild);
+}
+
 struct nsGenConInitializer {
   nsAutoPtr<nsGenConNode> mNode;
   nsGenConList*           mList;
   void (nsCSSFrameConstructor::*mDirtyAll)();
 
   nsGenConInitializer(nsGenConNode* aNode, nsGenConList* aList,
                       void (nsCSSFrameConstructor::*aDirtyAll)())
     : mNode(aNode), mList(aList), mDirtyAll(aDirtyAll) {}
@@ -8677,25 +8688,24 @@ nsCSSFrameConstructor::ContentRemoved(ns
   if (!childFrame || childFrame->GetContent() != aChild) {
     // XXXbz the GetContent() != aChild check is needed due to bug 135040.
     // Remove it once that's fixed.
     UnregisterDisplayNoneStyleFor(aChild, aContainer);
   }
   MOZ_ASSERT(!childFrame || !GetDisplayContentsStyleFor(aChild),
              "display:contents nodes shouldn't have a frame");
   if (!childFrame && GetDisplayContentsStyleFor(aChild)) {
-    nsIContent* ancestor = aChild->GetFlattenedTreeParent();
-    MOZ_ASSERT(ancestor, "display: contents on the root?");
-    while (!ancestor->GetPrimaryFrame()) {
-      ancestor = ancestor->GetFlattenedTreeParent();
-      MOZ_ASSERT(ancestor, "we can't have a display: contents subtree root!");
-    }
-
-    nsIFrame* ancestorFrame = ancestor->GetPrimaryFrame();
-    if (ancestorFrame->GetProperty(nsIFrame::GenConProperty())) {
+    if (HasGeneratedContent(aChild)) {
+      nsIContent* ancestor = aChild->GetFlattenedTreeParent();
+      MOZ_ASSERT(ancestor, "display: contents on the root?");
+      while (!ancestor->GetPrimaryFrame()) {
+        ancestor = ancestor->GetFlattenedTreeParent();
+        MOZ_ASSERT(ancestor, "we can't have a display: contents subtree root!");
+      }
+
       // XXXmats Can we recreate frames only for the ::after/::before content?
       // XXX Perhaps even only those that belong to the aChild sub-tree?
       LAYOUT_PHASE_TEMP_EXIT();
       RecreateFramesForContent(ancestor, InsertionKind::Async);
       LAYOUT_PHASE_TEMP_REENTER();
       return true;
     }
 
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -104104,16 +104104,28 @@
       [
        "/css/css-display-3/display-contents-flex-002-ref.html",
        "=="
       ]
      ],
      {}
     ]
    ],
+   "css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html": [
+    [
+     "/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html",
+     [
+      [
+       "/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001-ref.html",
+       "=="
+      ]
+     ],
+     {}
+    ]
+   ],
    "css/css-display-3/display-contents-dynamic-inline-flex-001-inline.html": [
     [
      "/css/css-display-3/display-contents-dynamic-inline-flex-001-inline.html",
      [
       [
        "/css/css-display-3/display-contents-inline-flex-001-ref.html",
        "=="
       ]
@@ -229218,16 +229230,21 @@
      {}
     ]
    ],
    "css/css-display-3/display-contents-block-002-ref.html": [
     [
      {}
     ]
    ],
+   "css/css-display-3/display-contents-dynamic-generated-content-fieldset-001-ref.html": [
+    [
+     {}
+    ]
+   ],
    "css/css-display-3/display-contents-flex-001-ref.html": [
     [
      {}
     ]
    ],
    "css/css-display-3/display-contents-flex-002-ref.html": [
     [
      {}
@@ -505751,16 +505768,24 @@
   "css/css-display-3/display-contents-dynamic-flex-003-inline.html": [
    "82c3af46cd3b5e7388df0d2b5f169ac3a454efe6",
    "reftest"
   ],
   "css/css-display-3/display-contents-dynamic-flex-003-none.html": [
    "a2d7c9368ed8c01ca06c36646666270e85aee070",
    "reftest"
   ],
+  "css/css-display-3/display-contents-dynamic-generated-content-fieldset-001-ref.html": [
+   "30ec5c8ddacfbfef8434c37ca7a0a766f2bbc89a",
+   "support"
+  ],
+  "css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html": [
+   "0be8853e66cd7c447725d681a1703a2ad85d8924",
+   "reftest"
+  ],
   "css/css-display-3/display-contents-dynamic-inline-flex-001-inline.html": [
    "40fb07e8ada1530e6835ff2d4e49c5571ffb0baa",
    "reftest"
   ],
   "css/css-display-3/display-contents-dynamic-inline-flex-001-none.html": [
    "40fb07e8ada1530e6835ff2d4e49c5571ffb0baa",
    "reftest"
   ],
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/meta/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html.ini
@@ -0,0 +1,4 @@
+[display-contents-dynamic-generated-content-fieldset-001.html]
+  type: reftest
+  expected:
+    if not stylo: FAIL
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001-ref.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Reftest Reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<style>
+div {
+  display: contents;
+  border: 10px solid red;
+}
+</style>
+<p>
+  Test passes if there is no red text and no red border.
+</p>
+<fieldset>
+  <div></div>
+</fieldset>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/css-display-3/display-contents-dynamic-generated-content-fieldset-001.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>CSS Test: Dynamic changes to display: contents generated content in fieldsets.</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://drafts.csswg.org/css-display-3/#valdef-display-contents">
+<link rel="match" href="display-contents-dynamic-generated-content-fieldset-001-ref.html">
+<style>
+.after::after {
+  content: "FAIL";
+  color: red;
+}
+div {
+  display: contents;
+  border: 10px solid red;
+}
+</style>
+<p>
+  Test passes if there is no red text and no red border.
+</p>
+<fieldset>
+  <div class="after"></div>
+</fieldset>
+<script>
+document.body.offsetHeight;
+document.querySelector("div").classList.remove("after");
+</script>