Bug 1147765 - Fix asynchronous initialization of Style Editor. r=ejpbruel
authorSami Jaktholm <sjakthol@outlook.com>
Thu, 26 Mar 2015 13:30:35 +0200
changeset 266522 60a108e6feb8c5df2d908cc265cd702b9f390d35
parent 266521 c21e67848c79a1520180558f5c6baabd9fad6867
child 266523 34fab46bd28ab9709ae68bc25af9690d0bd6da64
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersejpbruel
bugs1147765
milestone39.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 1147765 - Fix asynchronous initialization of Style Editor. r=ejpbruel
browser/devtools/styleeditor/StyleEditorUI.jsm
browser/devtools/styleeditor/styleeditor-panel.js
--- a/browser/devtools/styleeditor/StyleEditorUI.jsm
+++ b/browser/devtools/styleeditor/StyleEditorUI.jsm
@@ -110,44 +110,47 @@ StyleEditorUI.prototype = {
     return this.selectedEditor ?
            this.selectedEditor.styleSheet.styleSheetIndex : -1;
   },
 
   /**
    * Initiates the style editor ui creation, the inspector front to get
    * reference to the walker and the selector highlighter if available
    */
-  initialize: function() {
-    return Task.spawn(function*() {
-      let toolbox = gDevTools.getToolbox(this._target);
-      yield toolbox.initInspector();
-      this._walker = toolbox.walker;
+  initialize: Task.async(function* () {
+    yield this.initializeHighlighter();
+
+    this.createUI();
+
+    let styleSheets = yield this._debuggee.getStyleSheets();
+    yield this._resetStyleSheetList(styleSheets);
+
+    this._target.on("will-navigate", this._clear);
+    this._target.on("navigate", this._onNewDocument);
+  }),
 
-      let hUtils = toolbox.highlighterUtils;
-      if (hUtils.supportsCustomHighlighters()) {
-        try {
-          this._highlighter =
-            yield hUtils.getHighlighterByType(SELECTOR_HIGHLIGHTER_TYPE);
-        } catch (e) {
-          // The selectorHighlighter can't always be instantiated, for example
-          // it doesn't work with XUL windows (until bug 1094959 gets fixed);
-          // or the selectorHighlighter doesn't exist on the backend.
-          console.warn("The selectorHighlighter couldn't be instantiated, " +
-            "elements matching hovered selectors will not be highlighted");
-        }
+  initializeHighlighter: Task.async(function* () {
+    let toolbox = gDevTools.getToolbox(this._target);
+    yield toolbox.initInspector();
+    this._walker = toolbox.walker;
+
+    let hUtils = toolbox.highlighterUtils;
+    if (hUtils.supportsCustomHighlighters()) {
+      try {
+        this._highlighter =
+          yield hUtils.getHighlighterByType(SELECTOR_HIGHLIGHTER_TYPE);
+      } catch (e) {
+        // The selectorHighlighter can't always be instantiated, for example
+        // it doesn't work with XUL windows (until bug 1094959 gets fixed);
+        // or the selectorHighlighter doesn't exist on the backend.
+        console.warn("The selectorHighlighter couldn't be instantiated, " +
+          "elements matching hovered selectors will not be highlighted");
       }
-    }.bind(this)).then(() => {
-      this.createUI();
-      this._debuggee.getStyleSheets().then((styleSheets) => {
-        this._resetStyleSheetList(styleSheets); 
-        this._target.on("will-navigate", this._clear);
-        this._target.on("navigate", this._onNewDocument);
-      }, Cu.reportError);
-    });
-  },
+    }
+  }),
 
   /**
    * Build the initial UI and wire buttons with event handlers.
    */
   createUI: function() {
     let viewRoot = this._root.parentNode.querySelector(".splitview-root");
 
     this._view = new SplitView(viewRoot);
@@ -202,37 +205,37 @@ StyleEditorUI.prototype = {
    *
    * @param {string} event
    *        Event name
    * @param {StyleSheet} styleSheet
    *        StyleSheet object for new sheet
    */
   _onNewDocument: function() {
     this._debuggee.getStyleSheets().then((styleSheets) => {
-      this._resetStyleSheetList(styleSheets);
-    }, Cu.reportError);
+      return this._resetStyleSheetList(styleSheets);
+    }).then(null, Cu.reportError);
   },
 
   /**
    * Add editors for all the given stylesheets to the UI.
    *
    * @param  {array} styleSheets
    *         Array of StyleSheetFront
    */
-  _resetStyleSheetList: function(styleSheets) {
+  _resetStyleSheetList: Task.async(function* (styleSheets) {
     this._clear();
 
     for (let sheet of styleSheets) {
-      this._addStyleSheet(sheet);
+      yield this._addStyleSheet(sheet);
     }
 
     this._root.classList.remove("loading");
 
     this.emit("stylesheets-reset");
-  },
+  }),
 
   /**
    * Remove all editors and add loading indicator.
    */
   _clear: function() {
     // remember selected sheet and line number for next load
     if (this.selectedEditor && this.selectedEditor.sourceEditor) {
       let href = this.selectedEditor.styleSheet.href;
@@ -263,48 +266,50 @@ StyleEditorUI.prototype = {
 
   /**
    * Add an editor for this stylesheet. Add editors for its original sources
    * instead (e.g. Sass sources), if applicable.
    *
    * @param  {StyleSheetFront} styleSheet
    *         Style sheet to add to style editor
    */
-  _addStyleSheet: function(styleSheet) {
-    let editor = this._addStyleSheetEditor(styleSheet);
+  _addStyleSheet: Task.async(function* (styleSheet) {
+    let editor = yield this._addStyleSheetEditor(styleSheet);
 
     if (!Services.prefs.getBoolPref(PREF_ORIG_SOURCES)) {
       return;
     }
 
-    styleSheet.getOriginalSources().then((sources) => {
-      if (sources && sources.length) {
-        this._removeStyleSheetEditor(editor);
-        sources.forEach((source) => {
-          // set so the first sheet will be selected, even if it's a source
-          source.styleSheetIndex = styleSheet.styleSheetIndex;
-          source.relatedStyleSheet = styleSheet;
+    let sources = yield styleSheet.getOriginalSources();
+    if (sources && sources.length) {
+      this._removeStyleSheetEditor(editor);
 
-          this._addStyleSheetEditor(source);
-        });
+      for (let source of sources) {
+        // set so the first sheet will be selected, even if it's a source
+        source.styleSheetIndex = styleSheet.styleSheetIndex;
+        source.relatedStyleSheet = styleSheet;
+
+        yield this._addStyleSheetEditor(source);
       }
-    }, Cu.reportError);
-  },
+    }
+  }),
 
   /**
    * Add a new editor to the UI for a source.
    *
    * @param {StyleSheet}  styleSheet
    *        Object representing stylesheet
    * @param {nsIfile}  file
    *         Optional file object that sheet was imported from
    * @param {Boolean} isNew
    *         Optional if stylesheet is a new sheet created by user
+   * @return {Promise} that is resolved with the created StyleSheetEditor when
+   *                   the editor is fully initialized or rejected on error.
    */
-  _addStyleSheetEditor: function(styleSheet, file, isNew) {
+  _addStyleSheetEditor: Task.async(function* (styleSheet, file, isNew) {
     // recall location of saved file for this sheet after page reload
     let identifier = this.getStyleSheetIdentifier(styleSheet);
     let savedFile = this.savedLocations[identifier];
     if (savedFile && !file) {
       file = savedFile;
     }
 
     let editor = new StyleSheetEditor(styleSheet, this._window, file, isNew,
@@ -313,20 +318,21 @@ StyleEditorUI.prototype = {
     editor.on("property-change", this._summaryChange.bind(this, editor));
     editor.on("media-rules-changed", this._updateMediaList.bind(this, editor));
     editor.on("linked-css-file", this._summaryChange.bind(this, editor));
     editor.on("linked-css-file-error", this._summaryChange.bind(this, editor));
     editor.on("error", this._onError);
 
     this.editors.push(editor);
 
-    editor.fetchSource(this._sourceLoaded.bind(this, editor))
-          .then(null, Cu.reportError);
+    yield editor.fetchSource();
+    this._sourceLoaded(editor);
+
     return editor;
-  },
+  }),
 
   /**
    * Import a style sheet from file and asynchronously create a
    * new stylesheet on the debuggee for it.
    *
    * @param {mixed} file
    *        Optional nsIFile or filename string.
    *        If not set a file picker will be shown.
--- a/browser/devtools/styleeditor/styleeditor-panel.js
+++ b/browser/devtools/styleeditor/styleeditor-panel.js
@@ -38,49 +38,41 @@ exports.StyleEditorPanel = StyleEditorPa
 StyleEditorPanel.prototype = {
   get target() this._toolbox.target,
 
   get panelWindow() this._panelWin,
 
   /**
    * open is effectively an asynchronous constructor
    */
-  open: function() {
-    let deferred = promise.defer();
-
-    let targetPromise;
+  open: Task.async(function* () {
     // We always interact with the target as if it were remote
     if (!this.target.isRemote) {
-      targetPromise = this.target.makeRemote();
-    } else {
-      targetPromise = promise.resolve(this.target);
+      yield this.target.makeRemote();
     }
 
-    targetPromise.then(() => {
-      this.target.on("close", this.destroy);
+    this.target.on("close", this.destroy);
+
+    if (this.target.form.styleSheetsActor) {
+      this._debuggee = StyleSheetsFront(this.target.client, this.target.form);
+    }
+    else {
+      /* We're talking to a pre-Firefox 29 server-side */
+      this._debuggee = StyleEditorFront(this.target.client, this.target.form);
+    }
 
-      if (this.target.form.styleSheetsActor) {
-        this._debuggee = StyleSheetsFront(this.target.client, this.target.form);
-      }
-      else {
-        /* We're talking to a pre-Firefox 29 server-side */
-        this._debuggee = StyleEditorFront(this.target.client, this.target.form);
-      }
-      this.UI = new StyleEditorUI(this._debuggee, this.target, this._panelDoc);
-      this.UI.initialize().then(() => {
-        this.UI.on("error", this._showError);
+    // Initialize the UI
+    this.UI = new StyleEditorUI(this._debuggee, this.target, this._panelDoc);
+    yield this.UI.initialize();
 
-        this.isReady = true;
+    this.UI.on("error", this._showError);
+    this.isReady = true;
 
-        deferred.resolve(this);
-      });
-    }, console.error);
-
-    return deferred.promise;
-  },
+    return this;
+  }),
 
   /**
    * Show an error message from the style editor in the toolbox
    * notification box.
    *
    * @param  {string} event
    *         Type of event
    * @param  {string} data