Bug 1451940: Don't reparse stylesheets when assigning empty string to empty element. r?bz draft
authorKris Maglione <maglione.k@gmail.com>
Sun, 08 Apr 2018 14:24:51 -0700
changeset 779053 a985182e55b3de9ead3e162a2ed6e14bfb08431e
parent 778959 a51eff8c27bfe75861ffe0d9c296367114eb9b4e
push id105644
push usermaglione.k@gmail.com
push dateSun, 08 Apr 2018 21:25:58 +0000
reviewersbz
bugs1451940
milestone61.0a1
Bug 1451940: Don't reparse stylesheets when assigning empty string to empty element. r?bz Per spec, assinging an empty string to textContent or innerHTML should not trigger any mutation observers, and therefore should not trigger a stylesheet reparse, when the element is already empty. Since we need to apply some special handling to innerHTML and textContent assignments to <style> nodes, and therefore re-parse directly in the setter rather than in response to mutation observers, we need to special-case this scenario. MozReview-Commit-ID: KdOYFs8ayT7
dom/html/HTMLStyleElement.cpp
testing/web-platform/meta/MANIFEST.json
testing/web-platform/tests/css/cssom/css-style-reparse.html
--- a/dom/html/HTMLStyleElement.cpp
+++ b/dom/html/HTMLStyleElement.cpp
@@ -168,16 +168,26 @@ HTMLStyleElement::SetInnerHTML(const nsA
   SetTextContentInternal(aInnerHTML, aScriptedPrincipal, aError);
 }
 
 void
 HTMLStyleElement::SetTextContentInternal(const nsAString& aTextContent,
                                          nsIPrincipal* aScriptedPrincipal,
                                          ErrorResult& aError)
 {
+  // Per spec, if we're setting text content to an empty string and don't
+  // already have any children, we should not trigger any mutation observers, or
+  // re-parse the stylesheet.
+  if (aTextContent.IsEmpty() && !GetChildCount()) {
+    nsIPrincipal* principal = mTriggeringPrincipal ? mTriggeringPrincipal.get() : NodePrincipal();
+    if (principal == aScriptedPrincipal) {
+      return;
+    }
+  }
+
   SetEnableUpdates(false);
 
   aError = nsContentUtils::SetNodeTextContent(this, aTextContent, true);
 
   SetEnableUpdates(true);
 
   mTriggeringPrincipal = aScriptedPrincipal;
 
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -318107,16 +318107,22 @@
     ]
    ],
    "css/cssom/css-style-declaration-modifications.html": [
     [
      "/css/cssom/css-style-declaration-modifications.html",
      {}
     ]
    ],
