Bug 940541 - Convert shader editor to use Promise.jsm. r=vp, r=benvie

This commit is contained in:
Jordan Santell 2013-12-02 17:08:09 -05:00
Родитель 983b37578f
Коммит e6ddb65707
22 изменённых файлов: 193 добавлений и 155 удалений

Просмотреть файл

@ -6,7 +6,7 @@
"use strict";
const { Cc, Ci, Cu, Cr } = require("chrome");
const promise = require("sdk/core/promise");
const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
const EventEmitter = require("devtools/shared/event-emitter");
const { WebGLFront } = require("devtools/server/actors/webgl");

Просмотреть файл

@ -13,7 +13,7 @@ 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 = require("sdk/core/promise");
const promise = Cu.import("resource://gre/modules/Promise.jsm", {}).Promise;
const EventEmitter = require("devtools/shared/event-emitter");
const {Tooltip} = require("devtools/shared/widgets/Tooltip");
const Editor = require("devtools/sourceeditor/editor");
@ -28,7 +28,13 @@ const EVENTS = {
SOURCES_SHOWN: "ShaderEditor:SourcesShown",
// When a shader's source was edited and compiled via the editor.
SHADER_COMPILED: "ShaderEditor:ShaderCompiled"
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"
};
const STRINGS_URI = "chrome://browser/locale/devtools/shadereditor.properties"
@ -114,15 +120,17 @@ let EventsHandler = {
_onTabNavigated: function(event) {
switch (event) {
case "will-navigate": {
// Make sure the backend is prepared to handle WebGL contexts.
gFront.setup({ reload: false });
Task.spawn(function() {
// Make sure the backend is prepared to handle WebGL contexts.
gFront.setup({ reload: false });
// Reset UI.
ShadersListView.empty();
ShadersEditorsView.setText({ vs: "", fs: "" });
$("#reload-notice").hidden = true;
$("#waiting-notice").hidden = false;
$("#content").hidden = true;
// 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));
break;
}
case "navigate": {
@ -272,13 +280,16 @@ let ShadersListView = Heritage.extend(WidgetMethods, {
]);
}
function showSources([vertexShaderText, fragmentShaderText]) {
ShadersEditorsView.setText({
return ShadersEditorsView.setText({
vs: vertexShaderText,
fs: fragmentShaderText
});
}
getShaders().then(getSources).then(showSources).then(null, Cu.reportError);
getShaders()
.then(getSources)
.then(showSources)
.then(null, Cu.reportError);
},
/**
@ -351,19 +362,24 @@ let ShadersEditorsView = {
* 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();
}
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);
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));
},
/**
@ -372,10 +388,12 @@ let ShadersEditorsView = {
* @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(null);
return promise.reject(new Error("Shader Editor is still waiting for a WebGL context to be created."));
}
if (this._editorPromises.has(type)) {
return this._editorPromises.get(type);
@ -399,14 +417,16 @@ let ShadersEditorsView = {
*
* @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) {
["vs", "fs"].forEach(type => {
this._getEditor(type).then(editor => {
return promise.all(["vs", "fs"].map(type => {
return this._getEditor(type).then(editor => {
editor[flag]("focus", this["_" + type + "Focused"]);
editor[flag]("change", this["_" + type + "Changed"]);
});
});
}));
},
/**
@ -486,7 +506,7 @@ let ShadersEditorsView = {
}
function sanitizeValidMatches(e) {
return {
// Drivers might yield retarded line numbers under some obscure
// Drivers might yield confusing 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,
@ -554,6 +574,7 @@ let ShadersEditorsView = {
editor.removeAllMarkers("errors");
this._errors[type].forEach(e => editor.removeLineClass(e.line));
this._errors[type].length = 0;
window.emit(EVENTS.EDITOR_ERROR_MARKERS_REMOVED);
});
},

Просмотреть файл

@ -14,8 +14,7 @@ function ifWebGLSupported() {
yield reloaded;
let navigated = navigate(target, MULTIPLE_CONTEXTS_URL);
let secondProgram = yield once(gFront, "program-linked");
let thirdProgram = yield once(gFront, "program-linked");
let [secondProgram, thirdProgram] = yield getPrograms(gFront, 2);
yield navigated;
let vsEditor = yield ShadersEditorsView._getEditor("vs");
@ -56,9 +55,3 @@ function ifWebGLSupported() {
yield teardown(panel);
finish();
}
function once(aTarget, aEvent) {
let deferred = promise.defer();
aTarget.once(aEvent, deferred.resolve);
return deferred.promise;
}

Просмотреть файл

@ -8,14 +8,18 @@
function ifWebGLSupported() {
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
let { gFront, ShadersEditorsView } = panel.panelWin;
let { gFront, ShadersEditorsView, EVENTS } = panel.panelWin;
reload(target);
yield once(gFront, "program-linked");
yield promise.all([
once(gFront, "program-linked"),
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
]);
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,

Просмотреть файл

@ -11,55 +11,61 @@ function ifWebGLSupported() {
let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
reload(target);
yield once(gFront, "program-linked");
yield promise.all([
once(gFront, "program-linked"),
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
]);
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 once(panel.panelWin, EVENTS.SHADER_COMPILED);
let [, vertError] = yield onceSpread(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 once(panel.panelWin, EVENTS.SHADER_COMPILED);
let [_, vertError] = yield onceSpread(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 once(panel.panelWin, EVENTS.SHADER_COMPILED);
let [_, fragError] = yield onceSpread(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 once(panel.panelWin, EVENTS.SHADER_COMPILED);
let [_, fragError] = yield onceSpread(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 once(panel.panelWin, EVENTS.SHADER_COMPILED);
let [_, vertError] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
checkHasVertFirstError(true, vertError);
checkHasVertSecondError(true, vertError);
checkHasFragError(true, fragError);
@ -148,9 +154,3 @@ function ifWebGLSupported() {
}
}
}
function once(aTarget, aEvent) {
let deferred = promise.defer();
aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
return deferred.promise;
}

Просмотреть файл

@ -11,7 +11,10 @@ function ifWebGLSupported() {
let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
reload(target);
yield once(gFront, "program-linked");
yield promise.all([
once(gFront, "program-linked"),
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
]);
let vsEditor = yield ShadersEditorsView._getEditor("vs");
let fsEditor = yield ShadersEditorsView._getEditor("fs");
@ -51,9 +54,3 @@ function ifWebGLSupported() {
yield teardown(panel);
finish();
}
function once(aTarget, aEvent) {
let deferred = promise.defer();
aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
return deferred.promise;
}

Просмотреть файл

@ -7,10 +7,13 @@
function ifWebGLSupported() {
let [target, debuggee, panel] = yield initShaderEditor(SIMPLE_CANVAS_URL);
let { gFront, $, ShadersListView, ShadersEditorsView } = panel.panelWin;
let { gFront, $, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
reload(target);
yield once(gFront, "program-linked");
yield promise.all([
once(gFront, "program-linked"),
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
]);
is($("#reload-notice").hidden, true,
"The 'reload this page' notice should be hidden after linking.");
@ -39,6 +42,7 @@ function ifWebGLSupported() {
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.");
@ -54,19 +58,17 @@ function ifWebGLSupported() {
is(ShadersListView.selectedIndex, -1,
"The shaders list has a negative index.");
try {
yield ShadersEditorsView._getEditor("vs");
yield ShadersEditorsView._getEditor("vs").then(() => {
ok(false, "The promise for a vertex shader editor should be rejected.");
} catch (e) {
}, () => {
ok(true, "The vertex shader editors wasn't initialized.");
}
});
try {
yield ShadersEditorsView._getEditor("fs");
yield ShadersEditorsView._getEditor("fs").then(() => {
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;

Просмотреть файл

@ -14,8 +14,10 @@ function ifWebGLSupported() {
});
reload(target);
let firstProgramActor = yield once(gFront, "program-linked");
let secondProgramActor = yield once(gFront, "program-linked");
let [firstProgramActor, secondProgramActor] = yield promise.all([
getPrograms(gFront, 2),
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
]).then(([programs, ]) => programs);
let vsEditor = yield ShadersEditorsView._getEditor("vs");
let fsEditor = yield ShadersEditorsView._getEditor("fs");

Просмотреть файл

@ -11,8 +11,10 @@ function ifWebGLSupported() {
let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
reload(target);
let firstProgramActor = yield once(gFront, "program-linked");
let secondProgramActor = yield once(gFront, "program-linked");
let [firstProgramActor, secondProgramActor] = yield promise.all([
getPrograms(gFront, 2),
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
]).then(([programs, ]) => programs);
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);
@ -59,9 +61,3 @@ 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;
}

Просмотреть файл

@ -7,10 +7,14 @@
function ifWebGLSupported() {
let [target, debuggee, panel] = yield initShaderEditor(MULTIPLE_CONTEXTS_URL);
let { gFront, ShadersListView, ShadersEditorsView } = panel.panelWin;
let { EVENTS, gFront, ShadersListView, ShadersEditorsView } = panel.panelWin;
reload(target);
let programActor = yield once(gFront, "program-linked");
let [programActor, ] = yield promise.all([
getPrograms(gFront, 1),
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
]).then(([programs, ]) => programs);
let programItem = ShadersListView.selectedItem;
is(programItem.attachment.programActor, programActor,

Просмотреть файл

@ -14,8 +14,10 @@ function ifWebGLSupported() {
});
reload(target);
let firstProgramActor = yield once(gFront, "program-linked");
let secondProgramActor = yield once(gFront, "program-linked");
let [firstProgramActor, secondProgramActor] = yield promise.all([
getPrograms(gFront, 2),
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
]).then(([programs, ]) => programs);
let vsEditor = yield ShadersEditorsView._getEditor("vs");
let fsEditor = yield ShadersEditorsView._getEditor("fs");
@ -89,9 +91,3 @@ 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;
}

Просмотреть файл

@ -11,8 +11,10 @@ function ifWebGLSupported() {
let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
reload(target);
let firstProgramActor = yield once(gFront, "program-linked");
let secondProgramActor = yield once(gFront, "program-linked");
let [firstProgramActor, secondProgramActor] = yield promise.all([
getPrograms(gFront, 2),
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
]).then(([programs, ]) => programs);
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);
@ -45,9 +47,3 @@ 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;
}

Просмотреть файл

@ -19,23 +19,17 @@ function ifWebGLSupported() {
reload(target);
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.");
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);
is(ShadersListView.labels[0], L10N.getFormatStr("shadersList.programLabel", 0),
"The correct first label is shown in the shaders list.");
@ -73,10 +67,21 @@ function ifWebGLSupported() {
yield teardown(panel);
finish();
}
function once(aTarget, aEvent) {
let deferred = promise.defer();
aTarget.once(aEvent, deferred.resolve);
return deferred.promise;
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.");
}
}

Просмотреть файл

@ -10,7 +10,10 @@ function ifWebGLSupported() {
let { gFront, $, EVENTS, ShadersEditorsView } = panel.panelWin;
reload(target);
yield once(gFront, "program-linked");
yield promise.all([
once(gFront, "program-linked"),
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
]);
let vsEditor = yield ShadersEditorsView._getEditor("vs");
let fsEditor = yield ShadersEditorsView._getEditor("fs");
@ -68,9 +71,3 @@ function ifWebGLSupported() {
yield teardown(panel);
finish();
}
function once(aTarget, aEvent) {
let deferred = promise.defer();
aTarget.once(aEvent, deferred.resolve);
return deferred.promise;
}

Просмотреть файл

@ -11,13 +11,16 @@ function ifWebGLSupported() {
let { gFront, EVENTS, ShadersEditorsView } = panel.panelWin;
reload(target);
yield once(gFront, "program-linked");
yield promise.all([
once(gFront, "program-linked"),
once(panel.panelWin, EVENTS.SOURCES_SHOWN)
]);
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 once(panel.panelWin, EVENTS.SHADER_COMPILED);
let [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
ok(error,
"The new vertex shader source was compiled with errors.");
@ -33,7 +36,7 @@ function ifWebGLSupported() {
"An assignment error is contained in the linkage status.");
fsEditor.replaceText("vec4", { line: 2, ch: 14 }, { line: 2, ch: 18 });
let error = yield once(panel.panelWin, EVENTS.SHADER_COMPILED);
let [, error] = yield onceSpread(panel.panelWin, EVENTS.SHADER_COMPILED);
ok(error,
"The new fragment shader source was compiled with errors.");
@ -50,11 +53,11 @@ function ifWebGLSupported() {
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 once(panel.panelWin, EVENTS.SHADER_COMPILED);
let [, error] = yield onceSpread(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 once(panel.panelWin, EVENTS.SHADER_COMPILED);
let [, error] = yield onceSpread(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);
@ -63,9 +66,3 @@ function ifWebGLSupported() {
yield teardown(panel);
finish();
}
function once(aTarget, aEvent) {
let deferred = promise.defer();
aTarget.once(aEvent, (aName, aData) => deferred.resolve(aData));
return deferred.promise;
}

Просмотреть файл

@ -11,8 +11,13 @@ function ifWebGLSupported() {
let { gFront, EVENTS, ShadersListView, ShadersEditorsView } = panel.panelWin;
reload(target);
let firstProgramActor = yield once(gFront, "program-linked");
let secondProgramActor = yield once(gFront, "program-linked");
yield promise.all([
once(gFront, "program-linked"),
once(gFront, "program-linked")
]);
yield once(panel.panelWin, EVENTS.SOURCES_SHOWN)
let vsEditor = yield ShadersEditorsView._getEditor("vs");
let fsEditor = yield ShadersEditorsView._getEditor("fs");
@ -78,9 +83,3 @@ function ifWebGLSupported() {
yield teardown(panel);
finish();
}
function once(aTarget, aEvent) {
let deferred = promise.defer();
aTarget.once(aEvent, deferred.resolve);
return deferred.promise;
}

Просмотреть файл

@ -9,8 +9,7 @@ function ifWebGLSupported() {
let [target, debuggee, front] = yield initBackend(MULTIPLE_CONTEXTS_URL);
front.setup({ reload: true });
let firstProgramActor = yield once(front, "program-linked");
let secondProgramActor = yield once(front, "program-linked");
let [firstProgramActor, secondProgramActor] = yield getPrograms(front, 2);
isnot(firstProgramActor, secondProgramActor,
"Two distinct program actors were recevide from two separate contexts.");

Просмотреть файл

@ -10,8 +10,8 @@ function ifWebGLSupported() {
let [target, debuggee, front] = yield initBackend(MULTIPLE_CONTEXTS_URL);
front.setup({ reload: true });
let firstProgramActor = yield once(front, "program-linked");
let secondProgramActor = yield once(front, "program-linked");
let [firstProgramActor, secondProgramActor] = yield getPrograms(front, 2);
let firstFragmentShader = yield firstProgramActor.getFragmentShader();
let secondFragmentShader = yield secondProgramActor.getFragmentShader();

Просмотреть файл

@ -16,8 +16,7 @@ function ifWebGLSupported() {
ok(true, "The cached programs behave correctly before the navigation.");
navigate(target, MULTIPLE_CONTEXTS_URL);
let secondProgram = yield once(front, "program-linked");
let thirdProgram = yield once(front, "program-linked");
let [secondProgram, thirdProgram] = yield getPrograms(front, 2);
yield checkSecondCachedPrograms(firstProgram, [secondProgram, thirdProgram]);
yield checkHighlightingInTheSecondPage(secondProgram, thirdProgram);
ok(true, "The cached programs behave correctly after the navigation.");

Просмотреть файл

@ -23,8 +23,7 @@ function ifWebGLSupported() {
// 1. Perform a simple navigation.
navigate(target, MULTIPLE_CONTEXTS_URL);
let secondProgram = yield once(front, "program-linked");
let thirdProgram = yield once(front, "program-linked");
let [secondProgram, thirdProgram] = yield getPrograms(front, 2);
let programs = yield front.getPrograms();
is(programs.length, 2,
"The second and third programs should be returned by a call to getPrograms().");
@ -65,8 +64,7 @@ function ifWebGLSupported() {
is(programs.length, 0,
"There should be no cached program actors yet.");
yield once(front, "program-linked");
yield once(front, "program-linked");
yield getPrograms(front, 2);
yield globalCreated;
let programs = yield front.getPrograms();
is(programs.length, 2,

Просмотреть файл

@ -10,8 +10,7 @@ function ifWebGLSupported() {
let [target, debuggee, front] = yield initBackend(OVERLAPPING_GEOMETRY_CANVAS_URL);
front.setup({ reload: true });
let firstProgramActor = yield once(front, "program-linked");
let secondProgramActor = yield once(front, "program-linked");
let [firstProgramActor, secondProgramActor] = yield getPrograms(front, 2);
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);

Просмотреть файл

@ -12,7 +12,7 @@ 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/commonjs/sdk/core/promise.js", {});
let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {});
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", {});
@ -124,14 +124,14 @@ function once(aTarget, aEventName, aUseCapture = false) {
let deferred = promise.defer();
for (let [add, remove] of [
["on", "off"], // Use event emitter before DOM events for consistency
["addEventListener", "removeEventListener"],
["addListener", "removeListener"],
["on", "off"]
["addListener", "removeListener"]
]) {
if ((add in aTarget) && (remove in aTarget)) {
aTarget[add](aEventName, function onEvent(...aArgs) {
aTarget[remove](aEventName, onEvent, aUseCapture);
deferred.resolve.apply(deferred, aArgs);
deferred.resolve(...aArgs);
}, aUseCapture);
break;
}
@ -140,6 +140,16 @@ function once(aTarget, aEventName, aUseCapture = false) {
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 + ".");
@ -273,3 +283,27 @@ function teardown(aPanel) {
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;
}