Bug 1476908 - Show keyframes for elements in shadow dom;r=bgrins draft
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 20 Jul 2018 17:48:50 +0200
changeset 820875 e1f663dd2044fb642b0606ba2dc153b4f8e43172
parent 820805 8b9a6ec01fe671c59527a28cf8fc03057ef26c70
push id116973
push userjdescottes@mozilla.com
push dateFri, 20 Jul 2018 15:49:17 +0000
reviewersbgrins
bugs1476908
milestone63.0a1
Bug 1476908 - Show keyframes for elements in shadow dom;r=bgrins MozReview-Commit-ID: 6YJUnReL3PS
devtools/client/inspector/markup/test/head.js
devtools/client/inspector/rules/test/browser.ini
devtools/client/inspector/rules/test/browser_rules_keyframes-rule-shadowdom.js
devtools/client/shared/test/shared-head.js
devtools/server/actors/inspector/css-logic.js
devtools/server/actors/stylesheets.js
--- a/devtools/client/inspector/markup/test/head.js
+++ b/devtools/client/inspector/markup/test/head.js
@@ -553,24 +553,16 @@ async function checkDeleteAndSelection(i
 
   info("Undo the deletion to restore the original markup");
   await undoChange(inspector);
   node = await getNodeFront(selector, inspector);
   ok(node, "The node is back");
 }
 
 /**
- * Temporarily flip all the preferences needed to enable web components.
- */
-async function enableWebComponents() {
-  await pushPref("dom.webcomponents.shadowdom.enabled", true);
-  await pushPref("dom.webcomponents.customelements.enabled", true);
-}
-
-/**
  * Assert whether the provided container is slotted.
  */
 function assertContainerSlotted(container) {
   ok(container.isSlotted(), "Container is a slotted container");
   ok(container.elt.querySelector(".reveal-link"),
      "Slotted container has a reveal link element");
 }
 
--- a/devtools/client/inspector/rules/test/browser.ini
+++ b/devtools/client/inspector/rules/test/browser.ini
@@ -189,16 +189,17 @@ skip-if = (os == "win" && debug) # bug 9
 [browser_rules_inherited-properties_02.js]
 [browser_rules_inherited-properties_03.js]
 [browser_rules_inherited-properties_04.js]
 [browser_rules_inline-source-map.js]
 [browser_rules_inline-style-order.js]
 [browser_rules_invalid.js]
 [browser_rules_invalid-source-map.js]
 [browser_rules_keybindings.js]
