Bug 1240183 - make styleeditor eslint-clean; r=pbro
authorTom Tromey <tom@tromey.com>
Fri, 15 Jan 2016 08:34:45 -0700
changeset 305321 7428a32a3346e6b055c53dee61e23d6d30e7326b
parent 305320 6a96995d887a74d4fb867d6da5cd7382679effc6
child 305322 ccbe2dff012aa388153990e0a3e9c1323663270a
push id9214
push userraliiev@mozilla.com
push dateMon, 07 Mar 2016 14:25:21 +0000
treeherdermozilla-aurora@8849dd1a4a79 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1240183
milestone47.0a1
Bug 1240183 - make styleeditor eslint-clean; r=pbro
.eslintignore
devtools/client/styleeditor/StyleEditorUI.jsm
devtools/client/styleeditor/StyleEditorUtil.jsm
devtools/client/styleeditor/StyleSheetEditor.jsm
devtools/client/styleeditor/styleeditor-commands.js
devtools/client/styleeditor/styleeditor-panel.js
devtools/client/styleeditor/test/browser.ini
devtools/client/styleeditor/test/browser_styleeditor_cmd_edit.html
devtools/client/styleeditor/test/browser_styleeditor_cmd_edit.js
devtools/client/styleeditor/test/browser_styleeditor_media_sidebar.js
devtools/client/styleeditor/test/browser_styleeditor_media_sidebar_links.js
devtools/client/styleeditor/test/browser_styleeditor_new.js
devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js
devtools/client/styleeditor/test/browser_styleeditor_sourcemaps.js
devtools/client/styleeditor/test/browser_styleeditor_sync.js
devtools/client/styleeditor/test/browser_styleeditor_syncAddRule.js
devtools/client/styleeditor/test/browser_styleeditor_syncAlreadyOpen.js
devtools/client/styleeditor/test/browser_styleeditor_syncEditSelector.js
devtools/client/styleeditor/test/browser_styleeditor_syncIntoRuleView.js
devtools/client/styleeditor/test/browser_styleeditor_transition_rule.js
devtools/client/styleeditor/test/browser_styleeditor_xul.js
devtools/client/styleeditor/test/doc_frame_script.js
devtools/client/styleeditor/test/head.js
devtools/client/styleeditor/test/longload.html
devtools/client/styleeditor/utils.js
testing/mochitest/browser.eslintrc
--- a/.eslintignore
+++ b/.eslintignore
@@ -107,17 +107,16 @@ devtools/client/performance/**
 devtools/client/projecteditor/**
 devtools/client/promisedebugger/**
 devtools/client/responsivedesign/**
 devtools/client/scratchpad/**
 devtools/client/shadereditor/**
 devtools/client/shared/**
 devtools/client/sourceeditor/**
 devtools/client/storage/**
-devtools/client/styleeditor/**
 devtools/client/tilt/**
 devtools/client/webaudioeditor/**
 devtools/client/webconsole/**
 devtools/client/webide/**
 devtools/server/**
 devtools/shared/**
 
 # Ignore devtools pre-processed files
--- a/devtools/client/styleeditor/StyleEditorUI.jsm
+++ b/devtools/client/styleeditor/StyleEditorUI.jsm
@@ -2,32 +2,33 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 this.EXPORTED_SYMBOLS = ["StyleEditorUI"];
 
-const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 const {require, loader} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const Services = require("Services");
 const {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", {});
 const {OS} = Cu.import("resource://gre/modules/osfile.jsm", {});
 const {Task} = Cu.import("resource://gre/modules/Task.jsm", {});
 const EventEmitter = require("devtools/shared/event-emitter");
 const {gDevTools} = require("resource://devtools/client/framework/gDevTools.jsm");
+/* import-globals-from StyleEditorUtil.jsm */
 Cu.import("resource://devtools/client/styleeditor/StyleEditorUtil.jsm");
 const {SplitView} = Cu.import("resource://devtools/client/shared/SplitView.jsm", {});
 const {StyleSheetEditor} = Cu.import("resource://devtools/client/styleeditor/StyleSheetEditor.jsm");
 loader.lazyImporter(this, "PluralForm", "resource://gre/modules/PluralForm.jsm");
-const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
+const {PrefObserver, PREF_ORIG_SOURCES} =
+      require("devtools/client/styleeditor/utils");
 const csscoverage = require("devtools/server/actors/csscoverage");
 const {console} = require("resource://gre/modules/Console.jsm");
 const promise = require("promise");
 const {ResponsiveUIManager} =
   Cu.import("resource://devtools/client/responsivedesign/responsivedesign.jsm", {});
 
 const LOAD_ERROR = "error-load";
 const STYLE_EDITOR_TEMPLATE = "stylesheet";
