Back out 14d1050e721b (bug 940541) for Windows b-c bustage
authorPhil Ringnalda <philringnalda@gmail.com>
Mon, 02 Dec 2013 19:48:43 -0800
changeset 174082 ef4c8f6e3ef7010fc12075e5c34e4f33f37ec26c
parent 174081 e20c9dd37a86fe074f02e3d688bedf050e54f647
child 174083 5e2062d62bf627673ba1ed382f6f351c9538a816
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs940541
milestone28.0a1
backs out14d1050e721b15be403c76676b57cafaebc4819d
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
Back out 14d1050e721b (bug 940541) for Windows b-c bustage
browser/devtools/shadereditor/panel.js
browser/devtools/shadereditor/shadereditor.js
browser/devtools/shadereditor/test/browser_se_bfcache.js
browser/devtools/shadereditor/test/browser_se_editors-contents.js
browser/devtools/shadereditor/test/browser_se_editors-error-gutter.js
browser/devtools/shadereditor/test/browser_se_editors-error-tooltip.js
browser/devtools/shadereditor/test/browser_se_navigation.js
browser/devtools/shadereditor/test/browser_se_programs-blackbox-01.js
browser/devtools/shadereditor/test/browser_se_programs-blackbox-02.js
browser/devtools/shadereditor/test/browser_se_programs-cache.js
browser/devtools/shadereditor/test/browser_se_programs-highlight-01.js
browser/devtools/shadereditor/test/browser_se_programs-highlight-02.js
browser/devtools/shadereditor/test/browser_se_programs-list.js
browser/devtools/shadereditor/test/browser_se_shaders-edit-01.js
browser/devtools/shadereditor/test/browser_se_shaders-edit-02.js
browser/devtools/shadereditor/test/browser_se_shaders-edit-03.js
browser/devtools/shadereditor/test/browser_webgl-actor-test-13.js
browser/devtools/shadereditor/test/browser_webgl-actor-test-14.js
browser/devtools/shadereditor/test/browser_webgl-actor-test-15.js
browser/devtools/shadereditor/test/browser_webgl-actor-test-16.js
browser/devtools/shadereditor/test/browser_webgl-actor-test-17.js
browser/devtools/shadereditor/test/head.js
--- a/browser/devtools/shadereditor/panel.js
+++ b/browser/devtools/shadereditor/panel.js
@@ -1,17 +1,17 @@
 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/. */
 "use strict";
 
 const { Cc, Ci, Cu, Cr } = require("chrome");
-const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
+const promise = require("sdk/core/promise");
 const EventEmitter = require("devtools/shared/event-emitter");
 const { WebGLFront } = require("devtools/server/actors/webgl");
 
 function ShaderEditorPanel(iframeWindow, toolbox) {
   this.panelWin = iframeWindow;
   this._toolbox = toolbox;
   this._destroyer = null;
 
--- a/browser/devtools/shadereditor/shadereditor.js
+++ b/browser/devtools/shadereditor/shadereditor.js
@@ -8,38 +8,32 @@ const { classes: Cc, interfaces: Ci, uti
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/devtools/Loader.jsm");
 Cu.import("resource:///modules/devtools/SideMenuWidget.jsm");
 Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
 
 const require = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}).devtools.require;
-const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
+const promise = require("sdk/core/promise");
 const EventEmitter = require("devtools/shared/event-emitter");
 const {Tooltip} = require("devtools/shared/widgets/Tooltip");
 const Editor = require("devtools/sourceeditor/editor");
 
 // The panel's window global is an EventEmitter firing the following events:
 const EVENTS = {
   // When new programs are received from the server.
   NEW_PROGRAM: "ShaderEditor:NewProgram",
   PROGRAMS_ADDED: "ShaderEditor:ProgramsAdded",
 
   // When the vertex and fragment sources were shown in the editor.
   SOURCES_SHOWN: "ShaderEditor:SourcesShown",
 
   // When a shader's source was edited and compiled via the editor.
-  SHADER_COMPILED: "ShaderEditor:ShaderCompiled",
-
-  // When the UI is reset from tab navigation
-  UI_RESET: "ShaderEditor:UIReset",
-
-  // When the editor's error markers are all removed
-  EDITOR_ERROR_MARKERS_REMOVED: "ShaderEditor:EditorCleaned"
+  SHADER_COMPILED: "ShaderEditor:ShaderCompiled"
 };
 
 const STRINGS_URI = "chrome://browser/locale/devtools/shadereditor.properties"
 const HIGHLIGHT_TINT = [1, 0, 0.25, 1]; // rgba
 const TYPING_MAX_DELAY = 500; // ms
 const SHADERS_AUTOGROW_ITEMS = 4;
 const GUTTER_ERROR_PANEL_OFFSET_X = 7; // px
 const GUTTER_ERROR_PANEL_DELAY = 100; // ms
