Bug 1503896 - (Part 3) Extract CSS rule metadata to be reused with other logging methods; r=pbro
authorRazvan Caliman <rcaliman@mozilla.com>
Mon, 05 Nov 2018 09:23:43 +0000
changeset 444842 95ac332b63edbb9d3ea05f08b82c192aad35a1e8
parent 444841 33c358d0d2c2e10a9fd67c7a303ec2e2c9425a5e
child 444843 0a015306cf2b9d86f524036800ef95fc24bd335a
push id72515
push userrcaliman@mozilla.com
push dateWed, 07 Nov 2018 11:29:00 +0000
treeherderautoland@10a65f18e697 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1503896
milestone65.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 1503896 - (Part 3) Extract CSS rule metadata to be reused with other logging methods; r=pbro Depends on D10584 Other methods for tracking changes need to make use of the CSS rule metadata (selector, rule index, ancestors, etc). This extracts that logic into an accessor on the StyleRuleActor to facilitate reuse. The CSS rule metadata will be augmented with information about a CSS change (declarations added or removed) before being tracked. MozReview-Commit-ID: xXec1XgUhk Differential Revision: https://phabricator.services.mozilla.com/D10585
devtools/server/actors/styles.js
--- a/devtools/server/actors/styles.js
+++ b/devtools/server/actors/styles.js
@@ -1066,16 +1066,82 @@ var StyleRuleActor = protocol.ActorClass
     while (rule.parentRule) {
       ancestors.push(this.pageStyle._styleRef(rule.parentRule));
       rule = rule.parentRule;
     }
 
     return ancestors;
   },
 
+  /**
+   * Return an object with information about this rule used for tracking changes.
+   * It will be decorated with information about a CSS change before being tracked.
+   *
+   * It contains:
+   * - the rule selector (or generated selectror for inline styles)
+   * - the rule's host stylesheet (or element for inline styles)
+   * - the rule's ancestor rules (@media, @supports, @keyframes), if any
+   * - the rule's position within its ancestor tree, if any
+   *
+   * @return {Object}
+   */
+  get metadata() {
+    const data = {};
+    // Collect information about the rule's ancestors (@media, @supports, @keyframes).
+    // Used to show context for this change in the UI and to match the rule for undo/redo.
+    data.ancestors = this.ancestorRules.map(rule => {
+      return {
+        // Rule type as number defined by CSSRule.type (ex: 4, 7, 12)
+        // @see https://developer.mozilla.org/en-US/docs/Web/API/CSSRule
+        type: rule.rawRule.type,
+        // Rule type as human-readable string (ex: "@media", "@supports", "@keyframes")
+        typeName: CSSRuleTypeName[rule.rawRule.type],
+        // Conditions of @media and @supports rules (ex: "min-width: 1em")
+        conditionText: rule.rawRule.conditionText,
+        // Name of @keyframes rule; refrenced by the animation-name CSS property.
+        name: rule.rawRule.name,
+        // Selector of individual @keyframe rule within a @keyframes rule (ex: 0%, 100%).
+        keyText: rule.rawRule.keyText,
+        // Array with the indexes of this rule and its ancestors within the CSS rule tree.
+        ruleIndex: rule._ruleIndex,
+      };
+    });
+
+    // For changes in element style attributes, generate a unique selector.
+    if (this.type === ELEMENT_STYLE) {
+      // findCssSelector() fails on XUL documents. Catch and silently ignore that error.
+      try {
+        data.selector = findCssSelector(this.rawNode);
+      } catch (err) {}
+
+      data.source = {
+        type: "element",
+        // Used to differentiate between elements which match the same generated selector
+        // but live in different documents (ex: host document and iframe).
+        href: this.rawNode.baseURI,
+        // Element style attributes don't have a rule index; use the generated selector.
+        index: data.selector,
+      };
+      data.ruleIndex = 0;
+    } else {
+      data.selector = (this.type === CSSRule.KEYFRAME_RULE)
+        ? this.rawRule.keyText
+        : this.rawRule.selectorText;
+      data.source = {
+        type: "stylesheet",
+        href: this.sheetActor.href,
+        index: this.sheetActor.styleSheetIndex,
+      };
+      // Used to differentiate between changes to rules with identical selectors.
+      data.ruleIndex = this._ruleIndex;
+    }
+
+    return data;
+  },
+
   getDocument: function(sheet) {
     if (sheet.ownerNode) {
       return sheet.ownerNode.nodeType == sheet.ownerNode.DOCUMENT_NODE ?
              sheet.ownerNode : sheet.ownerNode.ownerDocument;
     } else if (sheet.parentStyleSheet) {
       return this.getDocument(sheet.parentStyleSheet);
     }
     throw (new Error("Failed trying to get the document of an invalid stylesheet"));
@@ -1498,66 +1564,17 @@ var StyleRuleActor = protocol.ActorClass
       commentOffsets,
     } = this._declarations[change.index] || {};
     // A declaration is disabled if it has a `commentOffsets` array.
     // Here we type coerce the value to a boolean with double-bang (!!)
     const prevDisabled = !!commentOffsets;
     // Append the "!important" string if defined in the previous priority flag.
     prevValue = (prevValue && prevPriority) ? `${prevValue} !important` : prevValue;
 
