mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 876277 - Rewrite head.js to use promises and remove useless cruft, r=past
This commit is contained in:
parent
a33ccba979
commit
a0d28d5edf
@ -1714,12 +1714,6 @@ DebuggerController.Breakpoints = new Breakpoints();
|
|||||||
* Export some properties to the global scope for easier access.
|
* Export some properties to the global scope for easier access.
|
||||||
*/
|
*/
|
||||||
Object.defineProperties(window, {
|
Object.defineProperties(window, {
|
||||||
"dispatchEvent": {
|
|
||||||
get: function() ViewHelpers.dispatchEvent,
|
|
||||||
},
|
|
||||||
"editor": {
|
|
||||||
get: function() DebuggerView.editor
|
|
||||||
},
|
|
||||||
"gTarget": {
|
"gTarget": {
|
||||||
get: function() DebuggerController._target
|
get: function() DebuggerController._target
|
||||||
},
|
},
|
||||||
@ -1729,18 +1723,6 @@ Object.defineProperties(window, {
|
|||||||
"gThreadClient": {
|
"gThreadClient": {
|
||||||
get: function() DebuggerController.activeThread
|
get: function() DebuggerController.activeThread
|
||||||
},
|
},
|
||||||
"gThreadState": {
|
|
||||||
get: function() DebuggerController.ThreadState
|
|
||||||
},
|
|
||||||
"gStackFrames": {
|
|
||||||
get: function() DebuggerController.StackFrames
|
|
||||||
},
|
|
||||||
"gSourceScripts": {
|
|
||||||
get: function() DebuggerController.SourceScripts
|
|
||||||
},
|
|
||||||
"gBreakpoints": {
|
|
||||||
get: function() DebuggerController.Breakpoints
|
|
||||||
},
|
|
||||||
"gCallStackPageSize": {
|
"gCallStackPageSize": {
|
||||||
get: function() CALL_STACK_PAGE_SIZE
|
get: function() CALL_STACK_PAGE_SIZE
|
||||||
}
|
}
|
||||||
|
@ -2,48 +2,45 @@
|
|||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const Cc = Components.classes;
|
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||||
const Ci = Components.interfaces;
|
|
||||||
const Cu = Components.utils;
|
let { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
|
||||||
|
|
||||||
let tempScope = {};
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm", tempScope);
|
|
||||||
let Services = tempScope.Services;
|
|
||||||
// Disable logging for faster test runs. Set this pref to true if you want to
|
// Disable logging for faster test runs. Set this pref to true if you want to
|
||||||
// debug a test in your try runs.
|
// debug a test in your try runs. Both the debugger server and frontend will
|
||||||
|
// be affected by this pref.
|
||||||
let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
let gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log");
|
||||||
Services.prefs.setBoolPref("devtools.debugger.log", false);
|
Services.prefs.setBoolPref("devtools.debugger.log", false);
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/devtools/dbg-server.jsm", tempScope);
|
let { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
|
||||||
Cu.import("resource://gre/modules/devtools/dbg-client.jsm", tempScope);
|
let { Promise: promise } = Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js", {});
|
||||||
Cu.import("resource:///modules/source-editor.jsm", tempScope);
|
let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {});
|
||||||
Cu.import("resource:///modules/devtools/gDevTools.jsm", tempScope);
|
let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});
|
||||||
Cu.import("resource://gre/modules/devtools/Loader.jsm", tempScope);
|
let { BrowserDebuggerProcess } = Cu.import("resource:///modules/devtools/DebuggerProcess.jsm", {});
|
||||||
Cu.import("resource://gre/modules/AddonManager.jsm", tempScope);
|
let { DebuggerServer } = Cu.import("resource://gre/modules/devtools/dbg-server.jsm", {});
|
||||||
let SourceEditor = tempScope.SourceEditor;
|
let { DebuggerClient } = Cu.import("resource://gre/modules/devtools/dbg-client.jsm", {});
|
||||||
let DebuggerServer = tempScope.DebuggerServer;
|
let { SourceEditor } = Cu.import("resource:///modules/source-editor.jsm", {});
|
||||||
let DebuggerTransport = tempScope.DebuggerTransport;
|
let { AddonManager } = Cu.import("resource://gre/modules/AddonManager.jsm", {});
|
||||||
let DebuggerClient = tempScope.DebuggerClient;
|
|
||||||
let AddonManager = tempScope.AddonManager;
|
|
||||||
let gDevTools = tempScope.gDevTools;
|
|
||||||
let devtools = tempScope.devtools;
|
|
||||||
let TargetFactory = devtools.TargetFactory;
|
let TargetFactory = devtools.TargetFactory;
|
||||||
|
let Toolbox = devtools.Toolbox;
|
||||||
|
|
||||||
|
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/debugger/test/";
|
||||||
|
|
||||||
|
// All tests are asynchronous.
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
registerCleanupFunction(function() {
|
||||||
|
info("finish() was called, cleaning up...");
|
||||||
|
Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
|
||||||
|
|
||||||
|
// Properly shut down the server to avoid memory leaks.
|
||||||
|
DebuggerServer.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
// Import the GCLI test helper
|
// Import the GCLI test helper
|
||||||
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
|
let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
|
||||||
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
|
Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
|
||||||
|
|
||||||
const EXAMPLE_URL = "http://example.com/browser/browser/devtools/debugger/test/";
|
|
||||||
const TAB1_URL = EXAMPLE_URL + "browser_dbg_tab1.html";
|
|
||||||
const TAB2_URL = EXAMPLE_URL + "browser_dbg_tab2.html";
|
|
||||||
const ADDON1_URL = EXAMPLE_URL + "browser_dbg_addon1.xpi";
|
|
||||||
const ADDON2_URL = EXAMPLE_URL + "browser_dbg_addon2.xpi";
|
|
||||||
const STACK_URL = EXAMPLE_URL + "browser_dbg_stack.html";
|
|
||||||
|
|
||||||
// Enable remote debugging for the relevant tests.
|
|
||||||
let gEnableRemote = Services.prefs.getBoolPref("devtools.debugger.remote-enabled");
|
|
||||||
Services.prefs.setBoolPref("devtools.debugger.remote-enabled", true);
|
|
||||||
|
|
||||||
// Redeclare dbg_assert with a fatal behavior.
|
// Redeclare dbg_assert with a fatal behavior.
|
||||||
function dbg_assert(cond, e) {
|
function dbg_assert(cond, e) {
|
||||||
if (!cond) {
|
if (!cond) {
|
||||||
@ -51,197 +48,461 @@ function dbg_assert(cond, e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
registerCleanupFunction(function() {
|
function addWindow(aUrl) {
|
||||||
Services.prefs.setBoolPref("devtools.debugger.remote-enabled", gEnableRemote);
|
info("Adding window: " + aUrl);
|
||||||
Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging);
|
return promise.resolve(getDOMWindow(window.open(aUrl)));
|
||||||
|
|
||||||
// Properly shut down the server to avoid memory leaks.
|
|
||||||
DebuggerServer.destroy();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!DebuggerServer.initialized) {
|
|
||||||
DebuggerServer.init(function() true);
|
|
||||||
DebuggerServer.addBrowserActors();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForExplicitFinish();
|
function getDOMWindow(aReference) {
|
||||||
|
return aReference
|
||||||
function addWindow() {
|
|
||||||
let windowReference = window.open();
|
|
||||||
let chromeWindow = windowReference
|
|
||||||
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
|
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation)
|
||||||
.QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem
|
.QueryInterface(Ci.nsIDocShellTreeItem).rootTreeItem
|
||||||
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
|
.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
|
||||||
|
|
||||||
return chromeWindow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addTab(aURL, aOnload, aWindow) {
|
function addTab(aUrl, aWindow) {
|
||||||
|
info("Adding tab: " + aUrl);
|
||||||
|
|
||||||
|
let deferred = promise.defer();
|
||||||
let targetWindow = aWindow || window;
|
let targetWindow = aWindow || window;
|
||||||
let targetBrowser = targetWindow.gBrowser;
|
let targetBrowser = targetWindow.gBrowser;
|
||||||
|
|
||||||
targetWindow.focus();
|
targetWindow.focus();
|
||||||
targetBrowser.selectedTab = targetBrowser.addTab(aURL);
|
let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl);
|
||||||
|
let linkedBrowser = tab.linkedBrowser;
|
||||||
|
|
||||||
let tab = targetBrowser.selectedTab;
|
linkedBrowser.addEventListener("load", function onLoad() {
|
||||||
let browser = tab.linkedBrowser;
|
linkedBrowser.removeEventListener("load", onLoad, true);
|
||||||
let win = browser.contentWindow;
|
deferred.resolve(tab);
|
||||||
let expectedReadyState = aURL == "about:blank" ? ["interactive", "complete"] : ["complete"];
|
}, true);
|
||||||
|
|
||||||
if (aOnload) {
|
return deferred.promise;
|
||||||
let handler = function() {
|
|
||||||
if (browser.currentURI.spec != aURL ||
|
|
||||||
expectedReadyState.indexOf((win.document || {}).readyState) == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
browser.removeEventListener("load", handler, true);
|
|
||||||
executeSoon(aOnload);
|
|
||||||
}
|
|
||||||
browser.addEventListener("load", handler, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return tab;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeTab(aTab, aWindow) {
|
function removeTab(aTab, aWindow) {
|
||||||
|
info("Removing tab.");
|
||||||
|
|
||||||
|
let deferred = promise.defer();
|
||||||
let targetWindow = aWindow || window;
|
let targetWindow = aWindow || window;
|
||||||
let targetBrowser = targetWindow.gBrowser;
|
let targetBrowser = targetWindow.gBrowser;
|
||||||
|
let tabContainer = targetBrowser.tabContainer;
|
||||||
|
|
||||||
|
tabContainer.addEventListener("TabClose", function onClose(aEvent) {
|
||||||
|
tabContainer.removeEventListener("TabClose", onClose, false);
|
||||||
|
deferred.resolve();
|
||||||
|
}, false);
|
||||||
|
|
||||||
targetBrowser.removeTab(aTab);
|
targetBrowser.removeTab(aTab);
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addAddon(aURL, aOnInstallEnded) {
|
function addAddon(aUrl) {
|
||||||
AddonManager.getInstallForURL(aURL, function(aInstall) {
|
info("Installing addon: " + aUrl);
|
||||||
aInstall.install();
|
|
||||||
var listener = {
|
let deferred = promise.defer();
|
||||||
|
|
||||||
|
AddonManager.getInstallForURL(aUrl, aInstaller => {
|
||||||
|
aInstaller.install();
|
||||||
|
let listener = {
|
||||||
onInstallEnded: function(aAddon, aAddonInstall) {
|
onInstallEnded: function(aAddon, aAddonInstall) {
|
||||||
aInstall.removeListener(listener);
|
aInstaller.removeListener(listener);
|
||||||
aOnInstallEnded(aAddonInstall);
|
deferred.resolve(aAddonInstall);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
aInstall.addListener(listener);
|
aInstaller.addListener(listener);
|
||||||
}, "application/x-xpinstall");
|
}, "application/x-xpinstall");
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeAddon(aAddon, aOnUninstalled) {
|
function removeAddon(aAddon) {
|
||||||
var listener = {
|
info("Removing addon.");
|
||||||
|
|
||||||
|
let deferred = promise.defer();
|
||||||
|
|
||||||
|
let listener = {
|
||||||
onUninstalled: function(aUninstalledAddon) {
|
onUninstalled: function(aUninstalledAddon) {
|
||||||
if (aUninstalledAddon != aAddon)
|
if (aUninstalledAddon != aAddon) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
AddonManager.removeAddonListener(listener);
|
AddonManager.removeAddonListener(listener);
|
||||||
aOnUninstalled();
|
deferred.resolve();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
AddonManager.addAddonListener(listener);
|
AddonManager.addAddonListener(listener);
|
||||||
aAddon.uninstall();
|
aAddon.uninstall();
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDebuggerAndFinish(aRemoteFlag, aCallback, aWindow) {
|
function getTabActorForUrl(aClient, aUrl) {
|
||||||
let debuggerClosed = false;
|
let deferred = promise.defer();
|
||||||
let debuggerDisconnected = false;
|
|
||||||
|
|
||||||
ok(gTab, "There is a gTab to use for getting a toolbox reference");
|
aClient.listTabs(aResponse => {
|
||||||
let target = TargetFactory.forTab(gTab);
|
let tabActor = aResponse.tabs.filter(aGrip => aGrip.url == aUrl).pop();
|
||||||
|
deferred.resolve(tabActor);
|
||||||
window.addEventListener("Debugger:Shutdown", function cleanup() {
|
|
||||||
window.removeEventListener("Debugger:Shutdown", cleanup, false);
|
|
||||||
debuggerDisconnected = true;
|
|
||||||
maybeFinish();
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
let toolbox = gDevTools.getToolbox(target);
|
|
||||||
toolbox.destroy().then(function() {
|
|
||||||
debuggerClosed = true;
|
|
||||||
maybeFinish();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function maybeFinish() {
|
return deferred.promise;
|
||||||
if (debuggerClosed && debuggerDisconnected) {
|
|
||||||
(finish || aCallback)();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_tab_actor_for_url(aClient, aURL, aCallback) {
|
function getAddonActorForUrl(aClient, aUrl) {
|
||||||
aClient.listTabs(function(aResponse) {
|
let deferred = promise.defer();
|
||||||
for each (let tab in aResponse.tabs) {
|
|
||||||
if (tab.url == aURL) {
|
aClient.listAddons(aResponse => {
|
||||||
aCallback(tab);
|
let addonActor = aResponse.addons.filter(aGrip => aGrip.url == aUrl).pop();
|
||||||
return;
|
deferred.resolve(addonActor);
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function attach_tab_actor_for_url(aClient, aURL, aCallback) {
|
function attachTabActorForUrl(aClient, aUrl) {
|
||||||
get_tab_actor_for_url(aClient, aURL, function(actor) {
|
let deferred = promise.defer();
|
||||||
aClient.attachTab(actor.actor, function(aResponse) {
|
|
||||||
aCallback(actor, aResponse);
|
getTabActorForUrl(aClient, aUrl).then(aGrip => {
|
||||||
|
aClient.attachTab(aGrip.actor, aResponse => {
|
||||||
|
deferred.resolve([aGrip, aResponse]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function attach_thread_actor_for_url(aClient, aURL, aCallback) {
|
function attachThreadActorForUrl(aClient, aUrl) {
|
||||||
attach_tab_actor_for_url(aClient, aURL, function(aTabActor, aResponse) {
|
let deferred = promise.defer();
|
||||||
aClient.attachThread(aResponse.threadActor, function(aResponse, aThreadClient) {
|
|
||||||
// We don't care about the pause right now (use
|
attachTabActorForUrl(aClient, aUrl).then(([aGrip, aResponse]) => {
|
||||||
// get_actor_for_url() if you do), so resume it.
|
aClient.attachThread(aResponse.threadActor, (aResponse, aThreadClient) => {
|
||||||
aThreadClient.resume(function(aResponse) {
|
aThreadClient.resume(aResponse => {
|
||||||
aCallback(aThreadClient);
|
deferred.resolve(aThreadClient);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function wait_for_connect_and_resume(aOnDebugging, aTab) {
|
function once(aTarget, aEventName, aUseCapture = false) {
|
||||||
let target = TargetFactory.forTab(aTab);
|
info("Waiting for event: '" + aEventName + "' on " + aTarget + ".");
|
||||||
|
|
||||||
gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
|
let deferred = promise.defer();
|
||||||
let dbg = toolbox.getCurrentPanel();
|
|
||||||
|
|
||||||
// Wait for the initial resume...
|
for (let [add, remove] of [
|
||||||
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
|
["addEventListener", "removeEventListener"],
|
||||||
aOnDebugging();
|
["addListener", "removeListener"],
|
||||||
});
|
["on", "off"]
|
||||||
|
]) {
|
||||||
|
if ((add in aTarget) && (remove in aTarget)) {
|
||||||
|
aTarget[add](aEventName, function onEvent(...aArgs) {
|
||||||
|
aTarget[remove](aEventName, onEvent, aUseCapture);
|
||||||
|
deferred.resolve.apply(deferred, aArgs);
|
||||||
|
}, aUseCapture);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForSourceShown(aPanel, aUrl) {
|
||||||
|
return waitForDebuggerEvents(aPanel, aPanel.panelWin.EVENTS.SOURCE_SHOWN).then(aSource => {
|
||||||
|
let sourceUrl = aSource.url;
|
||||||
|
info("Source shown: " + sourceUrl);
|
||||||
|
|
||||||
|
if (!sourceUrl.contains(aUrl)) {
|
||||||
|
return waitForSourceShown(aPanel, aUrl);
|
||||||
|
} else {
|
||||||
|
ok(true, "The correct source has been shown.");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function debug_tab_pane(aURL, aOnDebugging, aBeforeTabAdded) {
|
function ensureSourceIs(aPanel, aUrl, aWaitFlag = false) {
|
||||||
// Make any necessary preparations (start the debugger server etc.)
|
if (aPanel.panelWin.DebuggerView.Sources.selectedValue.contains(aUrl)) {
|
||||||
if (aBeforeTabAdded) {
|
ok(true, "Expected source is shown: " + aUrl);
|
||||||
aBeforeTabAdded();
|
return promise.resolve(null);
|
||||||
}
|
}
|
||||||
|
if (aWaitFlag) {
|
||||||
|
return waitForSourceShown(aPanel, aUrl);
|
||||||
|
}
|
||||||
|
ok(false, "Expected source was not already shown: " + aUrl);
|
||||||
|
return promise.reject(null);
|
||||||
|
}
|
||||||
|
|
||||||
let tab = addTab(aURL, function() {
|
function waitForCaretUpdated(aPanel, aLine, aCol = 1) {
|
||||||
let debuggee = gBrowser.selectedTab.linkedBrowser.contentWindow.wrappedJSObject;
|
return waitForEditorEvents(aPanel, SourceEditor.EVENTS.SELECTION).then(() => {
|
||||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
let caret = aPanel.panelWin.DebuggerView.editor.getCaretPosition();
|
||||||
|
info("Caret updated: " + (caret.line + 1) + ", " + (caret.col + 1));
|
||||||
|
|
||||||
info("Opening Debugger");
|
if (!isCaretPos(aPanel, aLine, aCol)) {
|
||||||
gDevTools.showToolbox(target, "jsdebugger").then(function(toolbox) {
|
return waitForCaretUpdated(aPanel, aLine, aCol);
|
||||||
let dbg = toolbox.getCurrentPanel();
|
} else {
|
||||||
|
ok(true, "The correct caret position has been set.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureCaretAt(aPanel, aLine, aCol = 1, aWaitFlag = false) {
|
||||||
|
if (isCaretPos(aPanel, aLine, aCol)) {
|
||||||
|
ok(true, "Expected caret position is set: " + aLine + "," + aCol);
|
||||||
|
return promise.resolve(null);
|
||||||
|
}
|
||||||
|
if (aWaitFlag) {
|
||||||
|
return waitForCaretUpdated(aPanel, aLine, aCol);
|
||||||
|
}
|
||||||
|
ok(false, "Expected caret position was not already set: " + aLine + "," + aCol);
|
||||||
|
return promise.reject(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCaretPos(aPanel, aLine, aCol = 1) {
|
||||||
|
let editor = aPanel.panelWin.DebuggerView.editor;
|
||||||
|
let caret = editor.getCaretPosition();
|
||||||
|
|
||||||
|
// Source editor starts counting line and column numbers from 0.
|
||||||
|
info("Current editor caret position: " + (caret.line + 1) + ", " + (caret.col + 1));
|
||||||
|
return caret.line == (aLine - 1) && caret.col == (aCol - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEditorSel(aPanel, [start, end]) {
|
||||||
|
let editor = aPanel.panelWin.DebuggerView.editor;
|
||||||
|
let range = editor.getSelection();
|
||||||
|
|
||||||
|
// Source editor starts counting line and column numbers from 0.
|
||||||
|
info("Current editor selection: " + (range.start + 1) + ", " + (range.end + 1));
|
||||||
|
return range.start == (start - 1) && range.end == (end - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForSourceAndCaret(aPanel, aUrl, aLine, aCol) {
|
||||||
|
return promise.all([
|
||||||
|
waitForSourceShown(aPanel, aUrl),
|
||||||
|
waitForCaretUpdated(aPanel, aLine, aCol)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForCaretAndScopes(aPanel, aLine, aCol) {
|
||||||
|
return promise.all([
|
||||||
|
waitForCaretUpdated(aPanel, aLine, aCol),
|
||||||
|
waitForDebuggerEvents(aPanel, aPanel.panelWin.EVENTS.FETCHED_SCOPES)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForSourceAndCaretAndScopes(aPanel, aUrl, aLine, aCol) {
|
||||||
|
return promise.all([
|
||||||
|
waitForSourceAndCaret(aPanel, aUrl, aLine, aCol),
|
||||||
|
waitForDebuggerEvents(aPanel, aPanel.panelWin.EVENTS.FETCHED_SCOPES)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForDebuggerEvents(aPanel, aEventName, aEventRepeat = 1) {
|
||||||
|
info("Waiting for debugger event: '" + aEventName + "' to fire: " + aEventRepeat + " time(s).");
|
||||||
|
|
||||||
|
let deferred = promise.defer();
|
||||||
|
let panelWin = aPanel.panelWin;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
panelWin.on(aEventName, function onEvent(aEventName, ...aArgs) {
|
||||||
|
info("Debugger event '" + aEventName + "' fired: " + (++count) + " time(s).");
|
||||||
|
|
||||||
|
if (count == aEventRepeat) {
|
||||||
|
ok(true, "Enough '" + aEventName + "' panel events have been fired.");
|
||||||
|
panelWin.off(aEventName, onEvent);
|
||||||
|
deferred.resolve.apply(deferred, aArgs);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForEditorEvents(aPanel, aEventName, aEventRepeat = 1) {
|
||||||
|
info("Waiting for editor event: '" + aEventName + "' to fire: " + aEventRepeat + " time(s).");
|
||||||
|
|
||||||
|
let deferred = promise.defer();
|
||||||
|
let editor = aPanel.panelWin.DebuggerView.editor;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
editor.addEventListener(aEventName, function onEvent(...aArgs) {
|
||||||
|
info("Editor event '" + aEventName + "' fired: " + (++count) + " time(s).");
|
||||||
|
|
||||||
|
if (count == aEventRepeat) {
|
||||||
|
ok(true, "Enough '" + aEventName + "' editor events have been fired.");
|
||||||
|
editor.removeEventListener(aEventName, onEvent);
|
||||||
|
deferred.resolve.apply(deferred, aArgs);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function waitForThreadEvents(aPanel, aEventName, aEventRepeat = 1) {
|
||||||
|
info("Waiting for thread event: '" + aEventName + "' to fire: " + aEventRepeat + " time(s).");
|
||||||
|
|
||||||
|
let deferred = promise.defer();
|
||||||
|
let thread = aPanel.panelWin.gThreadClient;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
|
thread.addListener(aEventName, function onEvent(aEventName, ...aArgs) {
|
||||||
|
info("Thread event '" + aEventName + "' fired: " + (++count) + " time(s).");
|
||||||
|
|
||||||
|
if (count == aEventRepeat) {
|
||||||
|
ok(true, "Enough '" + aEventName + "' thread events have been fired.");
|
||||||
|
thread.removeListener(aEventName, onEvent);
|
||||||
|
deferred.resolve.apply(deferred, aArgs);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ensureThreadClientState(aPanel, aState) {
|
||||||
|
let thread = aPanel.panelWin.gThreadClient;
|
||||||
|
let state = thread.state;
|
||||||
|
|
||||||
|
info("Thread is: '" + state + "'.");
|
||||||
|
|
||||||
|
if (state == aState) {
|
||||||
|
return promise.resolve(null);
|
||||||
|
} else {
|
||||||
|
return waitForThreadEvents(aPanel, aState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function navigateActiveTabTo(aPanel, aUrl, aWaitForEventName, aEventRepeat) {
|
||||||
|
let finished = waitForDebuggerEvents(aPanel, aWaitForEventName, aEventRepeat);
|
||||||
|
let activeTab = aPanel.panelWin.gClient.activeTab;
|
||||||
|
aUrl ? activeTab.navigateTo(aUrl) : activeTab.reload();
|
||||||
|
return finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
function navigateActiveTabInHistory(aPanel, aDirection, aWaitForEventName, aEventRepeat) {
|
||||||
|
let finished = waitForDebuggerEvents(aPanel, aWaitForEventName, aEventRepeat);
|
||||||
|
content.history[aDirection]();
|
||||||
|
return finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
function reloadActiveTab(aPanel, aWaitForEventName, aEventRepeat) {
|
||||||
|
return navigateActiveTabTo(aPanel, null, aWaitForEventName, aEventRepeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearText(aElement) {
|
||||||
|
info("Clearing text...");
|
||||||
|
aElement.focus();
|
||||||
|
aElement.value = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function setText(aElement, aText) {
|
||||||
|
clearText(aElement);
|
||||||
|
info("Setting text: " + aText);
|
||||||
|
aElement.value = aText;
|
||||||
|
}
|
||||||
|
|
||||||
|
function typeText(aElement, aText) {
|
||||||
|
info("Typing text: " + aText);
|
||||||
|
aElement.focus();
|
||||||
|
EventUtils.sendString(aText, aElement.ownerDocument.defaultView);
|
||||||
|
}
|
||||||
|
|
||||||
|
function backspaceText(aElement, aTimes) {
|
||||||
|
info("Pressing backspace " + aTimes + " times.");
|
||||||
|
for (let i = 0; i < aTimes; i++) {
|
||||||
|
aElement.focus();
|
||||||
|
EventUtils.sendKey("BACK_SPACE", aElement.ownerDocument.defaultView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTab(aTarget) {
|
||||||
|
if (aTarget instanceof XULElement) {
|
||||||
|
return promise.resolve(aTarget);
|
||||||
|
} else {
|
||||||
|
return addTab(aTarget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initDebugger(aTarget, aWindow) {
|
||||||
|
info("Initializing a debugger panel.");
|
||||||
|
|
||||||
|
return getTab(aTarget).then(aTab => {
|
||||||
|
info("Debugee tab added successfully: " + aTarget);
|
||||||
|
|
||||||
|
let deferred = promise.defer();
|
||||||
|
let debuggee = aTab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||||
|
let target = TargetFactory.forTab(aTab);
|
||||||
|
|
||||||
|
gDevTools.showToolbox(target, "jsdebugger").then(aToolbox => {
|
||||||
|
info("Debugger panel shown successfully.");
|
||||||
|
|
||||||
|
let debuggerPanel = aToolbox.getCurrentPanel();
|
||||||
|
let panelWin = debuggerPanel.panelWin;
|
||||||
|
|
||||||
// Wait for the initial resume...
|
// Wait for the initial resume...
|
||||||
dbg.panelWin.gClient.addOneTimeListener("resumed", function() {
|
panelWin.gClient.addOneTimeListener("resumed", () => {
|
||||||
info("Debugger has started");
|
info("Debugger client resumed successfully.");
|
||||||
dbg._view.Variables.lazyEmpty = false;
|
|
||||||
dbg._view.Variables.lazyAppend = false;
|
prepareDebugger(debuggerPanel);
|
||||||
dbg._view.Variables.lazyExpand = false;
|
deferred.resolve([aTab, debuggee, debuggerPanel]);
|
||||||
aOnDebugging(tab, debuggee, dbg);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function debug_chrome(aURL, aOnClosing, aOnDebugging) {
|
function initChromeDebugger(aOnClose) {
|
||||||
let tab = addTab(aURL, function() {
|
info("Initializing a chrome debugger process.");
|
||||||
let debuggee = tab.linkedBrowser.contentWindow.wrappedJSObject;
|
|
||||||
|
|
||||||
info("Opening Browser Debugger");
|
let deferred = promise.defer();
|
||||||
let win = BrowserDebuggerProcess.init(aOnClosing, function(process) {
|
|
||||||
|
|
||||||
// The remote debugging process has started...
|
// Wait for the debugger process to start...
|
||||||
info("Browser Debugger has started");
|
BrowserDebuggerProcess.init(aOnClose, aProcess => {
|
||||||
aOnDebugging(tab, debuggee, process);
|
info("Chrome debugger process started successfully.");
|
||||||
});
|
|
||||||
|
prepareDebugger(aProcess);
|
||||||
|
deferred.resolve(aProcess);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareDebugger(aDebugger) {
|
||||||
|
if ("target" in aDebugger) {
|
||||||
|
let variables = aDebugger.panelWin.DebuggerView.Variables;
|
||||||
|
variables.lazyEmpty = false;
|
||||||
|
variables.lazyAppend = false;
|
||||||
|
variables.lazyExpand = false;
|
||||||
|
variables.lazySearch = false;
|
||||||
|
} else {
|
||||||
|
// Nothing to do here yet.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function teardown(aPanel, aFlags = {}) {
|
||||||
|
info("Destroying the specified debugger.");
|
||||||
|
|
||||||
|
let toolbox = aPanel._toolbox;
|
||||||
|
let tab = aPanel.target.tab;
|
||||||
|
let debuggerRootActorDisconnected = once(window, "Debugger:Shutdown");
|
||||||
|
let debuggerPanelDestroyed = once(aPanel, "destroyed");
|
||||||
|
let devtoolsToolboxDestroyed = toolbox.destroy();
|
||||||
|
|
||||||
|
return promise.all([
|
||||||
|
debuggerRootActorDisconnected,
|
||||||
|
debuggerPanelDestroyed,
|
||||||
|
devtoolsToolboxDestroyed
|
||||||
|
]).then(() => aFlags.noTabRemoval ? null : removeTab(tab));
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeDebuggerAndFinish(aPanel, aFlags = {}) {
|
||||||
|
let thread = aPanel.panelWin.gThreadClient;
|
||||||
|
if (thread.state == "paused" && !aFlags.whilePaused) {
|
||||||
|
ok(false, "You should use 'resumeDebuggerThenCloseAndFinish' instead, " +
|
||||||
|
"unless you're absolutely sure about what you're doing.");
|
||||||
|
}
|
||||||
|
return teardown(aPanel, aFlags).then(finish);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resumeDebuggerThenCloseAndFinish(aPanel, aFlags = {}) {
|
||||||
|
let deferred = promise.defer();
|
||||||
|
let thread = aPanel.panelWin.gThreadClient;
|
||||||
|
thread.resume(() => closeDebuggerAndFinish(aPanel, aFlags).then(deferred.resolve));
|
||||||
|
return deferred.promise;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user