@@ -115,27 +109,25 @@ let EventsHandler = {
   },
 
   /**
    * Called for each location change in the debugged tab.
    */
   _onTabNavigated: function(event) {
     switch (event) {
       case "will-navigate": {
-        Task.spawn(function() {
-          // Make sure the backend is prepared to handle WebGL contexts.
-          gFront.setup({ reload: false });
+        // Make sure the backend is prepared to handle WebGL contexts.
+        gFront.setup({ reload: false });
 
-          // Reset UI.
-          ShadersListView.empty();
-          $("#reload-notice").hidden = true;
-          $("#waiting-notice").hidden = false;
-          yield ShadersEditorsView.setText({ vs: "", fs: "" });
-          $("#content").hidden = true;
-        }).then(() => window.emit(EVENTS.UI_RESET));
+        // Reset UI.
+        ShadersListView.empty();
+        ShadersEditorsView.setText({ vs: "", fs: "" });
+        $("#reload-notice").hidden = true;
+        $("#waiting-notice").hidden = false;
+        $("#content").hidden = true;
         break;
       }
       case "navigate": {
         // Manually retrieve the list of program actors known to the server,
         // because the backend won't emit "program-linked" notifications
         // in the case of a bfcache navigation (since no new programs are
         // actually linked).
         gFront.getPrograms().then(this._onProgramsAdded);
@@ -275,26 +267,23 @@ let ShadersListView = Heritage.extend(Wi
     }
     function getSources([vertexShaderActor, fragmentShaderActor]) {
       return promise.all([
         vertexShaderActor.getText(),
         fragmentShaderActor.getText()
       ]);
     }
     function showSources([vertexShaderText, fragmentShaderText]) {
-      return ShadersEditorsView.setText({
+      ShadersEditorsView.setText({
         vs: vertexShaderText,
         fs: fragmentShaderText
       });
     }
 
-    getShaders()
-      .then(getSources)
-      .then(showSources)
-      .then(null, Cu.reportError);
+    getShaders().then(getSources).then(showSources).then(null, Cu.reportError);
   },
 
   /**
    * The check listener for the programs container.
    */
   _onProgramCheck: function({ detail: { checked }, target }) {
     let sourceItem = this.getItemForElement(target);
     let attachment = sourceItem.attachment;
@@ -357,48 +346,41 @@ let ShadersEditorsView = {
 
   /**
    * Sets the text displayed in the vertex and fragment shader editors.
    *
    * @param object sources
    *        An object containing the following properties
    *          - vs: the vertex shader source code
    *          - fs: the fragment shader source code
-   * @return object
-   *        A promise resolving upon completion of text setting.
    */
   setText: function(sources) {
-    let view = this;
     function setTextAndClearHistory(editor, text) {
       editor.setText(text);
       editor.clearHistory();
     }
 
-    return Task.spawn(function() {
-      yield view._toggleListeners("off");
-      yield promise.all([
-        view._getEditor("vs").then(e => setTextAndClearHistory(e, sources.vs)),
-        view._getEditor("fs").then(e => setTextAndClearHistory(e, sources.fs))
-      ]);
-      yield view._toggleListeners("on");
-    }).then(() => window.emit(EVENTS.SOURCES_SHOWN, sources));
+    this._toggleListeners("off");
+    this._getEditor("vs").then(e => setTextAndClearHistory(e, sources.vs));
+    this._getEditor("fs").then(e => setTextAndClearHistory(e, sources.fs));
+    this._toggleListeners("on");
+
+    window.emit(EVENTS.SOURCES_SHOWN, sources);
   },
 
   /**
    * Lazily initializes and returns a promise for an Editor instance.
    *
    * @param string type
    *        Specifies for which shader type should an editor be retrieved,
    *        either are "vs" for a vertex, or "fs" for a fragment shader.
-   * @return object
-   *        Returns a promise that resolves to an editor instance
    */
   _getEditor: function(type) {
     if ($("#content").hidden) {
-      return promise.reject(new Error("Shader Editor is still waiting for a WebGL context to be created."));
+      return promise.reject(null);
     }
     if (this._editorPromises.has(type)) {
       return this._editorPromises.get(type);
     }
 
     let deferred = promise.defer();
     this._editorPromises.set(type, deferred.promise);
 
@@ -412,26 +394,24 @@ let ShadersEditorsView = {
     return deferred.promise;
   },
 
   /**
    * Toggles all the event listeners for the editors either on or off.
    *
    * @param string flag
    *        Either "on" to enable the event listeners, "off" to disable them.
-   * @return object
-   *        A promise resolving upon completion of toggling the listeners.
    */
   _toggleListeners: function(flag) {
-    return promise.all(["vs", "fs"].map(type => {
-      return this._getEditor(type).then(editor => {
+    ["vs", "fs"].forEach(type => {
+      this._getEditor(type).then(editor => {
         editor[flag]("focus", this["_" + type + "Focused"]);
         editor[flag]("change", this["_" + type + "Changed"]);
       });
-    }));
+    });
   },
 
   /**
    * The focus listener for a source editor.
    *
    * @param string focused
    *        The corresponding shader type for the focused editor (e.g. "vs").
    * @param string focused
@@ -501,17 +481,17 @@ let ShadersEditorsView = {
       };
     }
     function discardInvalidMatches(e) {
       // Discard empty line and text matches.
       return e.lineMatch && e.textMatch;
     }
     function sanitizeValidMatches(e) {
       return {
-        // Drivers might yield confusing line numbers under some obscure
+        // Drivers might yield retarded line numbers under some obscure
         // circumstances. Don't throw the errors away in those cases,
         // just display them on the currently edited line.
         line: e.lineMatch[0] > lineCount ? currentLine : e.lineMatch[0] - 1,
         // Trim whitespace from the beginning and the end of the message,
         // and replace all other occurences of double spaces to a single space.
         text: e.textMatch[0].trim().replace(/\s{2,}/g, " ")
       };
     }
@@ -569,17 +549,16 @@ let ShadersEditorsView = {
   /**
    * Removes all the gutter markers and line classes from the editor.
    */
   _cleanEditor: function(type) {
     this._getEditor(type).then(editor => {
       editor.removeAllMarkers("errors");
       this._errors[type].forEach(e => editor.removeLineClass(e.line));
       this._errors[type].length = 0;
-      window.emit(EVENTS.EDITOR_ERROR_MARKERS_REMOVED);
     });
   },
 
   _errors: {
     vs: [],
     fs: []
   }
 };
--- a/browser/devtools/shadereditor/test/browser_se_bfcache.js
+++ b/browser/devtools/shadereditor/test/browser_se_bfcache.js
@@ -9,17 +9,18 @@ function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
   let { gFront, $, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
 
   let reloaded = reload(target);
   let firstProgram = yield once(gFront, "program-linked");
   yield reloaded;
 
   let navigated = navigate(target, MULTIPLE_CONTEXTS_URL);
-  let [secondProgram, thirdProgram] = yield getPrograms(gFront, 2);
+  let secondProgram = yield once(gFront, "program-linked");
+  let thirdProgram = yield once(gFront, "program-linked");
   yield navigated;
 
   let vsEditor = yield ShadersEditorsView._getEditor("vs");
   let fsEditor = yield ShadersEditorsView._getEditor("fs");
 
   yield navigateInHistory(target, "back", "will-navigate");
   yield once(panel.panelWin, EVENTS.PROGRAMS_ADDED);
   yield once(panel.panelWin, EVENTS.SOURCES_SHOWN);
@@ -50,8 +51,14 @@ function ifWebGLSupported() {
   is(vsEditor.getText().indexOf("gl_Position"), 100,
     "The vertex shader editor contains the correct text.");
   is(fsEditor.getText().indexOf("gl_FragColor"), 89,
     "The fragment shader editor contains the correct text.");
 
   yield teardown(panel);
   finish();
 }
+
+function once(aTarget, aEvent) {
+  let deferred = promise.defer();
+  aTarget.once(aEvent, deferred.resolve);
+  return deferred.promise;
+}
--- a/browser/devtools/shadereditor/test/browser_se_editors-contents.js
+++ b/browser/devtools/shadereditor/test/browser_se_editors-contents.js
@@ -3,28 +3,24 @@
 
 /**
  * Tests if the editors contain the correct text when a program
  * becomes available.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
-  let { gFront, ShadersEditorsView, EVENTS } = panel.panelWin;
+  let { gFront, ShadersEditorsView } = panel.panelWin;
 
   reload(target);
-  yield promise.all([
-    once(gFront, "program-linked"),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]);
+  yield once(gFront, "program-linked");
 
   let vsEditor = yield ShadersEditorsView._getEditor("vs");
   let fsEditor = yield ShadersEditorsView._getEditor("fs");
 
-
   is(vsEditor.getText().indexOf("gl_Position"), 170,
     "The vertex shader editor contains the correct text.");
   is(fsEditor.getText().indexOf("gl_FragColor"), 97,
     "The fragment shader editor contains the correct text.");
 
   yield teardown(panel);
   finish();
 }
--- a/browser/devtools/shadereditor/test/browser_se_editors-error-gutter.js
+++ b/browser/devtools/shadereditor/test/browser_se_editors-error-gutter.js
@@ -6,71 +6,65 @@
  * when there's a shader compilation error.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
   let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
 
   reload(target);
-  yield promise.all([
-    once(gFront, "program-linked"),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]);
+  yield once(gFront, "program-linked");
 
   let vsEditor = yield ShadersEditorsView._getEditor("vs");
   let fsEditor = yield ShadersEditorsView._getEditor("fs");
 
   vsEditor.replaceText("vec3", { line: 7, ch: 22 }, { line: 7, ch: 26 });
-  let [, vertError] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
+  let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
   checkHasVertFirstError(true, vertError);
   checkHasVertSecondError(false, vertError);
   info("Error marks added in the vertex shader editor.");
 
   vsEditor.insertText(" ", { line: 1, ch: 0 });
-  yield once(panel.panelWin, EVENTS.EDITOR_ERROR_MARKERS_REMOVED);
   is(vsEditor.getText(1), "       precision lowp float;", "Typed space.");
   checkHasVertFirstError(false, vertError);
   checkHasVertSecondError(false, vertError);
   info("Error marks removed while typing in the vertex shader editor.");
 
-  let [_, vertError] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
+  let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
   checkHasVertFirstError(true, vertError);
   checkHasVertSecondError(false, vertError);
   info("Error marks were re-added after recompiling the vertex shader.");
 
   fsEditor.replaceText("vec4", { line: 2, ch: 14 }, { line: 2, ch: 18 });
-  let [_, fragError] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
+  let fragError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
   checkHasVertFirstError(true, vertError);
   checkHasVertSecondError(false, vertError);
   checkHasFragError(true, fragError);
   info("Error marks added in the fragment shader editor.");
 
   fsEditor.insertText(" ", { line: 1, ch: 0 });
-  yield once(panel.panelWin, EVENTS.EDITOR_ERROR_MARKERS_REMOVED);
   is(fsEditor.getText(1), "       precision lowp float;", "Typed space.");
   checkHasVertFirstError(true, vertError);
   checkHasVertSecondError(false, vertError);
   checkHasFragError(false, fragError);
   info("Error marks removed while typing in the fragment shader editor.");
 
-  let [_, fragError] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
+  let fragError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
   checkHasVertFirstError(true, vertError);
   checkHasVertSecondError(false, vertError);
   checkHasFragError(true, fragError);
   info("Error marks were re-added after recompiling the fragment shader.");
 
   vsEditor.replaceText("2", { line: 3, ch: 19 }, { line: 3, ch: 20 });
-  yield once(panel.panelWin, EVENTS.EDITOR_ERROR_MARKERS_REMOVED);
   checkHasVertFirstError(false, vertError);
   checkHasVertSecondError(false, vertError);
   checkHasFragError(true, fragError);
   info("Error marks removed while typing in the vertex shader editor again.");
 
-  let [_, vertError] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
+  let vertError = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
   checkHasVertFirstError(true, vertError);
   checkHasVertSecondError(true, vertError);
   checkHasFragError(true, fragError);
   info("Error marks were re-added after recompiling the fragment shader again.");
 
   yield teardown(panel);
   finish();
 
@@ -149,8 +143,14 @@ function ifWebGLSupported() {
         "The correct line was parsed.");
       is(parsed[0].messages.length, 1,
         "There is 1 parsed message.");
       ok(parsed[0].messages[0].contains("'constructor' : too many arguments"),
         "The correct message was parsed.");
     }
   }
 }
+
+function once(aTarget, aEvent) {
+  let deferred = promise.defer();
+  aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
+  return deferred.promise;
+}
--- a/browser/devtools/shadereditor/test/browser_se_editors-error-tooltip.js
+++ b/browser/devtools/shadereditor/test/browser_se_editors-error-tooltip.js
@@ -6,20 +6,17 @@
  * a shader compilation error.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
   let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
 
   reload(target);
-  yield promise.all([
-    once(gFront, "program-linked"),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]);
+  yield once(gFront, "program-linked");
 
   let vsEditor = yield ShadersEditorsView._getEditor("vs");
   let fsEditor = yield ShadersEditorsView._getEditor("fs");
 
   vsEditor.replaceText("vec3", { line: 7, ch: 22 }, { line: 7, ch: 26 });
   yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
 
   // Synthesizing 'mouseenter' events doesn't work, hack around this by
@@ -49,8 +46,14 @@ function ifWebGLSupported() {
   ok(messages[0].textContent.contains("'constructor' : too many arguments"),
     "The first message contains the correct text.");
   ok(messages[1].textContent.contains("'assign' : cannot convert"),
     "The second message contains the correct text.");
 
   yield teardown(panel);
   finish();
 }
+
+function once(aTarget, aEvent) {
+  let deferred = promise.defer();
+  aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
+  return deferred.promise;
+}
--- a/browser/devtools/shadereditor/test/browser_se_navigation.js
+++ b/browser/devtools/shadereditor/test/browser_se_navigation.js
@@ -2,23 +2,20 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests target navigations are handled correctly in the UI.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
-  let { gFront, $, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
+  let { gFront, $, ShadersListView, ShadersEditorsView } = panel.panelWin;
 
   reload(target);
-  yield promise.all([
-    once(gFront, "program-linked"),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]);
+  yield once(gFront, "program-linked");
 
   is($("#reload-notice").hidden, true,
     "The 'reload this page' notice should be hidden after linking.");
   is($("#waiting-notice").hidden, true,
     "The 'waiting for a WebGL context' notice should be visible after linking.");
   is($("#content").hidden, false,
     "The tool's content should not be hidden anymore.");
 
@@ -37,43 +34,44 @@ function ifWebGLSupported() {
   is(fsEditor.getText().indexOf("gl_FragColor"), 97,
     "The fragment shader editor contains the correct text.");
 
   let navigating = once(target, "will-navigate");
   let navigated = once(target, "will-navigate");
   navigate(target, "about:blank");
 
   yield navigating;
-  yield once(panel.panelWin, EVENTS.UI_RESET);
 
   is($("#reload-notice").hidden, true,
     "The 'reload this page' notice should be hidden while navigating.");
   is($("#waiting-notice").hidden, false,
     "The 'waiting for a WebGL context' notice should be visible while navigating.");
   is($("#content").hidden, true,
     "The tool's content should be hidden now that there's no WebGL content.");
 
   is(ShadersListView.itemCount, 0,
     "The shaders list should be empty.");
   is(ShadersListView.selectedItem, null,
     "The shaders list has no correct item.");
   is(ShadersListView.selectedIndex, -1,
     "The shaders list has a negative index.");
 
-  yield ShadersEditorsView._getEditor("vs").then(() => {
+  try {
+    yield ShadersEditorsView._getEditor("vs");
     ok(false, "The promise for a vertex shader editor should be rejected.");
-  }, () => {
+  } catch (e) {
     ok(true, "The vertex shader editors wasn't initialized.");
-  });
+  }
 
-  yield ShadersEditorsView._getEditor("fs").then(() => {
+  try {
+    yield ShadersEditorsView._getEditor("fs");
     ok(false, "The promise for a fragment shader editor should be rejected.");
-  }, () => {
+  } catch (e) {
     ok(true, "The fragment shader editors wasn't initialized.");
-  });
+  }
 
   yield navigated;
 
   is($("#reload-notice").hidden, true,
     "The 'reload this page' notice should still be hidden after navigating.");
   is($("#waiting-notice").hidden, false,
     "The 'waiting for a WebGL context' notice should still be visible after navigating.");
   is($("#content").hidden, true,
--- a/browser/devtools/shadereditor/test/browser_se_programs-blackbox-01.js
+++ b/browser/devtools/shadereditor/test/browser_se_programs-blackbox-01.js
@@ -9,20 +9,18 @@ function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(MULTIPLE_CONTEXTS_URL);
   let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
 
   once(panel.panelWin, EVENTS.SHADER_COMPILED).then(() => {
     ok(false, "No shaders should be publicly compiled during this test.");
   });
 
   reload(target);
-  let [firstProgramActor, secondProgramActor] = yield promise.all([
-    getPrograms(gFront, 2),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]).then(([programs, ]) => programs);
+  let firstProgramActor = yield once(gFront, "program-linked");
+  let secondProgramActor = yield once(gFront, "program-linked");
 
   let vsEditor = yield ShadersEditorsView._getEditor("vs");
   let fsEditor = yield ShadersEditorsView._getEditor("fs");
 
   vsEditor.once("change", () => {
     ok(false, "The vertex shader source was unexpectedly changed.");
   });
   fsEditor.once("change", () => {
--- a/browser/devtools/shadereditor/test/browser_se_programs-blackbox-02.js
+++ b/browser/devtools/shadereditor/test/browser_se_programs-blackbox-02.js
@@ -6,20 +6,18 @@
  * overlapping geometry.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(BLENDED_GEOMETRY_CANVAS_URL);
   let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
 
   reload(target);
-  let [firstProgramActor, secondProgramActor] = yield promise.all([
-    getPrograms(gFront, 2),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]).then(([programs, ]) => programs);
+  let firstProgramActor = yield once(gFront, "program-linked");
+  let secondProgramActor = yield once(gFront, "program-linked");
 
   yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 127, g: 127, b: 127, a: 255 }, true);
   yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 127, b: 127, a: 127 }, true);
   ok(true, "The canvas was correctly drawn.");
 
   getBlackBoxCheckbox(panel, 0).click();
 
   yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
@@ -56,8 +54,14 @@ function ifWebGLSupported() {
   yield teardown(panel);
   finish();
 }
 
 function getBlackBoxCheckbox(aPanel, aIndex) {
   return aPanel.panelWin.document.querySelectorAll(
     ".side-menu-widget-item-checkbox")[aIndex];
 }
+
+function once(aTarget, aEvent) {
+  let deferred = promise.defer();
+  aTarget.once(aEvent, deferred.resolve);
+  return deferred.promise;
+}
--- a/browser/devtools/shadereditor/test/browser_se_programs-cache.js
+++ b/browser/devtools/shadereditor/test/browser_se_programs-cache.js
@@ -2,24 +2,20 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests that program and shader actors are cached in the frontend.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(MULTIPLE_CONTEXTS_URL);
-  let { EVENTS, gFront, ShadersListView, ShadersEditorsView } = panel.panelWin;
+  let { gFront, ShadersListView, ShadersEditorsView } = panel.panelWin;
 
   reload(target);
-  let [programActor, ] = yield promise.all([
-    getPrograms(gFront, 1),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]).then(([programs, ]) => programs);
-
+  let programActor = yield once(gFront, "program-linked");
   let programItem = ShadersListView.selectedItem;
 
   is(programItem.attachment.programActor, programActor,
     "The correct program actor is cached for the selected item.");
 
   is((yield programActor.getVertexShader()),
      (yield programItem.attachment.vs),
     "The cached vertex shader promise returns the correct actor.");
--- a/browser/devtools/shadereditor/test/browser_se_programs-highlight-01.js
+++ b/browser/devtools/shadereditor/test/browser_se_programs-highlight-01.js
@@ -9,20 +9,18 @@ function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(MULTIPLE_CONTEXTS_URL);
   let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
 
   once(panel.panelWin, EVENTS.SHADER_COMPILED).then(() => {
     ok(false, "No shaders should be publicly compiled during this test.");
   });
 
   reload(target);
-  let [firstProgramActor, secondProgramActor] = yield promise.all([
-    getPrograms(gFront, 2),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]).then(([programs, ]) => programs);
+  let firstProgramActor = yield once(gFront, "program-linked");
+  let secondProgramActor = yield once(gFront, "program-linked");
 
   let vsEditor = yield ShadersEditorsView._getEditor("vs");
   let fsEditor = yield ShadersEditorsView._getEditor("fs");
 
   vsEditor.once("change", () => {
     ok(false, "The vertex shader source was unexpectedly changed.");
   });
   fsEditor.once("change", () => {
@@ -86,8 +84,14 @@ function getItemLabel(aPanel, aIndex) {
   return aPanel.panelWin.document.querySelectorAll(
     ".side-menu-widget-item-label")[aIndex];
 }
 
 function getBlackBoxCheckbox(aPanel, aIndex) {
   return aPanel.panelWin.document.querySelectorAll(
     ".side-menu-widget-item-checkbox")[aIndex];
 }
+
+function once(aTarget, aEvent) {
+  let deferred = promise.defer();
+  aTarget.once(aEvent, deferred.resolve);
+  return deferred.promise;
+}
--- a/browser/devtools/shadereditor/test/browser_se_programs-highlight-02.js
+++ b/browser/devtools/shadereditor/test/browser_se_programs-highlight-02.js
@@ -6,20 +6,18 @@
  * overlapping geometry.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(BLENDED_GEOMETRY_CANVAS_URL);
   let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
 
   reload(target);
-  let [firstProgramActor, secondProgramActor] = yield promise.all([
-    getPrograms(gFront, 2),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]).then(([programs, ]) => programs);
+  let firstProgramActor = yield once(gFront, "program-linked");
+  let secondProgramActor = yield once(gFront, "program-linked");
 
   yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 127, g: 127, b: 127, a: 255 }, true);
   yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 127, b: 127, a: 127 }, true);
   ok(true, "The canvas was correctly drawn.");
 
   ShadersListView._onProgramMouseEnter({ target: getItemLabel(panel, 0) });
 
   yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 127, g: 0, b: 32, a: 255 }, true);
@@ -42,8 +40,14 @@ function ifWebGLSupported() {
   yield teardown(panel);
   finish();
 }
 
 function getItemLabel(aPanel, aIndex) {
   return aPanel.panelWin.document.querySelectorAll(
     ".side-menu-widget-item-label")[aIndex];
 }
+
+function once(aTarget, aEvent) {
+  let deferred = promise.defer();
+  aTarget.once(aEvent, deferred.resolve);
+  return deferred.promise;
+}
--- a/browser/devtools/shadereditor/test/browser_se_programs-list.js
+++ b/browser/devtools/shadereditor/test/browser_se_programs-list.js
@@ -14,27 +14,33 @@ function ifWebGLSupported() {
     "The shaders list should initially be empty.");
   is(ShadersListView.selectedItem, null,
     "The shaders list has no selected item.");
   is(ShadersListView.selectedIndex, -1,
     "The shaders list has a negative index.");
 
   reload(target);
 
-  let [firstProgramActor, secondProgramActor] = yield promise.all([
-    getPrograms(gFront, 2, (actors) => {
-      // Fired upon each actor addition, we want to check only
-      // after the first actor has been added so we can test state
-      if (actors.length === 1)
-        checkFirstProgram();
-      if (actors.length === 2)
-        checkSecondProgram();
-    }),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]).then(([programs, ]) => programs);
+  let firstProgramActor = yield once(gFront, "program-linked");
+
+  is(ShadersListView.itemCount, 1,
+    "The shaders list contains one entry.");
+  is(ShadersListView.selectedItem, ShadersListView.items[0],
+    "The shaders list has a correct item selected.");
+  is(ShadersListView.selectedIndex, 0,
+    "The shaders list has a correct index selected.");
+
+  let secondProgramActor = yield once(gFront, "program-linked");
+
+  is(ShadersListView.itemCount, 2,
+    "The shaders list contains two entries.");
+  is(ShadersListView.selectedItem, ShadersListView.items[0],
+    "The shaders list has a correct item selected.");
+  is(ShadersListView.selectedIndex, 0,
+    "The shaders list has a correct index selected.");
 
   is(ShadersListView.labels[0], L10N.getFormatStr("shadersList.programLabel", 0),
     "The correct first label is shown in the shaders list.");
   is(ShadersListView.labels[1], L10N.getFormatStr("shadersList.programLabel", 1),
     "The correct second label is shown in the shaders list.");
 
   let vertexShader = yield firstProgramActor.getVertexShader();
   let fragmentShader = yield firstProgramActor.getFragmentShader();
@@ -62,26 +68,15 @@ function ifWebGLSupported() {
 
   is(ShadersListView.selectedItem, ShadersListView.items[1],
     "The shaders list has a correct item selected.");
   is(ShadersListView.selectedIndex, 1,
     "The shaders list has a correct index selected.");
 
   yield teardown(panel);
   finish();
+}
 
-  function checkFirstProgram () {
-    is(ShadersListView.itemCount, 1,
-      "The shaders list contains one entry.");
-    is(ShadersListView.selectedItem, ShadersListView.items[0],
-      "The shaders list has a correct item selected.");
-    is(ShadersListView.selectedIndex, 0,
-      "The shaders list has a correct index selected.");
-  }
-  function checkSecondProgram () {
-    is(ShadersListView.itemCount, 2,
-      "The shaders list contains two entries.");
-    is(ShadersListView.selectedItem, ShadersListView.items[0],
-      "The shaders list has a correct item selected.");
-    is(ShadersListView.selectedIndex, 0,
-      "The shaders list has a correct index selected.");
-  }
+function once(aTarget, aEvent) {
+  let deferred = promise.defer();
+  aTarget.once(aEvent, deferred.resolve);
+  return deferred.promise;
 }
--- a/browser/devtools/shadereditor/test/browser_se_shaders-edit-01.js
+++ b/browser/devtools/shadereditor/test/browser_se_shaders-edit-01.js
@@ -5,20 +5,17 @@
  * Tests if editing a vertex and a fragment shader works properly.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
   let { gFront, $, EVENTS, ShadersEditorsView } = panel.panelWin;
 
   reload(target);
-  yield promise.all([
-    once(gFront, "program-linked"),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]);
+  yield once(gFront, "program-linked");
 
   let vsEditor = yield ShadersEditorsView._getEditor("vs");
   let fsEditor = yield ShadersEditorsView._getEditor("fs");
 
   is(vsEditor.getText().indexOf("gl_Position"), 170,
     "The vertex shader editor contains the correct text.");
   is(fsEditor.getText().indexOf("gl_FragColor"), 97,
     "The fragment shader editor contains the correct text.");
@@ -66,8 +63,14 @@ function ifWebGLSupported() {
   yield ensurePixelIs(debuggee, { x: 128, y: 128 }, { r: 255, g: 0, b: 0, a: 127 }, true);
   yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 0, b: 0, a: 255 }, true);
 
   ok(true, "The fragment shader was recompiled successfully.");
 
   yield teardown(panel);
   finish();
 }
+
+function once(aTarget, aEvent) {
+  let deferred = promise.defer();
+  aTarget.once(aEvent, deferred.resolve);
+  return deferred.promise;
+}
--- a/browser/devtools/shadereditor/test/browser_se_shaders-edit-02.js
+++ b/browser/devtools/shadereditor/test/browser_se_shaders-edit-02.js
@@ -6,63 +6,66 @@
  * gets malformed after being edited.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
   let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
 
   reload(target);
-  yield promise.all([
-    once(gFront, "program-linked"),
-    once(panel.panelWin, EVENTS.SOURCES_SHOWN)
-  ]);
+  yield once(gFront, "program-linked");
 
   let vsEditor = yield ShadersEditorsView._getEditor("vs");
   let fsEditor = yield ShadersEditorsView._getEditor("fs");
 
   vsEditor.replaceText("vec3", { line: 7, ch: 22 }, { line: 7, ch: 26 });
-  let [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
+  let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
 
   ok(error,
     "The new vertex shader source was compiled with errors.");
   is(error.compile, "",
     "The compilation status should be empty.");
   isnot(error.link, "",
     "The linkage status should not be empty.");
   is(error.link.split("ERROR").length - 1, 2,
     "The linkage status contains two errors.");
   ok(error.link.contains("ERROR: 0:8: 'constructor'"),
     "A constructor error is contained in the linkage status.");
   ok(error.link.contains("ERROR: 0:8: 'assign'"),
     "An assignment error is contained in the linkage status.");
 
   fsEditor.replaceText("vec4", { line: 2, ch: 14 }, { line: 2, ch: 18 });
-  let [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
+  let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
 
   ok(error,
     "The new fragment shader source was compiled with errors.");
   is(error.compile, "",
     "The compilation status should be empty.");
   isnot(error.link, "",
     "The linkage status should not be empty.");
   is(error.link.split("ERROR").length - 1, 1,
     "The linkage status contains one error.");
   ok(error.link.contains("ERROR: 0:6: 'constructor'"),
     "A constructor error is contained in the linkage status.");
 
   yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
   yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
 
   vsEditor.replaceText("vec4", { line: 7, ch: 22 }, { line: 7, ch: 26 });
-  let [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
+  let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
   ok(!error, "The new vertex shader source was compiled successfully.");
 
   fsEditor.replaceText("vec3", { line: 2, ch: 14 }, { line: 2, ch: 18 });
-  let [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
+  let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
   ok(!error, "The new fragment shader source was compiled successfully.");
 
   yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 0, b: 0, a: 255 }, true);
   yield ensurePixelIs(debuggee, { x: 511, y: 511 }, { r: 0, g: 255, b: 0, a: 255 }, true);
 
   yield teardown(panel);
   finish();
 }
+
+function once(aTarget, aEvent) {
+  let deferred = promise.defer();
+  aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
+  return deferred.promise;
+}
--- a/browser/devtools/shadereditor/test/browser_se_shaders-edit-03.js
+++ b/browser/devtools/shadereditor/test/browser_se_shaders-edit-03.js
@@ -6,23 +6,18 @@
  * their new source on the backend and reshow it in the frontend when required.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, panel] = yield initShaderEditor(MULTIPLE_CONTEXTS_URL);
   let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
 
   reload(target);
-
-  yield promise.all([
-    once(gFront, "program-linked"),
-    once(gFront, "program-linked")
-  ]);
-
-  yield once(panel.panelWin, EVENTS.SOURCES_SHOWN)
+  let firstProgramActor = yield once(gFront, "program-linked");
+  let secondProgramActor = yield once(gFront, "program-linked");
 
   let vsEditor = yield ShadersEditorsView._getEditor("vs");
   let fsEditor = yield ShadersEditorsView._getEditor("fs");
 
   is(ShadersListView.selectedIndex, 0,
     "The first program is currently selected.");
   is(vsEditor.getText().indexOf("1);"), 136,
     "The vertex shader editor contains the correct initial text (1).");
@@ -78,8 +73,14 @@ function ifWebGLSupported() {
   is(vsEditor.getText().indexOf("2.);"), 136,
     "The vertex shader editor contains the correct text (4).");
   is(fsEditor.getText().indexOf(".0);"), 116,
     "The fragment shader editor contains the correct text (4).");
 
   yield teardown(panel);
   finish();
 }
+
+function once(aTarget, aEvent) {
+  let deferred = promise.defer();
+  aTarget.once(aEvent, deferred.resolve);
+  return deferred.promise;
+}
--- a/browser/devtools/shadereditor/test/browser_webgl-actor-test-13.js
+++ b/browser/devtools/shadereditor/test/browser_webgl-actor-test-13.js
@@ -4,17 +4,18 @@
 /**
  * Tests if multiple WebGL contexts are correctly handled.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, front] = yield initBackend(MULTIPLE_CONTEXTS_URL);
   front.setup({ reload: true });
 
-  let [firstProgramActor, secondProgramActor] = yield getPrograms(front, 2);
+  let firstProgramActor = yield once(front, "program-linked");
+  let secondProgramActor = yield once(front, "program-linked");
 
   isnot(firstProgramActor, secondProgramActor,
     "Two distinct program actors were recevide from two separate contexts.");
 
   let firstVertexShader = yield firstProgramActor.getVertexShader();
   let firstFragmentShader = yield firstProgramActor.getFragmentShader();
   let secondVertexShader = yield secondProgramActor.getVertexShader();
   let secondFragmentShader = yield secondProgramActor.getFragmentShader();
--- a/browser/devtools/shadereditor/test/browser_webgl-actor-test-14.js
+++ b/browser/devtools/shadereditor/test/browser_webgl-actor-test-14.js
@@ -5,18 +5,18 @@
  * Tests that the rendering is updated when a uniform variable is
  * changed in one shader of a page with multiple WebGL contexts.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, front] = yield initBackend(MULTIPLE_CONTEXTS_URL);
   front.setup({ reload: true });
 
-  let [firstProgramActor, secondProgramActor] = yield getPrograms(front, 2);
-
+  let firstProgramActor = yield once(front, "program-linked");
+  let secondProgramActor = yield once(front, "program-linked");
   let firstFragmentShader = yield firstProgramActor.getFragmentShader();
   let secondFragmentShader = yield secondProgramActor.getFragmentShader();
 
   let oldFragSource = yield firstFragmentShader.getText();
   let newFragSource = oldFragSource.replace("vec4(uColor", "vec4(0.25, 0.25, 0.25");
   let status = yield firstFragmentShader.compile(newFragSource);
   ok(!status,
     "The first new fragment shader source was compiled without errors.");
--- a/browser/devtools/shadereditor/test/browser_webgl-actor-test-15.js
+++ b/browser/devtools/shadereditor/test/browser_webgl-actor-test-15.js
@@ -11,17 +11,18 @@ function ifWebGLSupported() {
 
   reload(target);
   let firstProgram = yield once(front, "program-linked");
   yield checkFirstCachedPrograms(firstProgram);
   yield checkHighlightingInTheFirstPage(firstProgram);
   ok(true, "The cached programs behave correctly before the navigation.");
 
   navigate(target, MULTIPLE_CONTEXTS_URL);
-  let [secondProgram, thirdProgram] = yield getPrograms(front, 2);
+  let secondProgram = yield once(front, "program-linked");
+  let thirdProgram = yield once(front, "program-linked");
   yield checkSecondCachedPrograms(firstProgram, [secondProgram, thirdProgram]);
   yield checkHighlightingInTheSecondPage(secondProgram, thirdProgram);
   ok(true, "The cached programs behave correctly after the navigation.");
 
   once(front, "program-linked").then(() => {
     ok(false, "Shouldn't have received any more program-linked notifications.");
   });
 
--- a/browser/devtools/shadereditor/test/browser_webgl-actor-test-16.js
+++ b/browser/devtools/shadereditor/test/browser_webgl-actor-test-16.js
@@ -18,17 +18,18 @@ function ifWebGLSupported() {
   is(programs.length, 1,
     "The first program should be returned by a call to getPrograms().");
   is(programs[0], firstProgram,
     "The first programs was correctly retrieved from the cache.");
 
   // 1. Perform a simple navigation.
 
   navigate(target, MULTIPLE_CONTEXTS_URL);
-  let [secondProgram, thirdProgram] = yield getPrograms(front, 2);
+  let secondProgram = yield once(front, "program-linked");
+  let thirdProgram = yield once(front, "program-linked");
   let programs = yield front.getPrograms();
   is(programs.length, 2,
     "The second and third programs should be returned by a call to getPrograms().");
   is(programs[0], secondProgram,
     "The second programs was correctly retrieved from the cache.");
   is(programs[1], thirdProgram,
     "The third programs was correctly retrieved from the cache.");
 
@@ -59,17 +60,18 @@ function ifWebGLSupported() {
   let globalCreated = observe("content-document-global-created");
   reload(target);
 
   yield globalDestroyed;
   let programs = yield front.getPrograms();
   is(programs.length, 0,
     "There should be no cached program actors yet.");
 
-  yield getPrograms(front, 2);
+  yield once(front, "program-linked");
+  yield once(front, "program-linked");
   yield globalCreated;
   let programs = yield front.getPrograms();
   is(programs.length, 2,
     "There should be 2 cached program actors now.");
 
   yield checkHighlightingInTheSecondPage(programs[0], programs[1]);
   ok(true, "The cached programs behave correctly after navigating forward and reloading.");
 
--- a/browser/devtools/shadereditor/test/browser_webgl-actor-test-17.js
+++ b/browser/devtools/shadereditor/test/browser_webgl-actor-test-17.js
@@ -5,17 +5,18 @@
  * Tests that the blackbox/unblackbox operations work as expected with
  * overlapping geometry.
  */
 
 function ifWebGLSupported() {
   let [target, debuggee, front] = yield initBackend(OVERLAPPING_GEOMETRY_CANVAS_URL);
   front.setup({ reload: true });
 
-  let [firstProgramActor, secondProgramActor] = yield getPrograms(front, 2);
+  let firstProgramActor = yield once(front, "program-linked");
+  let secondProgramActor = yield once(front, "program-linked");
 
   yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 255, g: 255, b: 0, a: 255 }, true);
   yield ensurePixelIs(debuggee, { x: 64, y: 64 }, { r: 0, g: 255, b: 255, a: 255 }, true);
   yield ensurePixelIs(debuggee, { x: 127, y: 127 }, { r: 255, g: 255, b: 0, a: 255 }, true);
   ok(true, "The corner vs. center pixel colors are correct before blackboxing.");
 
   yield firstProgramActor.blackbox();
   yield ensurePixelIs(debuggee, { x: 0, y: 0 }, { r: 0, g: 0, b: 0, a: 255 }, true);
--- a/browser/devtools/shadereditor/test/head.js
+++ b/browser/devtools/shadereditor/test/head.js
@@ -7,17 +7,17 @@ const { classes: Cc, interfaces: Ci, uti
 let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
 
 // Enable logging for all the tests. Both the debugger server and frontend will
 // be affected by this pref.
 let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
 Services.prefs.setBoolPref("devtools.debugger.log", true);
 
 let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
-let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
+let { Promise: promise } = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
 let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
 let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
 let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
 let { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
 
 let { WebGLFront } = devtools.require("devtools/server/actors/webgl");
 let TiltGL = devtools.require("devtools/tilt/tilt-gl");
 let TargetFactory = devtools.TargetFactory;
@@ -119,42 +119,32 @@ function isWebGLSupported() {
 }
 
 function once(aTarget, aEventName, aUseCapture = false) {
   info("Waiting for event: '" + aEventName + "' on " + aTarget + ".");
 
   let deferred = promise.defer();
 
   for (let [add, remove] of [
-    ["on", "off"], // Use event emitter before DOM events for consistency
     ["addEventListener", "removeEventListener"],
-    ["addListener", "removeListener"]
+    ["addListener", "removeListener"],
+    ["on", "off"]
   ]) {
     if ((add in aTarget) && (remove in aTarget)) {
       aTarget[add](aEventName, function onEvent(...aArgs) {
         aTarget[remove](aEventName, onEvent, aUseCapture);
-        deferred.resolve(...aArgs);
+        deferred.resolve.apply(deferred, aArgs);
       }, aUseCapture);
       break;
     }
   }
 
   return deferred.promise;
 }
 
-// Hack around `once`, as that only resolves to a single (first) argument
-// and discards the rest. `onceSpread` is similar, except resolves to an
-// array of all of the arguments in the handler. These should be consolidated
-// into the same function, but many tests will need to be changed.
-function onceSpread(aTarget, aEvent) {
-  let deferred = promise.defer();
-  aTarget.once(aEvent, (...args) => deferred.resolve(args));
-  return deferred.promise;
-}
-
 function observe(aNotificationName, aOwnsWeak = false) {
   info("Waiting for observer notification: '" + aNotificationName + ".");
 
   let deferred = promise.defer();
 
   Services.obs.addObserver(function onNotification(...aArgs) {
     Services.obs.removeObserver(onNotification, aNotificationName);
     deferred.resolve.apply(deferred, aArgs);
@@ -278,32 +268,8 @@ function initShaderEditor(aUrl) {
 function teardown(aPanel) {
   info("Destroying the specified shader editor.");
 
   return promise.all([
     once(aPanel, "destroyed"),
     removeTab(aPanel.target.tab)
   ]);
 }
-
-// Due to `program-linked` events firing synchronously, we cannot
-// just yield/chain them together, as then we miss all actors after the
-// first event since they're fired consecutively. This allows us to capture
-// all actors and returns an array containing them.
-//
-// Takes a `front` object that is an event emitter, the number of
-// programs that should be listened to and waited on, and an optional
-// `onAdd` function that calls with the entire actors array on program link
-function getPrograms(front, count, onAdd) {
-  let actors = [];
-  let deferred = promise.defer();
-  front.on("program-linked", function onLink (actor) {
-    if (actors.length !== count) {
-      actors.push(actor);
-      if (typeof onAdd === 'function') onAdd(actors)
-    }
-    if (actors.length === count) {
-      front.off("program-linked", onLink);
-      deferred.resolve(actors);
-    }
-  });
-  return deferred.promise;
-}