@@ -168,31 +169,33 @@ StyleEditorUI.prototype = {
     this._panelDoc.addEventListener("contextmenu", () => {
       this._contextMenuStyleSheet = null;
     }, true);
 
     this._contextMenu = this._panelDoc.getElementById("sidebar-context");
     this._contextMenu.addEventListener("popupshowing",
                                        this._updateOpenLinkItem);
 
-    this._optionsMenu = this._panelDoc.getElementById("style-editor-options-popup");
+    this._optionsMenu =
+      this._panelDoc.getElementById("style-editor-options-popup");
     this._optionsMenu.addEventListener("popupshowing",
                                        this._onOptionsPopupShowing);
     this._optionsMenu.addEventListener("popuphiding",
                                        this._onOptionsPopupHiding);
 
     this._sourcesItem = this._panelDoc.getElementById("options-origsources");
     this._sourcesItem.addEventListener("command",
                                        this._toggleOrigSources);
 
     this._mediaItem = this._panelDoc.getElementById("options-show-media");
     this._mediaItem.addEventListener("command",
                                      this._toggleMediaSidebar);
 
-    this._openLinkNewTabItem = this._panelDoc.getElementById("context-openlinknewtab");
+    this._openLinkNewTabItem =
+      this._panelDoc.getElementById("context-openlinknewtab");
     this._openLinkNewTabItem.addEventListener("command",
                                               this._openLinkNewTab);
 
     let nav = this._panelDoc.querySelector(".splitview-controller");
     nav.setAttribute("width", Services.prefs.getIntPref(PREF_NAV_WIDTH));
   },
 
   /**
@@ -353,43 +356,43 @@ StyleEditorUI.prototype = {
    *
    * @param {mixed} file
    *        Optional nsIFile or filename string.
    *        If not set a file picker will be shown.
    * @param {nsIWindow} parentWindow
    *        Optional parent window for the file picker.
    */
   _importFromFile: function(file, parentWindow) {
-    let onFileSelected = (file) => {
-      if (!file) {
+    let onFileSelected = (selectedFile) => {
+      if (!selectedFile) {
         // nothing selected
         return;
       }
       NetUtil.asyncFetch({
-        uri: NetUtil.newURI(file),
+        uri: NetUtil.newURI(selectedFile),
         loadingNode: this._window.document,
         contentPolicyType: Ci.nsIContentPolicy.TYPE_OTHER
       }, (stream, status) => {
         if (!Components.isSuccessCode(status)) {
           this.emit("error", { key: LOAD_ERROR });
           return;
         }
-        let source = NetUtil.readInputStreamToString(stream, stream.available());
+        let source =
+            NetUtil.readInputStreamToString(stream, stream.available());
         stream.close();
 
         this._debuggee.addStyleSheet(source).then((styleSheet) => {
-          this._onStyleSheetCreated(styleSheet, file);
+          this._onStyleSheetCreated(styleSheet, selectedFile);
         });
       });
     };
 
     showFilePicker(file, false, parentWindow, onFileSelected);
   },
 
-
   /**
    * When a new or imported stylesheet has been added to the document.
    * Add an editor for it.
    */
   _onStyleSheetCreated: function(styleSheet, file) {
     this._addStyleSheetEditor(styleSheet, file, true);
   },
 
@@ -424,26 +427,32 @@ StyleEditorUI.prototype = {
   /**
    * Toggle the @media sidebar in each editor depending on the setting.
    */
   _onMediaPrefChanged: function() {
     this.editors.forEach(this._updateMediaList);
   },
 
   /**
-   * This method handles the following cases related to the context menu item "_openLinkNewTabItem":
+   * This method handles the following cases related to the context
+   * menu item "_openLinkNewTabItem":
    *
-   * 1) There was a stylesheet clicked on and it is external: show and enable the context menu item
-   * 2) There was a stylesheet clicked on and it is inline: show and disable the context menu item
-   * 3) There was no stylesheet clicked on (the right click happened below the list): hide the context menu
+   * 1) There was a stylesheet clicked on and it is external: show and
+   * enable the context menu item
+   * 2) There was a stylesheet clicked on and it is inline: show and
+   * disable the context menu item
+   * 3) There was no stylesheet clicked on (the right click happened
+   * below the list): hide the context menu
    */
   _updateOpenLinkItem: function() {
-    this._openLinkNewTabItem.setAttribute("hidden", !this._contextMenuStyleSheet);
+    this._openLinkNewTabItem.setAttribute("hidden",
+                                          !this._contextMenuStyleSheet);
     if (this._contextMenuStyleSheet) {
-      this._openLinkNewTabItem.setAttribute("disabled", !this._contextMenuStyleSheet.href);
+      this._openLinkNewTabItem.setAttribute("disabled",
+                                            !this._contextMenuStyleSheet.href);
     }
   },
 
   /**
    * Open a particular stylesheet in a new tab.
    */
   _openLinkNewTab: function() {
     if (this._contextMenuStyleSheet) {
@@ -455,25 +464,24 @@ StyleEditorUI.prototype = {
    * Remove a particular stylesheet editor from the UI
    *
    * @param {StyleSheetEditor}  editor
    *        The editor to remove.
    */
   _removeStyleSheetEditor: function(editor) {
     if (editor.summary) {
       this._view.removeItem(editor.summary);
-    }
-    else {
+    } else {
       let self = this;
       this.on("editor-added", function onAdd(event, added) {
         if (editor == added) {
           self.off("editor-added", onAdd);
           self._view.removeItem(editor.summary);
         }
-      })
+      });
     }
 
     editor.destroy();
     this.editors.splice(this.editors.indexOf(editor), 1);
   },
 
   /**
    * Clear all the editors from the UI.
@@ -498,48 +506,48 @@ StyleEditorUI.prototype = {
     // add new sidebar item and editor to the UI
     this._view.appendTemplatedItem(STYLE_EDITOR_TEMPLATE, {
       data: {
         editor: editor
       },
       disableAnimations: this._alwaysDisableAnimations,
       ordinal: ordinal,
       onCreate: function(summary, details, data) {
-        let editor = data.editor;
-        editor.summary = summary;
-        editor.details = details;
+        let createdEditor = data.editor;
+        createdEditor.summary = summary;
+        createdEditor.details = details;
 
         wire(summary, ".stylesheet-enabled", function onToggleDisabled(event) {
           event.stopPropagation();
           event.target.blur();
 
-          editor.toggleDisabled();
+          createdEditor.toggleDisabled();
         });
 
         wire(summary, ".stylesheet-name", {
           events: {
-            "keypress": (aEvent) => {
-              if (aEvent.keyCode == aEvent.DOM_VK_RETURN) {
+            "keypress": (event) => {
+              if (event.keyCode == event.DOM_VK_RETURN) {
                 this._view.activeSummary = summary;
               }
             }
           }
         });
 
         wire(summary, ".stylesheet-saveButton", function onSaveButton(event) {
           event.stopPropagation();
           event.target.blur();
 
-          editor.saveToFile(editor.savedFile);
+          createdEditor.saveToFile(createdEditor.savedFile);
         });
 
-        this._updateSummaryForEditor(editor, summary);
+        this._updateSummaryForEditor(createdEditor, summary);
 
-        summary.addEventListener("contextmenu", (event) => {
-          this._contextMenuStyleSheet = editor.styleSheet;
+        summary.addEventListener("contextmenu", () => {
+          this._contextMenuStyleSheet = createdEditor.styleSheet;
         }, false);
 
         summary.addEventListener("focus", function onSummaryFocus(event) {
           if (event.target == summary) {
             // autofocus the stylesheet name
             summary.querySelector(".stylesheet-name").focus();
           }
         }, false);
@@ -549,76 +557,77 @@ StyleEditorUI.prototype = {
             Services.prefs.getIntPref(PREF_SIDEBAR_WIDTH));
 
         let splitter = details.querySelector(".devtools-side-splitter");
         splitter.addEventListener("mousemove", () => {
           let sidebarWidth = sidebar.getAttribute("width");
           Services.prefs.setIntPref(PREF_SIDEBAR_WIDTH, sidebarWidth);
 
           // update all @media sidebars for consistency
-          let sidebars = [...this._panelDoc.querySelectorAll(".stylesheet-sidebar")];
+          let sidebars =
+              [...this._panelDoc.querySelectorAll(".stylesheet-sidebar")];
           for (let mediaSidebar of sidebars) {
             mediaSidebar.setAttribute("width", sidebarWidth);
           }
         });
 
         // autofocus if it's a new user-created stylesheet
-        if (editor.isNew) {
-          this._selectEditor(editor);
+        if (createdEditor.isNew) {
+          this._selectEditor(createdEditor);
         }
 
-        if (this._isEditorToSelect(editor)) {
+        if (this._isEditorToSelect(createdEditor)) {
           this.switchToSelectedSheet();
         }
 
         // If this is the first stylesheet and there is no pending request to
         // select a particular style sheet, select this sheet.
         if (!this.selectedEditor && !this._styleSheetBoundToSelect
-            && editor.styleSheet.styleSheetIndex == 0) {
-          this._selectEditor(editor);
+            && createdEditor.styleSheet.styleSheetIndex == 0) {
+          this._selectEditor(createdEditor);
         }
-        this.emit("editor-added", editor);
+        this.emit("editor-added", createdEditor);
       }.bind(this),
 
       onShow: function(summary, details, data) {
-        let editor = data.editor;
-        this.selectedEditor = editor;
+        let showEditor = data.editor;
+        this.selectedEditor = showEditor;
 
         Task.spawn(function* () {
-          if (!editor.sourceEditor) {
+          if (!showEditor.sourceEditor) {
             // only initialize source editor when we switch to this view
-            let inputElement = details.querySelector(".stylesheet-editor-input");
-            yield editor.load(inputElement);
+            let inputElement =
+                details.querySelector(".stylesheet-editor-input");
+            yield showEditor.load(inputElement);
           }
 
-          editor.onShow();
+          showEditor.onShow();
 
-          this.emit("editor-selected", editor);
+          this.emit("editor-selected", showEditor);
 
           // Is there any CSS coverage markup to include?
           let usage = yield csscoverage.getUsage(this._target);
           if (usage == null) {
             return;
           }
 
-          let href = csscoverage.sheetToUrl(editor.styleSheet);
-          let data = yield usage.createEditorReport(href)
+          let href = csscoverage.sheetToUrl(showEditor.styleSheet);
+          let reportData = yield usage.createEditorReport(href);
 
-          editor.removeAllUnusedRegions();
+          showEditor.removeAllUnusedRegions();
 
-          if (data.reports.length > 0) {
+          if (reportData.reports.length > 0) {
             // Only apply if this file isn't compressed. We detect a
             // compressed file if there are more rules than lines.
-            let text = editor.sourceEditor.getText();
+            let text = showEditor.sourceEditor.getText();
             let lineCount = text.split("\n").length;
-            let ruleCount = editor.styleSheet.ruleCount;
+            let ruleCount = showEditor.styleSheet.ruleCount;
             if (lineCount >= ruleCount) {
-              editor.addUnusedRegions(data.reports);
-            }
-            else {
+              showEditor.addUnusedRegions(reportData.reports);
+            } else {
               this.emit("error", { key: "error-compressed", level: "info" });
             }
           }
         }.bind(this)).then(null, Cu.reportError);
       }.bind(this)
     });
   },
 
@@ -728,23 +737,24 @@ StyleEditorUI.prototype = {
     });
 
     return deferred.promise;
   },
 
   /**
    * Returns an identifier for the given style sheet.
    *
-   * @param {StyleSheet} aStyleSheet
+   * @param {StyleSheet} styleSheet
    *        The style sheet to be identified.
    */
-  getStyleSheetIdentifier: function (aStyleSheet) {
-    // Identify inline style sheets by their host page URI and index at the page.
-    return aStyleSheet.href ? aStyleSheet.href :
-            "inline-" + aStyleSheet.styleSheetIndex + "-at-" + aStyleSheet.nodeHref;
+  getStyleSheetIdentifier: function(styleSheet) {
+    // Identify inline style sheets by their host page URI and index
+    // at the page.
+    return styleSheet.href ? styleSheet.href :
+      "inline-" + styleSheet.styleSheetIndex + "-at-" + styleSheet.nodeHref;
   },
 
   /**
    * selects a stylesheet and optionally moves the cursor to a selected line
    *
    * @param {StyleSheetFront} [stylesheet]
    *        Stylesheet to select or href of stylesheet to select
    * @param {Number} [line]
@@ -762,51 +772,50 @@ StyleEditorUI.prototype = {
       col: col,
     };
 
     /* Switch to the editor for this sheet, if it exists yet.
        Otherwise each editor will be checked when it's created. */
     return this.switchToSelectedSheet();
   },
 
-
   /**
    * Handler for an editor's 'property-changed' event.
    * Update the summary in the UI.
    *
    * @param  {StyleSheetEditor} editor
    *         Editor for which a property has changed
    */
   _summaryChange: function(editor) {
     this._updateSummaryForEditor(editor);
   },
 
   /**
    * Update split view summary of given StyleEditor instance.
    *
    * @param {StyleSheetEditor} editor
    * @param {DOMElement} summary
-   *        Optional item's summary element to update. If none, item corresponding
-   *        to passed editor is used.
+   *        Optional item's summary element to update. If none, item
+   *        corresponding to passed editor is used.
    */
   _updateSummaryForEditor: function(editor, summary) {
     summary = summary || editor.summary;
     if (!summary) {
       return;
     }
 
     let ruleCount = editor.styleSheet.ruleCount;
     if (editor.styleSheet.relatedStyleSheet && editor.linkedCSSFile) {
       ruleCount = editor.styleSheet.relatedStyleSheet.ruleCount;
     }
     if (ruleCount === undefined) {
       ruleCount = "-";
     }
 
-    var flags = [];
+    let flags = [];
     if (editor.styleSheet.disabled) {
       flags.push("disabled");
     }
     if (editor.unsaved) {
       flags.push("unsaved");
     }
     if (editor.linkedCSSFileError) {
       flags.push("linked-file-error");
@@ -868,27 +877,33 @@ StyleEditorUI.prototype = {
         // this @media rule is from a different original source
         if (location.source != editor.styleSheet.href) {
           continue;
         }
         inSource = true;
 
         let div = this._panelDoc.createElement("div");
         div.className = "media-rule-label";
-        div.addEventListener("click", this._jumpToLocation.bind(this, location));
+        div.addEventListener("click",
+                             this._jumpToLocation.bind(this, location));
 
         let cond = this._panelDoc.createElement("div");
         cond.textContent = rule.conditionText;
         cond.className = "media-rule-condition";
         if (!rule.matches) {
           cond.classList.add("media-condition-unmatched");
         }
         if (this._target.tab.tagName == "tab") {
-          cond.innerHTML = cond.textContent.replace(/(min\-|max\-)(width|height):\s\d+(px)/ig, "<a href='#' class='media-responsive-mode-toggle'>$&</a>");
-          cond.addEventListener("click", this._onMediaConditionClick.bind(this));
+          const minMaxPattern = /(min\-|max\-)(width|height):\s\d+(px)/ig;
+          const replacement =
+                "<a href='#' class='media-responsive-mode-toggle'>$&</a>";
+
+          cond.innerHTML = cond.textContent.replace(minMaxPattern, replacement);
+          cond.addEventListener("click",
+                                this._onMediaConditionClick.bind(this));
         }
         div.appendChild(cond);
 
         let link = this._panelDoc.createElement("div");
         link.className = "media-rule-line theme-link";
         if (location.line != -1) {
           link.textContent = ":" + location.line;
         }
@@ -911,17 +926,17 @@ StyleEditorUI.prototype = {
     *        Event object
     */
   _onMediaConditionClick: function(e) {
     if (!e.target.matches(".media-responsive-mode-toggle")) {
       return;
     }
     let conditionText = e.target.textContent;
     let isWidthCond = conditionText.toLowerCase().indexOf("width") > -1;
-    let mediaVal = parseInt(/\d+/.exec(conditionText));
+    let mediaVal = parseInt(/\d+/.exec(conditionText), 10);
 
     let options = isWidthCond ? {width: mediaVal} : {height: mediaVal};
     this._launchResponsiveMode(options);
     e.preventDefault();
     e.stopPropagation();
   },
 
   /**
@@ -931,22 +946,21 @@ StyleEditorUI.prototype = {
    *         Object with width or/and height properties.
    */
   _launchResponsiveMode: function(options = {}) {
     let tab = this._target.tab;
     let win = this._target.tab.ownerGlobal;
 
     ResponsiveUIManager.runIfNeeded(win, tab);
     if (options.width && options.height) {
-      ResponsiveUIManager.getResponsiveUIForTab(tab).setSize(options.width, options.height);
-    }
-    else if (options.width) {
+      ResponsiveUIManager.getResponsiveUIForTab(tab).setSize(options.width,
+                                                             options.height);
+    } else if (options.width) {
       ResponsiveUIManager.getResponsiveUIForTab(tab).setWidth(options.width);
-    }
-    else if (options.height) {
+    } else if (options.height) {
       ResponsiveUIManager.getResponsiveUIForTab(tab).setHeight(options.height);
     }
   },
 
   /**
    * Jump cursor to the editor for a stylesheet and line number for a rule.
    *
    * @param  {object} location
@@ -973,9 +987,9 @@ StyleEditorUI.prototype = {
                                           this._onOptionsPopupShowing);
     this._optionsMenu.removeEventListener("popuphiding",
                                           this._onOptionsPopupHiding);
 
     this._prefObserver.off(PREF_ORIG_SOURCES, this._onNewDocument);
     this._prefObserver.off(PREF_MEDIA_SIDEBAR, this._onMediaPrefChanged);
     this._prefObserver.destroy();
   }
-}
+};
--- a/devtools/client/styleeditor/StyleEditorUtil.jsm
+++ b/devtools/client/styleeditor/StyleEditorUtil.jsm
@@ -1,13 +1,16 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+/* All top-level definitions here are exports.  */
+/* eslint no-unused-vars: [2, {"vars": "local"}] */
+
 "use strict";
 
 this.EXPORTED_SYMBOLS = [
   "_",
   "assert",
   "log",
   "text",
   "wire",
@@ -21,152 +24,149 @@ const Cu = Components.utils;
 Cu.import("resource://gre/modules/Services.jsm");
 
 const PROPERTIES_URL = "chrome://devtools/locale/styleeditor.properties";
 
 const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 const console = require("resource://gre/modules/Console.jsm").console;
 const gStringBundle = Services.strings.createBundle(PROPERTIES_URL);
 
-
 /**
  * Returns a localized string with the given key name from the string bundle.
  *
- * @param aName
+ * @param name
  * @param ...rest
  *        Optional arguments to format in the string.
  * @return string
  */
-this._ = function _(aName)
-{
+function _(name) {
   try {
     if (arguments.length == 1) {
-      return gStringBundle.GetStringFromName(aName);
+      return gStringBundle.GetStringFromName(name);
     }
     let rest = Array.prototype.slice.call(arguments, 1);
-    return gStringBundle.formatStringFromName(aName, rest, rest.length);
-  }
-  catch (ex) {
+    return gStringBundle.formatStringFromName(name, rest, rest.length);
+  } catch (ex) {
     console.error(ex);
-    throw new Error("L10N error. '" + aName + "' is missing from " + PROPERTIES_URL);
+    throw new Error("L10N error. '" + name + "' is missing from " +
+                    PROPERTIES_URL);
   }
 }
 
 /**
  * Assert an expression is true or throw if false.
  *
- * @param aExpression
- * @param aMessage
+ * @param expression
+ * @param message
  *        Optional message.
- * @return aExpression
+ * @return expression
  */
-this.assert = function assert(aExpression, aMessage)
-{
-  if (!!!(aExpression)) {
-    let msg = aMessage ? "ASSERTION FAILURE:" + aMessage : "ASSERTION FAILURE";
+function assert(expression, message) {
+  if (!expression) {
+    let msg = message ? "ASSERTION FAILURE:" + message : "ASSERTION FAILURE";
     log(msg);
     throw new Error(msg);
   }
-  return aExpression;
+  return expression;
 }
 
 /**
  * Retrieve or set the text content of an element.
  *
- * @param DOMElement aRoot
+ * @param DOMElement root
  *        The element to use for querySelector.
- * @param string aSelector
+ * @param string selector
  *        Selector string for the element to get/set the text content.
- * @param string aText
+ * @param string textContent
  *        Optional text to set.
  * @return string
  *         Text content of matching element or null if there were no element
- *         matching aSelector.
+ *         matching selector.
  */
-this.text = function text(aRoot, aSelector, aText)
-{
-  let element = aRoot.querySelector(aSelector);
+function text(root, selector, textContent) {
+  let element = root.querySelector(selector);
   if (!element) {
     return null;
   }
 
-  if (aText === undefined) {
+  if (textContent === undefined) {
     return element.textContent;
   }
-  element.textContent = aText;
-  return aText;
+  element.textContent = textContent;
+  return textContent;
 }
 
 /**
  * Iterates _own_ properties of an object.
  *
- * @param aObject
+ * @param object
  *        The object to iterate.
- * @param function aCallback(aKey, aValue)
+ * @param function callback(aKey, aValue)
  */
-function forEach(aObject, aCallback)
-{
-  for (let key in aObject) {
-    if (aObject.hasOwnProperty(key)) {
-      aCallback(key, aObject[key]);
+function forEach(object, callback) {
+  for (let key in object) {
+    if (object.hasOwnProperty(key)) {
+      callback(key, object[key]);
     }
   }
 }
 
 /**
  * Log a message to the console.
  *
  * @param ...rest
  *        One or multiple arguments to log.
- *        If multiple arguments are given, they will be joined by " " in the log.
+ *        If multiple arguments are given, they will be joined by " "
+ *        in the log.
  */
-this.log = function log()
-{
+function log() {
   console.logStringMessage(Array.prototype.slice.call(arguments).join(" "));
 }
 
 /**
  * Wire up element(s) matching selector with attributes, event listeners, etc.
  *
- * @param DOMElement aRoot
+ * @param DOMElement root
  *        The element to use for querySelectorAll.
- *        Can be null if aSelector is a DOMElement.
- * @param string|DOMElement aSelectorOrElement
+ *        Can be null if selector is a DOMElement.
+ * @param string|DOMElement selectorOrElement
  *        Selector string or DOMElement for the element(s) to wire up.
- * @param object aDescriptor
- *        An object describing how to wire matching selector, supported properties
- *        are "events" and "attributes" taking objects themselves.
+ * @param object descriptor
+ *        An object describing how to wire matching selector,
+ *        supported properties are "events" and "attributes" taking
+ *        objects themselves.
  *        Each key of properties above represents the name of the event or
  *        attribute, with the value being a function used as an event handler or
  *        string to use as attribute value.
- *        If aDescriptor is a function, the argument is equivalent to :
- *        {events: {'click': aDescriptor}}
+ *        If descriptor is a function, the argument is equivalent to :
+ *        {events: {'click': descriptor}}
  */
-this.wire = function wire(aRoot, aSelectorOrElement, aDescriptor)
-{
+function wire(root, selectorOrElement, descriptor) {
   let matches;
-  if (typeof(aSelectorOrElement) == "string") { // selector
-    matches = aRoot.querySelectorAll(aSelectorOrElement);
+  if (typeof selectorOrElement == "string") {
+    // selector
+    matches = root.querySelectorAll(selectorOrElement);
     if (!matches.length) {
       return;
     }
   } else {
-    matches = [aSelectorOrElement]; // element
+    // element
+    matches = [selectorOrElement];
   }
 
-  if (typeof(aDescriptor) == "function") {
-    aDescriptor = {events: {click: aDescriptor}};
+  if (typeof descriptor == "function") {
+    descriptor = {events: {click: descriptor}};
   }
 
   for (let i = 0; i < matches.length; i++) {
     let element = matches[i];
-    forEach(aDescriptor.events, function (aName, aHandler) {
-      element.addEventListener(aName, aHandler, false);
+    forEach(descriptor.events, function(name, handler) {
+      element.addEventListener(name, handler, false);
     });
-    forEach(aDescriptor.attributes, element.setAttribute);
+    forEach(descriptor.attributes, element.setAttribute);
   }
 }
 
 /**
  * Show file picker and return the file user selected.
  *
  * @param mixed file
  *        Optional nsIFile or string representing the filename to auto-select.
@@ -176,42 +176,43 @@ this.wire = function wire(aRoot, aSelect
  *        Optional parent window. If null the parent window of the file picker
  *        will be the window of the attached input element.
  * @param callback
  *        The callback method, which will be called passing in the selected
  *        file or null if the user did not pick one.
  * @param AString suggestedFilename
  *        The suggested filename when toSave is true.
  */
-this.showFilePicker = function showFilePicker(path, toSave, parentWindow,
-                                              callback, suggestedFilename)
-{
-  if (typeof(path) == "string") {
+function showFilePicker(path, toSave, parentWindow, callback,
+                        suggestedFilename) {
+  if (typeof path == "string") {
     try {
       if (Services.io.extractScheme(path) == "file") {
         let uri = Services.io.newURI(path, null, null);
         let file = uri.QueryInterface(Ci.nsIFileURL).file;
         callback(file);
         return;
       }
     } catch (ex) {
       callback(null);
       return;
     }
     try {
-      let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
+      let file =
+          Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
       file.initWithPath(path);
       callback(file);
       return;
     } catch (ex) {
       callback(null);
       return;
     }
   }
-  if (path) { // "path" is an nsIFile
+  if (path) {
+    // "path" is an nsIFile
     callback(path);
     return;
   }
 
   let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
   let mode = toSave ? fp.modeSave : fp.modeOpen;
   let key = toSave ? "saveStyleSheet" : "importStyleSheet";
   let fpCallback = function(result) {
--- a/devtools/client/styleeditor/StyleSheetEditor.jsm
+++ b/devtools/client/styleeditor/StyleSheetEditor.jsm
@@ -7,27 +7,28 @@
 
 this.EXPORTED_SYMBOLS = ["StyleSheetEditor"];
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
-const Editor  = require("devtools/client/sourceeditor/editor");
+const Editor = require("devtools/client/sourceeditor/editor");
 const promise = require("promise");
 const {CssLogic} = require("devtools/shared/inspector/css-logic");
 const {console} = require("resource://gre/modules/Console.jsm");
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
-Cu.import("resource://gre/modules/osfile.jsm");
+const { TextDecoder, OS } = Cu.import("resource://gre/modules/osfile.jsm", {});
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://devtools/shared/event-emitter.js");
+/* import-globals-from StyleEditorUtil.jsm */
 Cu.import("resource://devtools/client/styleeditor/StyleEditorUtil.jsm");
 
 const LOAD_ERROR = "error-load";
 const SAVE_ERROR = "error-save";
 
 // max update frequency in ms (avoid potential typing lag and/or flicker)
 // @see StyleEditor.updateStylesheet
 const UPDATE_STYLESHEET_DELAY = 500;
@@ -35,20 +36,20 @@ const UPDATE_STYLESHEET_DELAY = 500;
 // Pref which decides if CSS autocompletion is enabled in Style Editor or not.
 const AUTOCOMPLETION_PREF = "devtools.styleeditor.autocompletion-enabled";
 
 // Pref which decides whether updates to the stylesheet use transitions
 const TRANSITION_PREF = "devtools.styleeditor.transitions";
 
 // How long to wait to update linked CSS file after original source was saved
 // to disk. Time in ms.
-const CHECK_LINKED_SHEET_DELAY=500;
+const CHECK_LINKED_SHEET_DELAY = 500;
 
 // How many times to check for linked file changes
-const MAX_CHECK_COUNT=10;
+const MAX_CHECK_COUNT = 10;
 
 // The classname used to show a line that is not used
 const UNUSED_CLASS = "cm-unused-line";
 
 // How much time should the mouse be still before the selector at that position
 // gets highlighted?
 const SELECTOR_HIGHLIGHT_TIMEOUT = 500;
 
@@ -87,17 +88,18 @@ function StyleSheetEditor(styleSheet, wi
   this.highlighter = highlighter;
 
   // True when we've called update() on the style sheet.
   this._isUpdating = false;
   // True when we've just set the editor text based on a style-applied
   // event from the StyleSheetActor.
   this._justSetText = false;
 
-  this._state = {   // state to use when inputElement attaches
+  // state to use when inputElement attaches
+  this._state = {
     text: "",
     selection: {
       start: {line: 0, ch: 0},
       end: {line: 0, ch: 0}
     }
   };
 
   this._styleSheetFilePath = null;
@@ -118,17 +120,18 @@ function StyleSheetEditor(styleSheet, wi
   this._updateStyleSheet = this._updateStyleSheet.bind(this);
   this._onMouseMove = this._onMouseMove.bind(this);
 
   this._focusOnSourceEditorReady = false;
   this.cssSheet.on("property-change", this._onPropertyChange);
   this.styleSheet.on("error", this._onError);
   this.mediaRules = [];
   if (this.cssSheet.getMediaRules) {
-    this.cssSheet.getMediaRules().then(this._onMediaRulesChanged, Cu.reportError);
+    this.cssSheet.getMediaRules().then(this._onMediaRulesChanged,
+                                       Cu.reportError);
   }
   this.cssSheet.on("media-rules-changed", this._onMediaRulesChanged);
   this.cssSheet.on("style-applied", this._onStyleApplied);
   this.savedFile = file;
   this.linkCSSFile();
 }
 this.StyleSheetEditor = StyleSheetEditor;
 
@@ -190,16 +193,17 @@ StyleSheetEditor.prototype = {
     }
 
     if (!this._friendlyName) {
       let sheetURI = this.styleSheet.href;
       this._friendlyName = CssLogic.shortSource({ href: sheetURI });
       try {
         this._friendlyName = decodeURI(this._friendlyName);
       } catch (ex) {
+        // Ignore.
       }
     }
     return this._friendlyName;
   },
 
   /**
    * Check if transitions are enabled for style changes.
    *
@@ -221,23 +225,21 @@ StyleSheetEditor.prototype = {
 
     let path;
     let href = removeQuery(relatedSheet.href);
     let uri = NetUtil.newURI(href);
 
     if (uri.scheme == "file") {
       let file = uri.QueryInterface(Ci.nsIFileURL).file;
       path = file.path;
-    }
-    else if (this.savedFile) {
+    } else if (this.savedFile) {
       let origHref = removeQuery(this.styleSheet.href);
       let origUri = NetUtil.newURI(origHref);
       path = findLinkedFilePath(uri, origUri, this.savedFile);
-    }
-    else {
+    } else {
       // we can't determine path to generated file on disk
       return;
     }
 
     if (this.linkedCSSFile == path) {
       return;
     }
 
@@ -524,28 +526,30 @@ StyleSheetEditor.prototype = {
                                                UPDATE_STYLESHEET_DELAY);
   },
 
   /**
    * Update live style sheet according to modifications.
    */
   _updateStyleSheet: function() {
     if (this.styleSheet.disabled) {
-      return;  // TODO: do we want to do this?
+      // TODO: do we want to do this?
+      return;
     }
 
     if (this._justSetText) {
       this._justSetText = false;
       return;
     }
 
-    this._updateTask = null; // reset only if we actually perform an update
-                             // (stylesheet is enabled) so that 'missed' updates
-                             // while the stylesheet is disabled can be performed
-                             // when it is enabled back. @see enableStylesheet
+    // reset only if we actually perform an update
+    // (stylesheet is enabled) so that 'missed' updates
+    // while the stylesheet is disabled can be performed
+    // when it is enabled back. @see enableStylesheet
+    this._updateTask = null;
 
     if (this.sourceEditor) {
       this._state.text = this.sourceEditor.getText();
     }
 
     this._isUpdating = true;
     this.styleSheet.update(this._state.text, this.transitionsEnabled)
                    .then(null, Cu.reportError);
@@ -577,17 +581,18 @@ StyleSheetEditor.prototype = {
    */
   _highlightSelectorAt: Task.async(function*(x, y) {
     let pos = this.sourceEditor.getPositionFromCoords({left: x, top: y});
     let info = this.sourceEditor.getInfoAt(pos);
     if (!info || info.state !== "selector") {
       return;
     }
 
-    let node = yield this.walker.getStyleSheetOwnerNode(this.styleSheet.actorID);
+    let node =
+        yield this.walker.getStyleSheetOwnerNode(this.styleSheet.actorID);
     yield this.highlighter.show(node, {
       selector: info.selector,
       hideInfoBar: true,
       showOnly: "border",
       region: "border"
     });
 
     this.emit("node-highlighted");
@@ -596,17 +601,18 @@ StyleSheetEditor.prototype = {
   /**
    * Save the editor contents into a file and set savedFile property.
    * A file picker UI will open if file is not set and editor is not headless.
    *
    * @param mixed file
    *        Optional nsIFile or string representing the filename to save in the
    *        background, no UI will be displayed.
    *        If not specified, the original style sheet URI is used.
-   *        To implement 'Save' instead of 'Save as', you can pass savedFile here.
+   *        To implement 'Save' instead of 'Save as', you can pass
+   *        savedFile here.
    * @param function(nsIFile aFile) callback
    *        Optional callback called when the operation has finished.
    *        aFile has the nsIFile object for saved file or null if the operation
    *        has failed or has been canceled by the user.
    * @see savedFile
    */
   saveToFile: function(file, callback) {
     let onFile = (returnFile) => {
@@ -710,17 +716,17 @@ StyleSheetEditor.prototype = {
    * @param string error
    *        The error we got when trying to access the file.
    */
   markLinkedFileBroken: function(error) {
     this.linkedCSSFileError = error || true;
     this.emit("linked-css-file-error");
 
     error += " querying " + this.linkedCSSFile +
-             " original source location: " + this.savedFile.path
+             " original source location: " + this.savedFile.path;
     Cu.reportError(error);
   },
 
   /**
    * For original sources (e.g. Sass files). Fetch contents of linked CSS
    * file from disk and live update the stylesheet object with the contents.
    */
   updateLinkedStyleSheet: function() {
@@ -745,17 +751,17 @@ StyleSheetEditor.prototype = {
     bindings[Editor.accel(_("saveStyleSheet.commandkey"))] = () => {
       this.saveToFile(this.savedFile);
     };
 
     bindings["Shift-" + Editor.accel(_("saveStyleSheet.commandkey"))] = () => {
       this.saveToFile();
     };
 
-    bindings["Esc"] = false;
+    bindings.Esc = false;
 
     return bindings;
   },
 
   /**
    * Clean up for this editor.
    */
   destroy: function() {
--- a/devtools/client/styleeditor/styleeditor-commands.js
+++ b/devtools/client/styleeditor/styleeditor-commands.js
@@ -24,45 +24,45 @@ const l10n = require("gcli/l10n");
  */
 exports.items = [{
   item: "command",
   runAt: "server",
   name: "edit",
   description: l10n.lookup("editDesc"),
   manual: l10n.lookup("editManual2"),
   params: [
-     {
-       name: 'resource',
-       type: {
-         name: 'resource',
-         include: 'text/css'
-       },
-       description: l10n.lookup("editResourceDesc")
-     },
-     {
-       name: "line",
-       defaultValue: 1,
-       type: {
-         name: "number",
-         min: 1,
-         step: 10
-       },
-       description: l10n.lookup("editLineToJumpToDesc")
-     }
-   ],
-   returnType: "editArgs",
-   exec: args => {
-     return { href: args.resource.name, line: args.line };
-   }
+    {
+      name: "resource",
+      type: {
+        name: "resource",
+        include: "text/css"
+      },
+      description: l10n.lookup("editResourceDesc")
+    },
+    {
+      name: "line",
+      defaultValue: 1,
+      type: {
+        name: "number",
+        min: 1,
+        step: 10
+      },
+      description: l10n.lookup("editLineToJumpToDesc")
+    }
+  ],
+  returnType: "editArgs",
+  exec: args => {
+    return { href: args.resource.name, line: args.line };
+  }
 }, {
   item: "converter",
   from: "editArgs",
   to: "dom",
-   exec: function(args, context) {
-     let target = context.environment.target;
-     let gDevTools = require("resource://devtools/client/framework/gDevTools.jsm").gDevTools;
-     return gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
-       let styleEditor = toolbox.getCurrentPanel();
-       styleEditor.selectStyleSheet(args.href, args.line);
-       return null;
-     });
-   }
+  exec: function(args, context) {
+    let target = context.environment.target;
+    let gDevTools = require("resource://devtools/client/framework/gDevTools.jsm").gDevTools;
+    return gDevTools.showToolbox(target, "styleeditor").then(function(toolbox) {
+      let styleEditor = toolbox.getCurrentPanel();
+      styleEditor.selectStyleSheet(args.href, args.line);
+      return null;
+    });
+  }
 }];
--- a/devtools/client/styleeditor/styleeditor-panel.js
+++ b/devtools/client/styleeditor/styleeditor-panel.js
@@ -1,42 +1,45 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-const {Cc, Ci, Cu, Cr} = require("chrome");
+"use strict";
+
+const {Cu} = require("chrome");
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 var promise = require("promise");
 var EventEmitter = require("devtools/shared/event-emitter");
 
 Cu.import("resource://devtools/client/styleeditor/StyleEditorUI.jsm");
+/* import-globals-from StyleEditorUtil.jsm */
 Cu.import("resource://devtools/client/styleeditor/StyleEditorUtil.jsm");
 
 loader.lazyGetter(this, "StyleSheetsFront",
   () => require("devtools/server/actors/stylesheets").StyleSheetsFront);
 
 loader.lazyGetter(this, "StyleEditorFront",
   () => require("devtools/server/actors/styleeditor").StyleEditorFront);
 
-this.StyleEditorPanel = function StyleEditorPanel(panelWin, toolbox) {
+var StyleEditorPanel = function StyleEditorPanel(panelWin, toolbox) {
   EventEmitter.decorate(this);
 
   this._toolbox = toolbox;
   this._target = toolbox.target;
   this._panelWin = panelWin;
   this._panelDoc = panelWin.document;
 
   this.destroy = this.destroy.bind(this);
   this._showError = this._showError.bind(this);
-}
+};
 
 exports.StyleEditorPanel = StyleEditorPanel;
 
 StyleEditorPanel.prototype = {
   get target() {
     return this._toolbox.target;
   },
 
@@ -52,18 +55,17 @@ StyleEditorPanel.prototype = {
     if (!this.target.isRemote) {
       yield this.target.makeRemote();
     }
 
     this.target.on("close", this.destroy);
 
     if (this.target.form.styleSheetsActor) {
       this._debuggee = StyleSheetsFront(this.target.client, this.target.form);
-    }
-    else {
+    } else {
       /* We're talking to a pre-Firefox 29 server-side */
       this._debuggee = StyleEditorFront(this.target.client, this.target.form);
     }
 
     // Initialize the UI
     this.UI = new StyleEditorUI(this._debuggee, this.target, this._panelDoc);
     this.UI.on("error", this._showError);
     yield this.UI.initialize();
@@ -89,17 +91,18 @@ StyleEditorPanel.prototype = {
     }
 
     let errorMessage = _(data.key);
     if (data.append) {
       errorMessage += " " + data.append;
     }
 
     let notificationBox = this._toolbox.getNotificationBox();
-    let notification = notificationBox.getNotificationWithValue("styleeditor-error");
+    let notification =
+        notificationBox.getNotificationWithValue("styleeditor-error");
     let level = (data.level === "info") ?
                 notificationBox.PRIORITY_INFO_LOW :
                 notificationBox.PRIORITY_CRITICAL_LOW;
 
     if (!notification) {
       notificationBox.appendNotification(errorMessage, "styleeditor-error",
                                          "", level);
     }
@@ -115,17 +118,17 @@ StyleEditorPanel.prototype = {
    * @param {number} col
    *        Column number to jump to after selecting. One-indexed
    * @return {Promise}
    *         Promise that will resolve when the editor is selected and ready
    *         to be used.
    */
   selectStyleSheet: function(href, line, col) {
     if (!this._debuggee || !this.UI) {
-      return;
+      return null;
     }
     return this.UI.selectStyleSheet(href, line - 1, col ? col - 1 : 0);
   },
 
   /**
    * Destroy the style editor.
    */
   destroy: function() {
@@ -141,15 +144,15 @@ StyleEditorPanel.prototype = {
       this._debuggee = null;
 
       this.UI.destroy();
       this.UI = null;
     }
 
     return promise.resolve(null);
   },
-}
+};
 
 XPCOMUtils.defineLazyGetter(StyleEditorPanel.prototype, "strings",
-  function () {
+  function() {
     return Services.strings.createBundle(
             "chrome://devtools/locale/styleeditor.properties");
   });
--- a/devtools/client/styleeditor/test/browser.ini
+++ b/devtools/client/styleeditor/test/browser.ini
@@ -39,16 +39,17 @@ support-files =
   sourcemap-sass/sourcemaps.scss
   sourcemap-sass/media-rules.scss
   sourcemap-styl/test-stylus.styl
   sourcemaps.html
   sourcemaps-large.html
   sourcemaps-watching.html
   test_private.css
   test_private.html
+  doc_frame_script.js
   doc_long.css
   doc_uncached.css
   doc_uncached.html
   doc_xulpage.xul
   sync.html
 
 [browser_styleeditor_autocomplete.js]
 [browser_styleeditor_autocomplete-disabled.js]
--- a/devtools/client/styleeditor/test/browser_styleeditor_cmd_edit.html
+++ b/devtools/client/styleeditor/test/browser_styleeditor_cmd_edit.html
@@ -1,23 +1,25 @@
 <!DOCTYPE html>
 <html>
 <!-- Any copyright is dedicated to the Public Domain.
      http://creativecommons.org/publicdomain/zero/1.0/ -->
 <head>
   <meta charset="utf-8">
   <title>Resources</title>
-  <script type="text/javascript" id="script1">
-    window.addEventListener('load', function() {
-      var pid = document.getElementById('pid');
-      var div = document.createElement('div');
-      div.id = 'divid';
-      div.classList.add('divclass');
-      div.appendChild(document.createTextNode('div'));
-      div.setAttribute('data-a1', 'div');
+  <script type="text/javascript;version=1.8" id="script1">
+    "use strict";
+
+    window.addEventListener("load", function() {
+      let pid = document.getElementById("pid");
+      let div = document.createElement("div");
+      div.id = "divid";
+      div.classList.add("divclass");
+      div.appendChild(document.createTextNode("div"));
+      div.setAttribute("data-a1", "div");
       pid.parentNode.appendChild(div);
     });
   </script>
   <script src="resources_inpage.jsi"></script>
   <link rel="stylesheet" type="text/css" href="resources_inpage1.css"/>
   <link rel="stylesheet" type="text/css" href="resources_inpage2.css"/>
   <style type="text/css">
     p { color: #800; }
@@ -32,19 +34,20 @@
     .divclass { background-color: #EEF; }
     .h4class { background-color: #EFE; }
     .h3class { background-color: #FFE; }
   </style>
 
   <p class="pclass" id="pid" data-a1="p">paragraph</p>
 
   <script>
-    var pid = document.getElementById('pid');
-    var h4 = document.createElement('h4');
-    h4.id = 'h4id';
-    h4.classList.add('h4class');
-    h4.appendChild(document.createTextNode('h4'));
-    h4.setAttribute('data-a1', 'h4');
+    "use strict";
+    let pid = document.getElementById("pid");
+    let h4 = document.createElement("h4");
+    h4.id = "h4id";
+    h4.classList.add("h4class");
+    h4.appendChild(document.createTextNode("h4"));
+    h4.setAttribute("data-a1", "h4");
     pid.parentNode.appendChild(h4);
   </script>
 
 </body>
 </html>
--- a/devtools/client/styleeditor/test/browser_styleeditor_cmd_edit.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_cmd_edit.js
@@ -1,15 +1,21 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Tests that the edit command works
 
+// Import the GCLI test helper
+/* import-globals-from ../../commandline/test/helpers.js */
+Services.scriptloader.loadSubScript(
+  "chrome://mochitests/content/browser/devtools/client/commandline/test/helpers.js",
+  this);
+
 const TEST_URI = "http://example.com/browser/devtools/client/styleeditor/" +
                  "test/browser_styleeditor_cmd_edit.html";
 
 add_task(function* () {
   let options = yield helpers.openTab(TEST_URI);
   yield helpers.openToolbar(options);
 
   yield helpers.audit(options, [
@@ -77,19 +83,19 @@ add_task(function* () {
         hints: " [line] -> http://example.com/browser/devtools/client/" +
                "styleeditor/test/resources_inpage1.css",
         markup: "VVVVVIIIII",
         status: "ERROR",
         args: {
           resource: {
             arg: " page1",
             status: "INCOMPLETE",
-            message: 'Value required for \'resource\'.'
+            message: "Value required for \'resource\'."
           },
-          line: { status: 'VALID' },
+          line: { status: "VALID" },
         }
       },
     },
     {
       setup: "edit page2",
       check: {
         input: "edit page2",
         hints: " [line] -> http://example.com/browser/devtools/client/" +
--- a/devtools/client/styleeditor/test/browser_styleeditor_media_sidebar.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_media_sidebar.js
@@ -5,17 +5,18 @@
 "use strict";
 
 // https rather than chrome to improve coverage
 const TESTCASE_URI = TEST_BASE_HTTPS + "media-rules.html";
 const MEDIA_PREF = "devtools.styleeditor.showMediaSidebar";
 
 const RESIZE = 300;
 const LABELS = ["not all", "all", "(max-width: 400px)",
-                "(min-height: 200px) and (max-height: 250px)", "(max-width: 600px)"];
+                "(min-height: 200px) and (max-height: 250px)",
+                "(max-width: 600px)"];
 const LINE_NOS = [1, 7, 19, 25, 30];
 const NEW_RULE = "\n@media (max-width: 600px) { div { color: blue; } }";
 
 waitForExplicitFinish();
 
 add_task(function*() {
   let { ui } = yield openStyleEditorForURL(TESTCASE_URI);
 
--- a/devtools/client/styleeditor/test/browser_styleeditor_media_sidebar_links.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_media_sidebar_links.js
@@ -1,12 +1,14 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
+"use strict";
+
 /* Tests responsive mode links for
  * @media sidebar width and height related conditions */
 
 const {ResponsiveUIManager} =
       Cu.import("resource://devtools/client/responsivedesign/responsivedesign.jsm", {});
 const TESTCASE_URI = TEST_BASE_HTTPS + "media-rules.html";
 
 waitForExplicitFinish();
@@ -15,26 +17,26 @@ add_task(function*() {
   let {ui} = yield openStyleEditorForURL(TESTCASE_URI);
 
   let mediaEditor = ui.editors[1];
   yield openEditor(mediaEditor);
 
   yield testLinkifiedConditions(mediaEditor, gBrowser.selectedTab, ui);
 });
 
-function testLinkifiedConditions(editor, tab, ui) {
+function* testLinkifiedConditions(editor, tab, ui) {
   let sidebar = editor.details.querySelector(".stylesheet-sidebar");
   let conditions = sidebar.querySelectorAll(".media-rule-condition");
   let responsiveModeToggleClass = ".media-responsive-mode-toggle";
 
   info("Testing if media rules have the appropriate number of links");
   ok(!conditions[0].querySelector(responsiveModeToggleClass),
     "There should be no links in the first media rule.");
   ok(!conditions[1].querySelector(responsiveModeToggleClass),
-    "There should be no links in the second media rule.")
+     "There should be no links in the second media rule.");
   ok(conditions[2].querySelector(responsiveModeToggleClass),
      "There should be 1 responsive mode link in the media rule");
   is(conditions[3].querySelectorAll(responsiveModeToggleClass).length, 2,
        "There should be 2 resposnive mode links in the media rule");
 
   info("Launching responsive mode");
   conditions[2].querySelector(responsiveModeToggleClass).click();
 
--- a/devtools/client/styleeditor/test/browser_styleeditor_new.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_new.js
@@ -8,17 +8,17 @@
 const TESTCASE_URI = TEST_BASE_HTTP + "simple.html";
 
 const TESTCASE_CSS_SOURCE = "body{background-color:red;";
 
 add_task(function*() {
   let { panel, ui } = yield openStyleEditorForURL(TESTCASE_URI);
 
   let editor = yield createNew(ui, panel.panelWindow);
-  testInitialState(editor);
+  yield testInitialState(editor);
 
   let originalHref = editor.styleSheet.href;
   let waitForPropertyChange = onPropertyChange(editor);
 
   yield typeInEditor(editor, panel.panelWindow);
 
   yield waitForPropertyChange;
 
@@ -40,71 +40,71 @@ function createNew(ui, panelWindow) {
     ok(newButton, "'new' button exists");
 
     EventUtils.synthesizeMouseAtCenter(newButton, {}, panelWindow);
   }, panelWindow);
 
   return deferred.promise;
 }
 
-function onPropertyChange(aEditor) {
+function onPropertyChange(editor) {
   let deferred = promise.defer();
 
-  aEditor.styleSheet.on("property-change", function onProp(property) {
+  editor.styleSheet.on("property-change", function onProp(property) {
     // wait for text to be entered fully
-    let text = aEditor.sourceEditor.getText();
+    let text = editor.sourceEditor.getText();
     if (property == "ruleCount" && text == TESTCASE_CSS_SOURCE + "}") {
-      aEditor.styleSheet.off("property-change", onProp);
+      editor.styleSheet.off("property-change", onProp);
       deferred.resolve();
     }
   });
 
   return deferred.promise;
 }
 
-function testInitialState(aEditor) {
+function* testInitialState(editor) {
   info("Testing the initial state of the new editor");
 
-  let summary = aEditor.summary;
+  let summary = editor.summary;
 
-  ok(aEditor.sourceLoaded, "new editor is loaded when attached");
-  ok(aEditor.isNew, "new editor has isNew flag");
+  ok(editor.sourceLoaded, "new editor is loaded when attached");
+  ok(editor.isNew, "new editor has isNew flag");
 
-  ok(aEditor.sourceEditor.hasFocus(), "new editor has focus");
+  ok(editor.sourceEditor.hasFocus(), "new editor has focus");
 
-  summary = aEditor.summary;
+  summary = editor.summary;
   let ruleCount = summary.querySelector(".stylesheet-rule-count").textContent;
   is(parseInt(ruleCount, 10), 0, "new editor initially shows 0 rules");
 
-  let computedStyle = content.getComputedStyle(content.document.body, null);
-  is(computedStyle.backgroundColor, "rgb(255, 255, 255)",
+  let color = yield getComputedStyleProperty("body", null, "background-color");
+  is(color, "rgb(255, 255, 255)",
      "content's background color is initially white");
 }
 
-function typeInEditor(aEditor, panelWindow) {
+function typeInEditor(editor, panelWindow) {
   let deferred = promise.defer();
 
   waitForFocus(function() {
     for (let c of TESTCASE_CSS_SOURCE) {
       EventUtils.synthesizeKey(c, {}, panelWindow);
     }
-    ok(aEditor.unsaved, "new editor has unsaved flag");
+    ok(editor.unsaved, "new editor has unsaved flag");
 
     deferred.resolve();
   }, panelWindow);
 
   return deferred.promise;
 }
 
-function testUpdated(aEditor, originalHref) {
+function testUpdated(editor, originalHref) {
   info("Testing the state of the new editor after editing it");
 
-  is(aEditor.sourceEditor.getText(), TESTCASE_CSS_SOURCE + "}",
+  is(editor.sourceEditor.getText(), TESTCASE_CSS_SOURCE + "}",
      "rule bracket has been auto-closed");
 
-  let ruleCount = aEditor.summary.querySelector(".stylesheet-rule-count")
+  let ruleCount = editor.summary.querySelector(".stylesheet-rule-count")
     .textContent;
   is(parseInt(ruleCount, 10), 1,
      "new editor shows 1 rule after modification");
 
-  is(aEditor.styleSheet.href, originalHref,
+  is(editor.styleSheet.href, originalHref,
      "style sheet href did not change");
 }
--- a/devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_sourcemap_watching.js
@@ -48,20 +48,18 @@ add_task(function*() {
 
   is(getStylesheetNameFor(editor), TESTCASE_SCSS_NAME, "found scss editor");
 
   let link = getLinkFor(editor);
   link.click();
 
   yield editor.getSourceEditor();
 
-  let element = content.document.querySelector("div");
-  let style = content.getComputedStyle(element, null);
-
-  is(style.color, "rgb(255, 0, 102)", "div is red before saving file");
+  let color = yield getComputedStyleProperty("div", null, "color");
+  is(color, "rgb(255, 0, 102)", "div is red before saving file");
 
   // let styleApplied = promise.defer();
   let styleApplied = editor.once("style-applied");
 
   yield pauseForTimeChange();
 
   // Edit and save Sass in the editor. This will start off a file-watching
   // process waiting for the CSS file to change.
@@ -70,17 +68,18 @@ add_task(function*() {
   // We can't run Sass or another compiler, so we fake it by just
   // directly changing the CSS file.
   yield editCSSFile(CSSFile);
 
   info("wrote to CSS file, waiting for style-applied event");
 
   yield styleApplied;
 
-  is(style.color, "rgb(0, 0, 255)", "div is blue after saving file");
+  color = yield getComputedStyleProperty("div", null, "color");
+  is(color, "rgb(0, 0, 255)", "div is blue after saving file");
 });
 
 function editSCSS(editor) {
   let deferred = promise.defer();
 
   editor.sourceEditor.setText(CSS_TEXT);
 
   editor.saveToFile(null, function(file) {
@@ -120,17 +119,16 @@ function getStylesheetNameFor(editor) {
 function copy(srcChromeURL, destFilePath) {
   let destFile = FileUtils.getFile("ProfD", destFilePath);
   return write(read(srcChromeURL), destFile);
 }
 
 function read(srcChromeURL) {
   let scriptableStream = Cc["@mozilla.org/scriptableinputstream;1"]
     .getService(Ci.nsIScriptableInputStream);
-  let principal = Services.scriptSecurityManager.getSystemPrincipal();
 
   let channel = NetUtil.newChannel({
     uri: srcChromeURL,
     loadUsingSystemPrincipal: true
   });
   let input = channel.open2();
   scriptableStream.init(input);
 
@@ -139,29 +137,29 @@ function read(srcChromeURL) {
     data = data.concat(scriptableStream.read(input.available()));
   }
   scriptableStream.close();
   input.close();
 
   return data;
 }
 
-function write(aData, aFile) {
+function write(data, file) {
   let deferred = promise.defer();
 
   let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
     .createInstance(Ci.nsIScriptableUnicodeConverter);
 
   converter.charset = "UTF-8";
 
-  let istream = converter.convertToInputStream(aData);
-  let ostream = FileUtils.openSafeFileOutputStream(aFile);
+  let istream = converter.convertToInputStream(data);
+  let ostream = FileUtils.openSafeFileOutputStream(file);
 
   NetUtil.asyncCopy(istream, ostream, function(status) {
     if (!Components.isSuccessCode(status)) {
-      info("Coudln't write to " + aFile.path);
+      info("Coudln't write to " + file.path);
       return;
     }
-    deferred.resolve(aFile);
+    deferred.resolve(file);
   });
 
   return deferred.promise;
 }
--- a/devtools/client/styleeditor/test/browser_styleeditor_sourcemaps.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_sourcemaps.js
@@ -42,24 +42,24 @@ const contents = {
     "  color: #f06; }",
     "",
     "/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJma" +
     "WxlIjoiIiwic291cmNlcyI6WyJzYXNzL2NvbnRhaW5lZC5zY3NzIl0sIm5hbWVzIjpbXSwi" +
     "bWFwcGluZ3MiOiJBQUVBO0VBQ0UsT0FISyIsInNvdXJjZXNDb250ZW50IjpbIiRwaW5rOiA" +
     "jZjA2O1xuXG4jaGVhZGVyIHtcbiAgY29sb3I6ICRwaW5rO1xufSJdfQ==*/"
   ].join("\n"),
   "test-stylus.styl": [
-   "paulrougetpink = #f06;",
-   "",
-   "div",
-   "  color: paulrougetpink",
-   "",
-  "span",
-  "  background-color: #EEE",
-  ""
+    "paulrougetpink = #f06;",
+    "",
+    "div",
+    "  color: paulrougetpink",
+    "",
+    "span",
+    "  background-color: #EEE",
+    ""
   ].join("\n"),
   "test-stylus.css": [
     "div {",
     "  color: #f06;",
     "}",
     "span {",
     "  background-color: #eee;",
     "}",
--- a/devtools/client/styleeditor/test/browser_styleeditor_sync.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_sync.js
@@ -1,16 +1,17 @@
 /* vim: set 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 changes in the style inspector are synchronized into the
 // style editor.
 
+/* import-globals-from ../../inspector/shared/test/head.js */
 Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/client/inspector/shared/test/head.js", this);
 
 const TESTCASE_URI = TEST_BASE_HTTP + "sync.html";
 
 const expectedText = `
   body {
     border-width: 15px;
     /*! color: red; */
@@ -60,15 +61,11 @@ add_task(function*() {
   // available.
   ui = yield closeAndReopenToolbox();
   editor = yield ui.editors[0].getSourceEditor();
   text = editor.sourceEditor.getText();
   is(text, expectedText, "changes remain after close and reopen");
 
   // For the time being, the actor does not update the style's owning
   // node's textContent.  See bug 1205380.
-  yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function*() {
-    let style = content.document.querySelector("style");
-    return style.textContent;
-  }).then((textContent) => {
-    isnot(textContent, expectedText, "changes not written back to style node");
-  });
+  let textContent = yield executeInContent("Test:GetStyleContent", null, null);
+  isnot(textContent, expectedText, "changes not written back to style node");
 });
--- a/devtools/client/styleeditor/test/browser_styleeditor_syncAddRule.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_syncAddRule.js
@@ -1,15 +1,16 @@
 /* vim: set 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 adding a new rule is synced to the style editor.
 
+/* import-globals-from ../../inspector/shared/test/head.js */
 Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/client/inspector/shared/test/head.js", this);
 
 const TESTCASE_URI = TEST_BASE_HTTP + "sync.html";
 
 const expectedText = `
 #testid {
 }`;
 
--- a/devtools/client/styleeditor/test/browser_styleeditor_syncAlreadyOpen.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_syncAlreadyOpen.js
@@ -1,16 +1,17 @@
 /* vim: set 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 changes in the style inspector are synchronized into the
 // style editor.
 
+/* import-globals-from ../../inspector/shared/test/head.js */
 Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/client/inspector/shared/test/head.js", this);
 
 const TESTCASE_URI = TEST_BASE_HTTP + "sync.html";
 
 const expectedText = `
   body {
     border-width: 15px;
     color: red;
--- a/devtools/client/styleeditor/test/browser_styleeditor_syncEditSelector.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_syncEditSelector.js
@@ -1,16 +1,17 @@
 /* vim: set 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 changes in the style inspector are synchronized into the
 // style editor.
 
+/* import-globals-from ../../inspector/shared/test/head.js */
 Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/client/inspector/shared/test/head.js", this);
 
 const TESTCASE_URI = TEST_BASE_HTTP + "sync.html";
 
 const expectedText = `
   body {
     border-width: 15px;
     color: red;
--- a/devtools/client/styleeditor/test/browser_styleeditor_syncIntoRuleView.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_syncIntoRuleView.js
@@ -1,16 +1,17 @@
 /* vim: set 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 changes in the style editor are synchronized into the
 // style inspector.
 
+/* import-globals-from ../../inspector/shared/test/head.js */
 Services.scriptloader.loadSubScript("chrome://mochitests/content/browser/devtools/client/inspector/shared/test/head.js", this);
 
 const TEST_URI = `
   <style type='text/css'>
     div { background-color: seagreen; }
   </style>
   <div id='testid' class='testclass'>Styled Node</div>
 `;
@@ -30,22 +31,22 @@ add_task(function*() {
   let waitForRuleView = view.once("ruleview-refreshed");
   yield typeInEditor(editor, panel.panelWindow);
   yield waitForRuleView;
 
   let value = getRuleViewPropertyValue(view, "#testid", "color");
   is(value, "chartreuse", "check that edits were synced to rule view");
 });
 
-function typeInEditor(aEditor, panelWindow) {
+function typeInEditor(editor, panelWindow) {
   let deferred = promise.defer();
 
   waitForFocus(function() {
     for (let c of TESTCASE_CSS_SOURCE) {
       EventUtils.synthesizeKey(c, {}, panelWindow);
     }
-    ok(aEditor.unsaved, "new editor has unsaved flag");
+    ok(editor.unsaved, "new editor has unsaved flag");
 
     deferred.resolve();
   }, panelWindow);
 
   return deferred.promise;
 }
--- a/devtools/client/styleeditor/test/browser_styleeditor_transition_rule.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_transition_rule.js
@@ -19,22 +19,23 @@ add_task(function*() {
   // Set text twice in a row
   let styleChanges = listenForStyleChange(editor.styleSheet);
 
   editor.sourceEditor.setText(NEW_RULE);
   editor.sourceEditor.setText(NEW_RULE + " ");
 
   yield styleChanges;
 
-  let sheet = content.document.styleSheets[0];
+  let rules = yield executeInContent("Test:cssRules", {
+    num: 0
+  });
 
   // Test that we removed the transition rule, but kept the rule we added
-  is(sheet.cssRules.length, 1, "only one rule in stylesheet");
-  is(sheet.cssRules[0].cssText, NEW_RULE,
-     "stylesheet only contains rule we added");
+  is(rules.length, 1, "only one rule in stylesheet");
+  is(rules[0], NEW_RULE, "stylesheet only contains rule we added");
 });
 
 /* Helpers */
 
 function openEditor(editor) {
   let link = editor.summary.querySelector(".stylesheet-name");
   link.click();
 
--- a/devtools/client/styleeditor/test/browser_styleeditor_xul.js
+++ b/devtools/client/styleeditor/test/browser_styleeditor_xul.js
@@ -1,19 +1,22 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 // Test that the style-editor initializes correctly for XUL windows.
 
+"use strict";
+
 waitForExplicitFinish();
 
 const TEST_URL = TEST_BASE + "doc_xulpage.xul";
 
 add_task(function*() {
   let tab = yield addTab(TEST_URL);
   let target = TargetFactory.forTab(tab);
 
   let toolbox = yield gDevTools.showToolbox(target, "styleeditor");
   let panel = toolbox.getCurrentPanel();
 
-  ok(panel, "The style-editor panel did initialize correctly for the XUL window");
+  ok(panel,
+     "The style-editor panel did initialize correctly for the XUL window");
 });
new file mode 100644
--- /dev/null
+++ b/devtools/client/styleeditor/test/doc_frame_script.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/* globals addMessageListener, sendAsyncMessage */
+
+addMessageListener("Test:cssRules", function(msg) {
+  let {num} = msg.data;
+  let sheet = content.document.styleSheets[num];
+  let result = [];
+  for (let i = 0; i < sheet.cssRules.length; ++i) {
+    result.push(sheet.cssRules[i].cssText);
+  }
+  sendAsyncMessage("Test:cssRules", result);
+});
+
+/**
+ * Get the property value from the computed style for an element.
+ * @param {Object} data Expects a data object with the following properties
+ * - {String} selector: The selector used to obtain the element.
+ * - {String} pseudo: pseudo id to query, or null.
+ * - {String} name: name of the property
+ * @return {String} The value, if found, null otherwise
+ */
+addMessageListener("Test:GetComputedStylePropertyValue", function(msg) {
+  let {selector, pseudo, name} = msg.data;
+  let element = content.document.querySelector(selector);
+  let style = content.document.defaultView.getComputedStyle(element, pseudo);
+  let value = style.getPropertyValue(name);
+  sendAsyncMessage("Test:GetComputedStylePropertyValue", value);
+});
+
+addMessageListener("Test:GetStyleContent", function() {
+  sendAsyncMessage("Test:GetStyleContent",
+                   content.document.querySelector("style").textContent);
+});
--- a/devtools/client/styleeditor/test/head.js
+++ b/devtools/client/styleeditor/test/head.js
@@ -1,28 +1,33 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-const FRAME_SCRIPT_UTILS_URL = "chrome://devtools/content/shared/frame-script-utils.js"
-const TEST_BASE = "chrome://mochitests/content/browser/devtools/client/styleeditor/test/";
-const TEST_BASE_HTTP = "http://example.com/browser/devtools/client/styleeditor/test/";
-const TEST_BASE_HTTPS = "https://example.com/browser/devtools/client/styleeditor/test/";
-const TEST_HOST = 'mochi.test:8888';
+/* All top-level definitions here are exports.  */
+/* eslint no-unused-vars: [2, {"vars": "local"}] */
+
+"use strict";
+
+const FRAME_SCRIPT_UTILS_URL =
+      "chrome://devtools/content/shared/frame-script-utils.js";
+const TEST_BASE =
+      "chrome://mochitests/content/browser/devtools/client/styleeditor/test/";
+const TEST_BASE_HTTP =
+      "http://example.com/browser/devtools/client/styleeditor/test/";
+const TEST_BASE_HTTPS =
+      "https://example.com/browser/devtools/client/styleeditor/test/";
+const TEST_HOST = "mochi.test:8888";
+
+const EDITOR_FRAME_SCRIPT = getRootDirectory(gTestPath) + "doc_frame_script.js";
 
 var {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
 var {TargetFactory} = require("devtools/client/framework/target");
-var {console} = Cu.import("resource://gre/modules/Console.jsm", {});
 var promise = require("promise");
 var DevToolsUtils = require("devtools/shared/DevToolsUtils");
 
-// Import the GCLI test helper
-Services.scriptloader.loadSubScript(
-  "chrome://mochitests/content/browser/devtools/client/commandline/test/helpers.js",
-  this);
-
 DevToolsUtils.testing = true;
 SimpleTest.registerCleanupFunction(() => {
   DevToolsUtils.testing = false;
 });
 
 /**
  * Add a new test tab in the browser and load the given url.
  * @param {String} url The url to be loaded in the new tab
@@ -56,18 +61,17 @@ function navigateTo(url) {
   gBrowser.selectedBrowser.addEventListener("load", function onload() {
     gBrowser.selectedBrowser.removeEventListener("load", onload, true);
     navigating.resolve();
   }, true);
   content.location = url;
   return navigating.promise;
 }
 
-function* cleanup()
-{
+function* cleanup() {
   while (gBrowser.tabs.length > 1) {
     let target = TargetFactory.forTab(gBrowser.selectedTab);
     yield gDevTools.closeToolbox(target);
 
     gBrowser.removeCurrentTab();
   }
 }
 
@@ -87,16 +91,20 @@ var openStyleEditor = Task.async(functio
 });
 
 /**
  * Creates a new tab in specified window navigates it to the given URL and
  * opens style editor in it.
  */
 var openStyleEditorForURL = Task.async(function* (url, win) {
   let tab = yield addTab(url, win);
+
+  gBrowser.selectedBrowser.messageManager.loadFrameScript(EDITOR_FRAME_SCRIPT,
+                                                          false);
+
   let result = yield openStyleEditor(tab);
   result.tab = tab;
   return result;
 });
 
 /**
  * Loads shared/frame-script-utils.js in the specified tab.
  *
@@ -123,38 +131,56 @@ function loadCommonFrameScript(tab) {
  * @param Boolean expectResponse
  *        If set to false, don't wait for a response with the same name from the
  *        content script. Defaults to true.
  *
  * @return Promise
  *         Resolves to the response data if a response is expected, immediately
  *         resolves otherwise
  */
-function executeInContent(name, data={}, objects={}, expectResponse=true) {
+function executeInContent(name, data = {}, objects = {},
+                          expectResponse = true) {
   let mm = gBrowser.selectedBrowser.messageManager;
 
   mm.sendAsyncMessage(name, data, objects);
   if (expectResponse) {
     return waitForContentMessage(name);
-  } else {
-    return promise.resolve();
   }
+  return promise.resolve();
 }
 
 /**
  * Wait for a content -> chrome message on the message manager (the window
  * messagemanager is used).
  * @param {String} name The message name
  * @return {Promise} A promise that resolves to the response data when the
  * message has been received
  */
 function waitForContentMessage(name) {
   let mm = gBrowser.selectedBrowser.messageManager;
 
   let def = promise.defer();
   mm.addMessageListener(name, function onMessage(msg) {
     mm.removeMessageListener(name, onMessage);
-    def.resolve(msg);
+    def.resolve(msg.data);
   });
   return def.promise;
 }
 
 registerCleanupFunction(cleanup);
+
+/**
+ * Send an async message to the frame script and get back the requested
+ * computed style property.
+ *
+ * @param {String} selector
+ *        The selector used to obtain the element.
+ * @param {String} pseudo
+ *        pseudo id to query, or null.
+ * @param {String} name
+ *        name of the property.
+ */
+function* getComputedStyleProperty(selector, pseudo, propName) {
+  return yield executeInContent("Test:GetComputedStylePropertyValue",
+                                {selector,
+                                pseudo,
+                                name: propName});
+}
--- a/devtools/client/styleeditor/test/longload.html
+++ b/devtools/client/styleeditor/test/longload.html
@@ -14,15 +14,16 @@
 
   div > span {
      text-decoration: underline;
   }
   </style>
 </head>
 <body>
   Time passes:
-  <script>
-    for (i = 0; i < 5000; i++) {
+  <script type="application/javascript;version=1.8">
+    "use strict";
+    for (let i = 0; i < 5000; i++) {
       document.write("<br>...");
     }
   </script>
 </body>
 </html>
--- a/devtools/client/styleeditor/utils.js
+++ b/devtools/client/styleeditor/utils.js
@@ -1,15 +1,17 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-const {Cc, Ci, Cu, Cr} = require("chrome");
+"use strict";
+
+const {Cu} = require("chrome");
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://devtools/shared/event-emitter.js");
 
 exports.PREF_ORIG_SOURCES = "devtools.styleeditor.source-maps-enabled";
 
 /**
  * A PreferenceObserver observes a pref branch for pref changes.
@@ -29,12 +31,12 @@ PrefObserver.prototype = {
   observe: function(subject, topic, data) {
     if (topic == "nsPref:changed") {
       this.emit(this.branchName + data);
     }
   },
 
   destroy: function() {
     if (this.branch) {
-      this.branch.removeObserver('', this);
+      this.branch.removeObserver("", this);
     }
   }
-};
\ No newline at end of file
+};
--- a/testing/mochitest/browser.eslintrc
+++ b/testing/mochitest/browser.eslintrc
@@ -21,17 +21,16 @@
     "finish": false,
     "getRootDirectory": false,
     "getTestFilePath": false,
     "gTestPath": false,
     "info": false,
     "is": false,
     "isnot": false,
     "ok": false,
-    "promise": false,
     "registerCleanupFunction": false,
     "requestLongerTimeout": false,
     "SimpleTest": false,
     "SpecialPowers": false,
     "thisTestLeaksUncaughtRejectionsAndShouldBeFixed": false,
     "todo": false,
     "todo_is": false,
     "todo_isnot": false,