Bug 1243736 - Enable browser_rules_content_02.js with e10s and make rule-view wait for updateSourceLink; r=bgrins draft
authorPatrick Brosset <pbrosset@mozilla.com>
Thu, 28 Jan 2016 15:39:13 +0100
changeset 326887 d0b8b9168c42274b3e2958cbcb4b28dfcb5fb427
parent 326715 f01c61b2c49270a44aa4d53c011c9b9f74447988
child 326889 22c5e9d7b0dd678607e3d63846d36b1aff1ecc63
push id10175
push userpbrosset@mozilla.com
push dateThu, 28 Jan 2016 14:39:41 +0000
reviewersbgrins
bugs1243736
milestone47.0a1
Bug 1243736 - Enable browser_rules_content_02.js with e10s and make rule-view wait for updateSourceLink; r=bgrins
devtools/client/inspector/rules/rules.js
devtools/client/inspector/rules/test/browser.ini
devtools/client/inspector/rules/test/browser_rules_pseudo-element_02.js
devtools/client/inspector/rules/views/rule-editor.js
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -957,22 +957,23 @@ CssRuleView.prototype = {
   _populate: function() {
     let elementStyle = this._elementStyle;
     return this._elementStyle.populate().then(() => {
       if (this._elementStyle !== elementStyle || this.isDestroyed) {
         return;
       }
 
       this._clearRules();
-      this._createEditors();
-
+      let onEditorsReady = this._createEditors();
       this.refreshPseudoClassPanel();
 
       // Notify anyone that cares that we refreshed.
-      this.emit("ruleview-refreshed");
+      return onEditorsReady.then(() => {
+        this.emit("ruleview-refreshed");
+      }, e => console.error(e));
     }).then(null, promiseWarn);
   },
 
   /**
    * Show the user that the rule view has no node selected.
    */
   _showEmpty: function() {
     if (this.styleDocument.getElementById("noResults") > 0) {
@@ -1142,27 +1143,31 @@ CssRuleView.prototype = {
     let lastInheritedSource = "";
     let lastKeyframes = null;
     let seenPseudoElement = false;
     let seenNormalElement = false;
     let seenSearchTerm = false;
     let container = null;
 
     if (!this._elementStyle.rules) {
-      return;
+      return promise.resolve();
     }
 
+    let editorReadyPromises = [];
     for (let rule of this._elementStyle.rules) {
       if (rule.domRule.system) {
         continue;
       }
 
       // Initialize rule editor
       if (!rule.editor) {
         rule.editor = new RuleEditor(this, rule);
+        let onEditorReady = promise.defer();
+        rule.editor.once("source-link-updated", onEditorReady.resolve);
+        editorReadyPromises.push(onEditorReady.promise);
       }
 
       // Filter the rules and highlight any matches if there is a search input
       if (this.searchValue && this.searchData) {
         if (this.highlightRule(rule)) {
           seenSearchTerm = true;
         } else if (rule.domRule.type !== ELEMENT_STYLE) {
           continue;
@@ -1206,16 +1211,18 @@ CssRuleView.prototype = {
       }
     }
 
     if (this.searchValue && !seenSearchTerm) {
       this.searchField.classList.add("devtools-style-searchbox-no-match");
     } else {
       this.searchField.classList.remove("devtools-style-searchbox-no-match");
     }
+
+    return promise.all(editorReadyPromises);
   },
 
   /**
    * Highlight rules that matches the filter search value and returns a
    * boolean indicating whether or not rules were highlighted.
    *
    * @param  {Rule} rule
    *         The rule object we're highlighting if its rule selectors or
--- a/devtools/client/inspector/rules/test/browser.ini
+++ b/devtools/client/inspector/rules/test/browser.ini
@@ -132,17 +132,16 @@ skip-if = (os == "win" && debug) || e10s
 [browser_rules_multiple-properties-priority.js]
 [browser_rules_multiple-properties-unfinished_01.js]
 [browser_rules_multiple-properties-unfinished_02.js]
 [browser_rules_multiple_properties_01.js]
 [browser_rules_multiple_properties_02.js]
 [browser_rules_original-source-link.js]
 [browser_rules_pseudo-element_01.js]
 [browser_rules_pseudo-element_02.js]
-skip-if = e10s # Bug 1090340
 [browser_rules_pseudo_lock_options.js]
 [browser_rules_refresh-no-flicker.js]
 [browser_rules_refresh-on-attribute-change_01.js]
 [browser_rules_refresh-on-attribute-change_02.js]
 [browser_rules_refresh-on-style-change.js]
 [browser_rules_search-filter-computed-list_01.js]
 [browser_rules_search-filter-computed-list_02.js]
 [browser_rules_search-filter-computed-list_03.js]
--- a/devtools/client/inspector/rules/test/browser_rules_pseudo-element_02.js
+++ b/devtools/client/inspector/rules/test/browser_rules_pseudo-element_02.js
@@ -6,28 +6,24 @@
 
 // Test that pseudoelements are displayed correctly in the rule view
 
 const TEST_URI = URL_ROOT + "doc_pseudoelement.html";
 
 add_task(function*() {
   yield addTab(TEST_URI);
   let {inspector} = yield openRuleView();
-  yield testTopLeft(inspector);
-});
 
-function* testTopLeft(inspector) {
-  let node = inspector.markup.walker.frontForRawNode(getNode("#topleft"));
+  let node = yield getNodeFront("#topleft", inspector);
   let children = yield inspector.markup.walker.children(node);
 
   is(children.nodes.length, 3, "Element has correct number of children");
 
   let beforeElement = children.nodes[0];
   is(beforeElement.tagName, "_moz_generated_content_before",
     "tag name is correct");
   yield selectNode(beforeElement, inspector);
 
   let afterElement = children.nodes[children.nodes.length - 1];
   is(afterElement.tagName, "_moz_generated_content_after",
     "tag name is correct");
   yield selectNode(afterElement, inspector);
-}
-
+});
--- a/devtools/client/inspector/rules/views/rule-editor.js
+++ b/devtools/client/inspector/rules/views/rule-editor.js
@@ -20,37 +20,49 @@ const {
 } = require("devtools/client/inspector/shared/utils");
 const {
   parseDeclarations,
   parsePseudoClassesAndAttributes,
   SELECTOR_ATTRIBUTE,
   SELECTOR_ELEMENT,
   SELECTOR_PSEUDO_CLASS
 } = require("devtools/client/shared/css-parsing-utils");
+const promise = require("promise");
+
+loader.lazyRequireGetter(this, "EventEmitter",
+  "devtools/shared/event-emitter");
 
 XPCOMUtils.defineLazyGetter(this, "_strings", function() {
   return Services.strings.createBundle(
     "chrome://devtools-shared/locale/styleinspector.properties");
 });
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 /**
  * RuleEditor is responsible for the following:
  *   Owns a Rule object and creates a list of TextPropertyEditors
  *     for its TextProperties.
  *   Manages creation of new text properties.
  *
+ * One step of a RuleEditor's instantiation is figuring out what's the original
+ * source link to the parent stylesheet (in case of source maps). This step is
+ * asynchronous and is triggered as soon as the RuleEditor is instantiated (see
+ * updateSourceLink). If you need to know when the RuleEditor is done with this,
+ * you need to listen to the source-link-updated event.
+ *
  * @param {CssRuleView} ruleView
  *        The CssRuleView containg the document holding this rule editor.
  * @param {Rule} rule
  *        The Rule object we're editing.
  */
 function RuleEditor(ruleView, rule) {
+  EventEmitter.decorate(this);
+
   this.ruleView = ruleView;
   this.doc = this.ruleView.styleDocument;
   this.rule = rule;
 
   this.isEditable = !rule.isSystem;
   // Flag that blocks updates of the selector and properties when it is
   // being edited
   this.isEditing = false;
@@ -219,20 +231,31 @@ RuleEditor.prototype = {
       if (this.rule.ruleLine === -1 && this.rule.domRule.parentStyleSheet) {
         sourceLabel.parentNode.setAttribute("unselectable", "true");
       }
     }
 
     let showOrig = Services.prefs.getBoolPref(PREF_ORIG_SOURCES);
     if (showOrig && !this.rule.isSystem &&
         this.rule.domRule.type !== ELEMENT_STYLE) {
+      // Only get the original source link if the right pref is set, if the rule
+      // isn't a system rule and if it isn't an inline rule.
       this.rule.getOriginalSourceStrings().then((strings) => {
         sourceLabel.setAttribute("value", strings.short);
         sourceLabel.setAttribute("tooltiptext", strings.full);
-      }, console.error);
+      }, e => console.error(e)).then(() => {
+        this.emit("source-link-updated");
+      });
+    } else {
+      // If we're not getting the original source link, then we can emit the
+      // event immediately (but still asynchronously to give consumers a chance
+      // to register it after having instantiated the RuleEditor).
+      promise.resolve().then(() => {
+        this.emit("source-link-updated");
+      });
     }
   },
 
   /**
    * Update the rule editor with the contents of the rule.
    */
   populate: function() {
     // Clear out existing viewers.