+   "css/cssom/css-style-reparse.html": [
+    [
+     "/css/cssom/css-style-reparse.html",
+     {}
+    ]
+   ],
    "css/cssom/cssimportrule.html": [
     [
      "/css/cssom/cssimportrule.html",
      {}
     ]
    ],
    "css/cssom/cssom-cssText-serialize.html": [
     [
@@ -481413,17 +481419,17 @@
    "f5f4f2279506dc6106de38080a639979ad7e05d0",
    "testharness"
   ],
   "css/css-align/content-distribution/place-content-shorthand-003.html": [
    "966e8dd3893c487b02bb139ac26862995b655603",
    "testharness"
   ],
   "css/css-align/content-distribution/place-content-shorthand-004.html": [
-   "e755317eedc580d6373df24596590d22fc9aad5d",
+   "52566e7e88edf9f57f441498b9d366b66be50fd7",
    "testharness"
   ],
   "css/css-align/content-distribution/place-content-shorthand-005.html": [
    "6b3d7b9ae7d5b28510385cccaaade09268409cab",
    "testharness"
   ],
   "css/css-align/content-distribution/place-content-shorthand-006.html": [
    "a40c054505716dda72b642ada40d8796a5d68795",
@@ -481505,17 +481511,17 @@
    "638f5cbcc320477d495b9b0a752e6aaa048fee5e",
    "testharness"
   ],
   "css/css-align/default-alignment/place-items-shorthand-006.html": [
    "b7106d0ee863673c0d9a6160d035706edb3c67a8",
    "testharness"
   ],
   "css/css-align/default-alignment/shorthand-serialization-001.html": [
-   "0126d0a56ec9af324a886d286563cf8f39fc1b78",
+   "6c85da43be475b680d5351bdb969d09b90a6d97e",
    "testharness"
   ],
   "css/css-align/distribution-values/space-evenly-001.html": [
    "6fd28a5bf615ce822ed935de90ce5c1a41d39104",
    "reftest"
   ],
   "css/css-align/gaps/column-gap-animation-001.html": [
    "00023e39b6fafbfb31cabb30ed4ddf77a71b248f",
@@ -481637,17 +481643,17 @@
    "a266e09207859b058f445acb7c472156e525dd21",
    "testharness"
   ],
   "css/css-align/self-alignment/place-self-shorthand-003.html": [
    "2f17a907183eee3c3383894212f7d3d84770db2d",
    "testharness"
   ],
   "css/css-align/self-alignment/place-self-shorthand-004.html": [
-   "4f153c62e5d1eecf9eb4678036123d0460d7ecf1",
+   "2259cbd38befc9cf4fcb3e7a567fe3197740f613",
    "testharness"
   ],
   "css/css-align/self-alignment/place-self-shorthand-005.html": [
    "5a11a37355d05683ac1adbf1a5f6e1d0f5c88863",
    "testharness"
   ],
   "css/css-align/self-alignment/place-self-shorthand-006.html": [
    "d355eac038a7307e7a969632bc745ad25d8d6f43",
@@ -506933,45 +506939,45 @@
    "7338abdd6edb1027dc2e12b001773ce5ad114286",
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-004.html": [
    "1e5377c120916557dc1525b38c9cf7eb86ae0151",
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-005.html": [
-   "dfbf4ad61f18ad05e243e58a2458b5b776ecf3fb",
+   "7d6563a162ba640b77801c5c8280078d4b087649",
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-006.html": [
-   "da35426f9ffc53101a053a61512c6928d140adff",
+   "72267d3bfbdbeb438f32266334bb5e4a9c91c1bf",
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-007.html": [
-   "03752707f61fbf16290b9733c280b79e00440b96",
+   "c1093645f439fc86272e7e5f71e62daf37240a3f",
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-008.html": [
-   "2ce6445aed0987c0ab7b83f614e9ceb8186fff7b",
+   "2f2b95904fad670919fae32cb94284118a45566c",
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-001.html": [
    "b13df2df3be12ac74a7933794d91558c416b412c",
    "testharness"
   ],
   "css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-002.html": [
    "dbe8bd280e7f65fc5a1b43f4a211ca8e08a20d5e",
    "testharness"
   ],
   "css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-003.html": [
    "80fd9390054506c5e7bd8a6e60c1e6156dd604ec",
    "testharness"
   ],
   "css/css-shapes/shape-outside/shape-image/gradients/shape-outside-radial-gradient-004.html": [
-   "fc47f277737dce4f7c6b08d0181355a810107c7b",
+   "67c3b8ea983da6b7d9b6b7e252b6415ebc7d1f9d",
    "testharness"
   ],
   "css/css-shapes/shape-outside/shape-image/reference/shape-image-000-ref.html": [
    "535d72bd77ac04e8e1accaa36edc6077baed17f3",
    "support"
   ],
   "css/css-shapes/shape-outside/shape-image/reference/shape-image-001-ref.html": [
    "5f5ed24372bdb45721dcb3befac0e5a0d3bb4091",
@@ -507133,17 +507139,17 @@
    "a68bf761c1ee6ab00432036b773b70ae6ba7b7c0",
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/shape-image-025.html": [
    "c20645a47561cfa655b759d20f52d22536776893",
    "reftest"
   ],
   "css/css-shapes/shape-outside/shape-image/support/animated.gif": [
-   "d7fa8b47fef48732b1e01143a714409443ff307f",
+   "c5252926d8dbf82c06cdb615fda708ca7728f0bb",
    "support"
   ],
   "css/css-shapes/shape-outside/shape-image/support/left-half-rectangle-20.png": [
    "d366673197353a2b32aee7befa9bab425d4a7be1",
    "support"
   ],
   "css/css-shapes/shape-outside/shape-image/support/left-half-rectangle-20.svg": [
    "3cdddaa71eb80bd275c01470bc7e85694b0d5c98",
@@ -531628,16 +531634,20 @@
   "css/cssom/css-style-attribute-modifications.html": [
    "9199534f3b6cc473832562b1701ade3a05dde172",
    "testharness"
   ],
   "css/cssom/css-style-declaration-modifications.html": [
    "c169d758c1d91b75697b04cf72750f8ac1650e1a",
    "testharness"
   ],
+  "css/cssom/css-style-reparse.html": [
+   "478157c15100d0f0eb164d2579b10e47a770ea46",
+   "testharness"
+  ],
   "css/cssom/cssimportrule.html": [
    "c7a70c7836b5a31631b12cc47f280d507542571d",
    "testharness"
   ],
   "css/cssom/cssom-cssText-serialize.html": [
    "66ad91da39c1e1da9021f6443e9b6d34baf57dcb",
    "testharness"
   ],
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/css/cssom/css-style-reparse.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<html>
+<head>
+  <meta charset=utf-8>
+  <title>CSS Test: DOM modification re-parsing test</title>
+  <link rel="help" href="https://drafts.csswg.org/cssom/">
+  <link rel="help" href="http://www.w3.org/TR/cssom-1/#the-cssrule-interface">
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <style>div { min-width: 0px; }</style>
+  <style id="style-element"></style>
+</head>
+<body>
+<div id="test-div"></div>
+<script type="text/javascript">
+    var style = document.getElementById("style-element");
+    var div = document.getElementById("test-div");
+
+    function testProperty(prop) {
+      // Assigning an empty string to textContent or innerHTML should trigger a
+      // reparse only if the element is not empty.
+      style.sheet.insertRule("#test-div { min-width: 42px; }");
+      assert_equals(getComputedStyle(div).minWidth, "42px");
+
+      style[prop] = "";
+      assert_equals(getComputedStyle(div).minWidth, "42px");
+
+      style[prop] = " ";
+      assert_equals(getComputedStyle(div).minWidth, "0px");
+
+      style.sheet.insertRule("#test-div { min-width: 42px; }");
+      assert_equals(getComputedStyle(div).minWidth, "42px");
+
+      style[prop] = "";
+      assert_equals(getComputedStyle(div).minWidth, "0px");
+    }
+
+    test(function() {
+      testProperty("textContent");
+    }, "style.textContent modification");
+
+    test(function() {
+      testProperty("innerHTML");
+    }, "style.innerHTML modification");
+</script>
+</body>
+</html>