+[browser_rules_keyframes-rule-shadowdom.js]
 [browser_rules_keyframes-rule_01.js]
 [browser_rules_keyframes-rule_02.js]
 [browser_rules_keyframeLineNumbers.js]
 [browser_rules_lineNumbers.js]
 [browser_rules_livepreview.js]
 [browser_rules_mark_overridden_01.js]
 [browser_rules_mark_overridden_02.js]
 [browser_rules_mark_overridden_03.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/rules/test/browser_rules_keyframes-rule-shadowdom.js
@@ -0,0 +1,77 @@
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test that keyframes are displayed for elements nested under a shadow-root.
+
+const TEST_URI = `data:text/html;charset=utf-8,
+  <div></div>
+  <script>
+    document.querySelector('div').attachShadow({mode: 'open'}).innerHTML = \`
+      <span>text</span>
+      <style>
+        @keyframes blink {
+          0% {
+            border: rgba(255,0,0,1) 2px dashed;
+          }
+          100% {
+            border: rgba(255,0,0,0) 2px dashed;
+          }
+        }
+        span {
+          animation: blink .5s 0s infinite;
+        }
+      </style>\`;
+  </script>`;
+
+add_task(async function() {
+  await enableWebComponents();
+
+  await addTab(TEST_URI);
+
+  const {inspector, view} = await openRuleView();
+
+  info("Expand the shadow-root parent");
+  const divFront = await getNodeFront("div", inspector);
+  await inspector.markup.expandNode(divFront);
+  await waitForMultipleChildrenUpdates(inspector);
+
+  const {markup} = inspector;
+  const divContainer = markup.getContainer(divFront);
+
+  info("Expand the shadow-root");
+  const shadowRootContainer = divContainer.getChildContainers()[0];
+  await expandContainer(inspector, shadowRootContainer);
+
+  info("Retrieve the rules displayed for the span under the shadow root");
+  const spanContainer = shadowRootContainer.getChildContainers()[0];
+  const rules = await getKeyframeRules(spanContainer.node, inspector, view);
+
+  is(convertTextPropsToString(rules.keyframeRules[0].textProps),
+    "border: rgba(255,0,0,1) 2px dashed",
+    "Keyframe blink (0%) property is correct"
+  );
+
+  is(convertTextPropsToString(rules.keyframeRules[1].textProps),
+    "border: rgba(255,0,0,0) 2px dashed",
+    "Keyframe blink (100%) property is correct"
+  );
+});
+
+function convertTextPropsToString(textProps) {
+  return textProps.map(t => t.name + ": " + t.value).join("; ");
+}
+
+async function getKeyframeRules(selector, inspector, view) {
+  await selectNode(selector, inspector);
+  const elementStyle = view._elementStyle;
+
+  const rules = {
+    elementRules: elementStyle.rules.filter(rule => !rule.keyframes),
+    keyframeRules: elementStyle.rules.filter(rule => rule.keyframes)
+  };
+
+  return rules;
+}
--- a/devtools/client/shared/test/shared-head.js
+++ b/devtools/client/shared/test/shared-head.js
@@ -717,8 +717,16 @@ async function injectEventUtilsInContent
       EventUtils.synthesizeMouseAtCenter(element,
         { type: "mouseup", isSynthesized: false }, content);
     });
 
     Services.scriptloader.loadSubScript(
       "chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
   });
 }
+
+/**
+ * Temporarily flip all the preferences needed to enable web components.
+ */
+async function enableWebComponents() {
+  await pushPref("dom.webcomponents.shadowdom.enabled", true);
+  await pushPref("dom.webcomponents.customelements.enabled", true);
+}
--- a/devtools/server/actors/inspector/css-logic.js
+++ b/devtools/server/actors/inspector/css-logic.js
@@ -221,18 +221,18 @@ CssLogic.prototype = {
    * Cache all the stylesheets in the inspected document
    * @private
    */
   _cacheSheets: function() {
     this._passId++;
     this.reset();
 
     // styleSheets isn't an array, but forEach can work on it anyway
-    Array.prototype.forEach.call(this.viewedDocument.styleSheets,
-        this._cacheSheet, this);
+    const styleSheets = InspectorUtils.getAllStyleSheets(this.viewedDocument, true);
+    Array.prototype.forEach.call(styleSheets, this._cacheSheet, this);
 
     this._sheetsCached = true;
   },
 
   /**
    * Cache a stylesheet if it falls within the requirements: if it's enabled,
    * and if the @media is allowed. This method also walks through the stylesheet
    * cssRules to find @imported rules, to cache the stylesheets of those rules
--- a/devtools/server/actors/stylesheets.js
+++ b/devtools/server/actors/stylesheets.js
@@ -316,18 +316,19 @@ var StyleSheetActor = protocol.ActorClas
 
   /**
    * Retrieve the index (order) of stylesheet in the document.
    *
    * @return number
    */
   get styleSheetIndex() {
     if (this._styleSheetIndex == -1) {
-      for (let i = 0; i < this.document.styleSheets.length; i++) {
-        if (this.document.styleSheets[i] == this.rawSheet) {
+      const styleSheets = InspectorUtils.getAllStyleSheets(this.document, true);
+      for (let i = 0; i < styleSheets.length; i++) {
+        if (styleSheets[i] == this.rawSheet) {
           this._styleSheetIndex = i;
           break;
         }
       }
     }
     return this._styleSheetIndex;
   },