-    // Metadata about a change.
-    const data = {};
-    // Collect information about the rule's ancestors (@media, @supports, @keyframes).
-    // Used to show context for this change in the UI and to match the rule for undo/redo.
-    data.ancestors = this.ancestorRules.map(rule => {
-      return {
-        // Rule type as number defined by CSSRule.type (ex: 4, 7, 12)
-        // @see https://developer.mozilla.org/en-US/docs/Web/API/CSSRule
-        type: rule.rawRule.type,
-        // Rule type as human-readable string (ex: "@media", "@supports", "@keyframes")
-        typeName: CSSRuleTypeName[rule.rawRule.type],
-        // Conditions of @media and @supports rules (ex: "min-width: 1em")
-        conditionText: rule.rawRule.conditionText,
-        // Name of @keyframes rule; refrenced by the animation-name CSS property.
-        name: rule.rawRule.name,
-        // Selector of individual @keyframe rule within a @keyframes rule (ex: 0%, 100%).
-        keyText: rule.rawRule.keyText,
-        // Array with the indexes of this rule and its ancestors within the CSS rule tree.
-        ruleIndex: rule._ruleIndex,
-      };
-    });
-
-    // For changes in element style attributes, generate a unique selector.
-    if (this.type === ELEMENT_STYLE) {
-      // findCssSelector() fails on XUL documents. Catch and silently ignore that error.
-      try {
-        data.selector = findCssSelector(this.rawNode);
-      } catch (err) {}
-
-      data.source = {
-        type: "element",
-        // Used to differentiate between elements which match the same generated selector
-        // but live in different documents (ex: host document and iframe).
-        href: this.rawNode.baseURI,
-        // Element style attributes don't have a rule index; use the generated selector.
-        index: data.selector,
-      };
-      data.ruleIndex = 0;
-    } else {
-      data.selector = (this.type === CSSRule.KEYFRAME_RULE)
-        ? this.rawRule.keyText
-        : this.rawRule.selectorText;
-      data.source = {
-        type: "stylesheet",
-        href: this.sheetActor.href,
-        index: this.sheetActor.styleSheetIndex,
-      };
-      // Used to differentiate between changes to rules with identical selectors.
-      data.ruleIndex = this._ruleIndex;
-    }
+    const data = this.metadata;
 
     switch (change.type) {
       case "set":
         // If `change.newName` is defined, use it because the property is being renamed.
         // Otherwise, a new declaration is being created or the value of an existing
         // declaration is being updated. In that case, use the provided `change.name`.
         const name = change.newName ? change.newName : change.name;
         // Append the "!important" string if defined in the incoming priority flag.